Add unread messages marker
This commit is contained in:
parent
6ca03dcfc8
commit
7f518f7e1e
4 changed files with 229 additions and 71 deletions
39
Cargo.lock
generated
39
Cargo.lock
generated
|
@ -45,6 +45,15 @@ dependencies = [
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aliasable"
|
name = "aliasable"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
@ -473,6 +482,7 @@ dependencies = [
|
||||||
"iced",
|
"iced",
|
||||||
"irc",
|
"irc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"regex",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2085,6 +2095,35 @@ dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "renderdoc-sys"
|
name = "renderdoc-sys"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
|
@ -11,4 +11,5 @@ futures = "0.3.29"
|
||||||
iced = { version = "0.10.0", features = ["tokio"] }
|
iced = { version = "0.10.0", features = ["tokio"] }
|
||||||
irc = "0.15.0"
|
irc = "0.15.0"
|
||||||
once_cell = "1.18.0"
|
once_cell = "1.18.0"
|
||||||
|
regex = "1.10.2"
|
||||||
tokio = { version = "1.33.0", features = ["full"] }
|
tokio = { version = "1.33.0", features = ["full"] }
|
||||||
|
|
156
src/main.rs
156
src/main.rs
|
@ -5,10 +5,11 @@ use crate::{irc_message::IrcMessage, message_log::MessageLog};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use iced::{
|
use iced::{
|
||||||
|
alignment::{Horizontal, Vertical},
|
||||||
executor,
|
executor,
|
||||||
theme::Theme,
|
theme::Theme,
|
||||||
widget::{column, container, mouse_area, row, text, text_input},
|
widget::{column, container, mouse_area, row, text, text_input},
|
||||||
Application, Background, Color, Length, Settings,
|
Application, Background, Color, Element, Length, Settings,
|
||||||
};
|
};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -92,9 +93,6 @@ pub enum UiMessage {
|
||||||
struct Cri {
|
struct Cri {
|
||||||
message_rx: RefCell<Option<UnboundedReceiver<irc::proto::Message>>>,
|
message_rx: RefCell<Option<UnboundedReceiver<irc::proto::Message>>>,
|
||||||
input_tx: RefCell<UnboundedSender<irc::proto::Message>>,
|
input_tx: RefCell<UnboundedSender<irc::proto::Message>>,
|
||||||
|
|
||||||
active_channel: Option<String>,
|
|
||||||
|
|
||||||
message_log: MessageLog,
|
message_log: MessageLog,
|
||||||
input_value: String,
|
input_value: String,
|
||||||
}
|
}
|
||||||
|
@ -110,9 +108,6 @@ impl Application for Cri {
|
||||||
Self {
|
Self {
|
||||||
message_rx: RefCell::new(Some(flags.message_rx)),
|
message_rx: RefCell::new(Some(flags.message_rx)),
|
||||||
input_tx: RefCell::new(flags.input_tx),
|
input_tx: RefCell::new(flags.input_tx),
|
||||||
|
|
||||||
active_channel: None,
|
|
||||||
|
|
||||||
message_log: MessageLog::new(),
|
message_log: MessageLog::new(),
|
||||||
input_value: String::new(),
|
input_value: String::new(),
|
||||||
},
|
},
|
||||||
|
@ -134,15 +129,12 @@ impl Application for Cri {
|
||||||
|
|
||||||
match &message.command {
|
match &message.command {
|
||||||
Command::JOIN(chanlist, _, _) => {
|
Command::JOIN(chanlist, _, _) => {
|
||||||
self.message_log.on_join(chanlist.clone(), &source_nickname);
|
self.message_log.on_join(chanlist, &source_nickname);
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::PART(chanlist, comment) => {
|
Command::PART(chanlist, comment) => {
|
||||||
self.message_log.on_part(
|
self.message_log
|
||||||
chanlist.clone(),
|
.on_part(chanlist, &source_nickname, comment.as_deref());
|
||||||
&source_nickname,
|
|
||||||
comment.as_deref(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::NICK(new) => {
|
Command::NICK(new) => {
|
||||||
|
@ -157,7 +149,7 @@ impl Application for Cri {
|
||||||
Command::PRIVMSG(msgtarget, content) => {
|
Command::PRIVMSG(msgtarget, content) => {
|
||||||
let channel = message.response_target().unwrap_or(msgtarget).to_string();
|
let channel = message.response_target().unwrap_or(msgtarget).to_string();
|
||||||
self.message_log
|
self.message_log
|
||||||
.on_privmsg(channel, &source_nickname, content);
|
.on_privmsg(&channel, &source_nickname, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => self.message_log.on_other(&message.to_string()),
|
_ => self.message_log.on_other(&message.to_string()),
|
||||||
|
@ -165,25 +157,26 @@ impl Application for Cri {
|
||||||
}
|
}
|
||||||
UiMessage::InputChanged(text) => self.input_value = text,
|
UiMessage::InputChanged(text) => self.input_value = text,
|
||||||
UiMessage::InputSubmitted => {
|
UiMessage::InputSubmitted => {
|
||||||
if let Some(active_channel) = &self.active_channel {
|
if let Some(active_channel) = &self.message_log.active_channel {
|
||||||
let command = irc::proto::Command::PRIVMSG(
|
let command = irc::proto::Command::PRIVMSG(
|
||||||
active_channel.to_string(),
|
active_channel.to_string(),
|
||||||
self.input_value.clone(),
|
self.input_value.clone(),
|
||||||
);
|
);
|
||||||
let message: irc::proto::Message = command.into();
|
let message: irc::proto::Message = command.into();
|
||||||
|
|
||||||
self.message_log.get_mut(self.active_channel.clone()).push(
|
self.message_log
|
||||||
IrcMessage::Privmsg {
|
.get_mut(self.message_log.active_channel.clone())
|
||||||
|
.messages
|
||||||
|
.push(IrcMessage::Privmsg {
|
||||||
nickname: String::from("cri"),
|
nickname: String::from("cri"),
|
||||||
message: self.input_value.clone(),
|
message: self.input_value.clone(),
|
||||||
},
|
});
|
||||||
);
|
|
||||||
self.input_tx.borrow().send(message.clone()).unwrap();
|
self.input_tx.borrow().send(message.clone()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.input_value.clear();
|
self.input_value.clear();
|
||||||
}
|
}
|
||||||
UiMessage::HandleChannelPress(channel) => self.active_channel = channel,
|
UiMessage::HandleChannelPress(channel) => self.message_log.set_active(channel),
|
||||||
}
|
}
|
||||||
iced::Command::none()
|
iced::Command::none()
|
||||||
}
|
}
|
||||||
|
@ -202,8 +195,9 @@ impl Application for Cri {
|
||||||
fn view(&self) -> iced::Element<'_, Self::Message, iced::Renderer<Self::Theme>> {
|
fn view(&self) -> iced::Element<'_, Self::Message, iced::Renderer<Self::Theme>> {
|
||||||
let dark_grey = Color::new(0.58, 0.65, 0.65, 1.0);
|
let dark_grey = Color::new(0.58, 0.65, 0.65, 1.0);
|
||||||
let light_blue = Color::new(0.26, 0.62, 0.85, 1.0);
|
let light_blue = Color::new(0.26, 0.62, 0.85, 1.0);
|
||||||
|
let light_red = Color::new(0.99, 0.36, 0.40, 1.0);
|
||||||
|
|
||||||
let log = self.message_log.view(&self.active_channel);
|
let log = self.message_log.view(&self.message_log.active_channel);
|
||||||
|
|
||||||
let message_box = text_input("your magnum opus", &self.input_value)
|
let message_box = text_input("your magnum opus", &self.input_value)
|
||||||
.id(INPUT_ID.clone())
|
.id(INPUT_ID.clone())
|
||||||
|
@ -214,43 +208,113 @@ impl Application for Cri {
|
||||||
self.message_log
|
self.message_log
|
||||||
.get_all()
|
.get_all()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(&ref channel, log)| {
|
.map(|(channel_name, channel)| {
|
||||||
let is_active = &self.active_channel == channel;
|
let is_active = self.message_log.active_channel == **channel_name;
|
||||||
let channel_name = match channel {
|
let label = match channel_name {
|
||||||
None => "Server",
|
None => "Server",
|
||||||
Some(channel) => channel,
|
Some(channel_name) => channel_name,
|
||||||
};
|
};
|
||||||
|
|
||||||
let text_color = if is_active { Some(Color::WHITE) } else { None };
|
let text_color = if is_active { Some(Color::WHITE) } else { None };
|
||||||
let nickname_color = if is_active { Color::WHITE } else { light_blue };
|
let nickname_color = if is_active { Color::WHITE } else { light_blue };
|
||||||
let no_message_color = if is_active { Color::WHITE } else { dark_grey };
|
let no_message_color = if is_active { Color::WHITE } else { dark_grey };
|
||||||
|
|
||||||
let last_message = log
|
let text_size = 14.0;
|
||||||
.iter()
|
let last_message = container(
|
||||||
.rev()
|
channel
|
||||||
.find_map(|m| match m {
|
.messages
|
||||||
IrcMessage::Privmsg { nickname, message } => Some(row![
|
.iter()
|
||||||
text(format!("{nickname}: ")).style(nickname_color),
|
.rev()
|
||||||
text(message)
|
.find_map(|m| -> Option<Element<_, _>> {
|
||||||
]),
|
match m {
|
||||||
_ => None,
|
IrcMessage::Privmsg { nickname, message } => Some(
|
||||||
})
|
row![
|
||||||
.unwrap_or(row![text("No messages").style(no_message_color)]);
|
text(format!("{nickname}: "))
|
||||||
|
.style(nickname_color)
|
||||||
|
.size(text_size),
|
||||||
|
text(message).size(text_size)
|
||||||
|
]
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
IrcMessage::Join { nickname } => Some(
|
||||||
|
row![
|
||||||
|
text(nickname).style(nickname_color).size(text_size),
|
||||||
|
text(" joined").style(no_message_color).size(text_size)
|
||||||
|
]
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or(
|
||||||
|
text(if channel_name.is_some() {
|
||||||
|
"No messages"
|
||||||
|
} else {
|
||||||
|
"Server-related messages"
|
||||||
|
})
|
||||||
|
.style(no_message_color)
|
||||||
|
.size(text_size)
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.padding([2, 0]);
|
||||||
|
|
||||||
let container = container(column![text(channel_name), last_message])
|
let unread_events = channel.unread_events;
|
||||||
|
let unread_messages = channel.unread_messages;
|
||||||
|
let unread_highlights = channel.unread_highlights;
|
||||||
|
let unread_total = unread_events + unread_messages + unread_highlights;
|
||||||
|
|
||||||
|
let unread_indicator = container(
|
||||||
|
container(
|
||||||
|
text(if unread_total > 0 {
|
||||||
|
unread_total.to_string()
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
})
|
||||||
|
.style(Color::WHITE)
|
||||||
|
.size(12),
|
||||||
|
)
|
||||||
|
.width(20)
|
||||||
|
.height(20)
|
||||||
|
.align_x(Horizontal::Center)
|
||||||
|
.align_y(Vertical::Center)
|
||||||
.style(move |_: &_| container::Appearance {
|
.style(move |_: &_| container::Appearance {
|
||||||
background: match is_active {
|
background: Some(Background::Color(if unread_highlights > 0 {
|
||||||
true => Some(Background::Color(light_blue)),
|
light_red
|
||||||
false => None,
|
} else if unread_messages > 0 {
|
||||||
},
|
light_blue
|
||||||
text_color,
|
} else if unread_events > 0 {
|
||||||
|
dark_grey
|
||||||
|
} else {
|
||||||
|
Color::TRANSPARENT
|
||||||
|
})),
|
||||||
|
border_radius: 12.0.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
}),
|
||||||
.padding([4, 4])
|
)
|
||||||
.width(Length::Fill);
|
.padding([4, 4])
|
||||||
|
.align_y(Vertical::Center)
|
||||||
|
.height(Length::Fill);
|
||||||
|
|
||||||
|
let container = container(row![
|
||||||
|
column![text(label), last_message].width(Length::Fill),
|
||||||
|
unread_indicator
|
||||||
|
])
|
||||||
|
.style(move |_: &_| container::Appearance {
|
||||||
|
background: match is_active {
|
||||||
|
true => Some(Background::Color(light_blue)),
|
||||||
|
false => None,
|
||||||
|
},
|
||||||
|
text_color,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.padding([4, 4])
|
||||||
|
.align_y(Vertical::Center)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(54);
|
||||||
|
|
||||||
mouse_area(container)
|
mouse_area(container)
|
||||||
.on_press(UiMessage::HandleChannelPress(channel.clone()))
|
.on_press(UiMessage::HandleChannelPress((*channel_name).clone()))
|
||||||
.into()
|
.into()
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
|
|
|
@ -5,47 +5,78 @@ use iced::{
|
||||||
widget::{column, container, scrollable, text, Container},
|
widget::{column, container, scrollable, text, Container},
|
||||||
Background, Color, Length,
|
Background, Color, Length,
|
||||||
};
|
};
|
||||||
|
use regex::Regex;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub struct MessageLog(HashMap<Option<String>, Vec<IrcMessage>>);
|
#[derive(Default)]
|
||||||
|
pub struct Channel {
|
||||||
|
pub messages: Vec<IrcMessage>,
|
||||||
|
pub unread_messages: i32,
|
||||||
|
pub unread_highlights: i32,
|
||||||
|
pub unread_events: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MessageLog {
|
||||||
|
channels: HashMap<Option<String>, Channel>,
|
||||||
|
pub active_channel: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> MessageLog {
|
impl<'a> MessageLog {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut log = HashMap::new();
|
let mut channels = HashMap::new();
|
||||||
log.insert(None, Vec::new());
|
channels.insert(None, Default::default());
|
||||||
Self(log)
|
Self {
|
||||||
|
channels,
|
||||||
|
active_channel: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all(&'a self) -> Vec<(&'a Option<String>, &'a Vec<IrcMessage>)> {
|
pub fn get_all(&'a self) -> Vec<(&'a Option<String>, &'a Channel)> {
|
||||||
let mut log: Vec<(&Option<String>, &Vec<IrcMessage>)> = self.0.iter().collect();
|
let mut log: Vec<_> = self.channels.iter().collect();
|
||||||
log.sort_unstable_by_key(|(name, _)| name.as_deref());
|
log.sort_unstable_by_key(|(name, _)| name.as_deref());
|
||||||
log
|
log
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, channel: &Option<String>) -> Option<&Vec<IrcMessage>> {
|
pub fn get(&self, channel: &Option<String>) -> Option<&Channel> {
|
||||||
self.0.get(channel)
|
self.channels.get(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mut(&mut self, channel: Option<String>) -> &mut Vec<IrcMessage> {
|
pub fn get_mut(&mut self, channel_name: Option<String>) -> &mut Channel {
|
||||||
self.0.entry(channel).or_insert_with(Vec::new)
|
self.channels.entry(channel_name).or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_join(&mut self, channel: String, nickname: &str) {
|
pub fn on_join(&mut self, channel_name: &str, nickname: &str) {
|
||||||
self.get_mut(Some(channel)).push(IrcMessage::Join {
|
let is_active = self.active_channel.as_deref() != Some(channel_name);
|
||||||
|
|
||||||
|
let channel = self.get_mut(Some(channel_name.to_string()));
|
||||||
|
channel.messages.push(IrcMessage::Join {
|
||||||
nickname: nickname.to_string(),
|
nickname: nickname.to_string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if is_active {
|
||||||
|
channel.unread_events += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_part(&mut self, channel: String, nickname: &str, comment: Option<&str>) {
|
pub fn on_part(&mut self, channel_name: &str, nickname: &str, comment: Option<&str>) {
|
||||||
self.get_mut(Some(channel)).push(IrcMessage::Part {
|
let is_active = self.active_channel.as_deref() != Some(channel_name);
|
||||||
|
|
||||||
|
let channel = self.get_mut(Some(channel_name.to_string()));
|
||||||
|
channel.messages.push(IrcMessage::Part {
|
||||||
nickname: nickname.to_string(),
|
nickname: nickname.to_string(),
|
||||||
reason: comment.map(str::to_string),
|
reason: comment.map(str::to_string),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if is_active {
|
||||||
|
channel.unread_events += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_nick(&mut self, old: &str, new: &str) {
|
pub fn on_nick(&mut self, old: &str, new: &str) {
|
||||||
for log in self.0.values_mut() {
|
// TODO increment event counter for each relevant channel
|
||||||
log.push(IrcMessage::Nick {
|
for log in self.channels.values_mut() {
|
||||||
|
// TODO only show in relevant channels
|
||||||
|
log.messages.push(IrcMessage::Nick {
|
||||||
old: old.to_string(),
|
old: old.to_string(),
|
||||||
new: new.to_string(),
|
new: new.to_string(),
|
||||||
});
|
});
|
||||||
|
@ -53,25 +84,48 @@ impl<'a> MessageLog {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_quit(&mut self, nickname: &str, reason: Option<&str>) {
|
pub fn on_quit(&mut self, nickname: &str, reason: Option<&str>) {
|
||||||
for log in self.0.values_mut() {
|
// TODO increment event counter for each relevant channel
|
||||||
log.push(IrcMessage::Quit {
|
for log in self.channels.values_mut() {
|
||||||
|
// TODO only show in relevant channels
|
||||||
|
log.messages.push(IrcMessage::Quit {
|
||||||
nickname: nickname.to_string(),
|
nickname: nickname.to_string(),
|
||||||
reason: reason.map(str::to_string),
|
reason: reason.map(str::to_string),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_privmsg(&mut self, channel: String, nickname: &str, message: &str) {
|
pub fn on_privmsg(&mut self, channel_name: &str, nickname: &str, message: &str) {
|
||||||
self.get_mut(Some(channel)).push(IrcMessage::Privmsg {
|
let is_active = self.active_channel.as_deref() == Some(channel_name);
|
||||||
|
|
||||||
|
let channel = self.get_mut(Some(channel_name.to_string()));
|
||||||
|
channel.messages.push(IrcMessage::Privmsg {
|
||||||
nickname: nickname.to_string(),
|
nickname: nickname.to_string(),
|
||||||
message: message.to_string(),
|
message: message.to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
if !is_active {
|
||||||
|
// TODO Configurable nickname
|
||||||
|
let highlight_regex = Regex::new(r"\bcri\b").unwrap();
|
||||||
|
if highlight_regex.is_match(message) {
|
||||||
|
channel.unread_highlights += 1;
|
||||||
|
} else {
|
||||||
|
channel.unread_messages += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_other(&mut self, message: &str) {
|
||||||
|
self.get_mut(None).messages.push(IrcMessage::Other {
|
||||||
|
message: message.trim().to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn on_other(&mut self, message: &str) {
|
pub fn set_active(&mut self, channel_name: Option<String>) {
|
||||||
self.get_mut(None).push(IrcMessage::Other {
|
self.active_channel = channel_name.clone();
|
||||||
message: message.trim().to_string(),
|
let channel = self.get_mut(channel_name);
|
||||||
})
|
channel.unread_events = 0;
|
||||||
|
channel.unread_messages = 0;
|
||||||
|
channel.unread_highlights = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view(&self, active_channel: &Option<String>) -> Container<'_, crate::UiMessage> {
|
pub fn view(&self, active_channel: &Option<String>) -> Container<'_, crate::UiMessage> {
|
||||||
|
@ -102,6 +156,7 @@ impl<'a> MessageLog {
|
||||||
let messages = self
|
let messages = self
|
||||||
.get(active_channel)
|
.get(active_channel)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.messages
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|message| -> Option<iced::Element<_>> {
|
.flat_map(|message| -> Option<iced::Element<_>> {
|
||||||
match message {
|
match message {
|
||||||
|
@ -197,7 +252,6 @@ impl<'a> MessageLog {
|
||||||
IrcMessage::Other { message } => Some(text(message).into()),
|
IrcMessage::Other { message } => Some(text(message).into()),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map(|element| element.into())
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
container(
|
container(
|
||||||
|
|
Loading…
Reference in a new issue