Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync channels & users to connection state #104

Merged
merged 15 commits into from
Jul 6, 2023
76 changes: 50 additions & 26 deletions data/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::BTreeMap;
use std::collections::{BTreeMap, HashMap};

use irc::client::Client;
use itertools::Itertools;

use crate::user::NickRef;
use crate::{message, Message, Server, User};
Expand Down Expand Up @@ -28,13 +29,17 @@ pub enum State {
pub struct Connection {
client: Client,
resolved_nick: Option<String>,
channels: Vec<String>,
users: HashMap<String, Vec<User>>,
Comment on lines +32 to +33
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Power to us!

}

impl Connection {
pub fn new(client: Client) -> Self {
Self {
client,
resolved_nick: None,
channels: vec![],
users: HashMap::new(),
}
}

Expand Down Expand Up @@ -88,17 +93,42 @@ impl Connection {
}
}

pub fn channels(&self) -> Vec<String> {
self.client.list_channels().unwrap_or_default()
fn sync(&mut self) {
self.channels = self
.client
.list_channels()
.unwrap_or_default()
.into_iter()
.sorted()
.collect();

self.users = self
.channels
.iter()
.map(|channel| {
(
channel.clone(),
self.client
.list_users(channel)
.unwrap_or_default()
.into_iter()
.map(User::from)
.sorted()
.collect(),
)
})
.collect();
}

fn users(&self, channel: &str) -> Vec<User> {
self.client
.list_users(channel)
pub fn channels(&self) -> &[String] {
&self.channels
}

fn users<'a>(&'a self, channel: &str) -> &'a [User] {
self.users
.get(channel)
.map(Vec::as_slice)
.unwrap_or_default()
.into_iter()
.map(User::from)
.collect()
}

pub fn nickname(&self) -> NickRef {
Expand Down Expand Up @@ -158,30 +188,24 @@ impl Map {
.and_then(|connection| connection.receive(message))
}

pub fn sync(&mut self) {
self.0.values_mut().for_each(|state| {
if let State::Ready(connection) = state {
connection.sync();
}
});
}

pub fn send(&mut self, server: &Server, message: message::Encoded) {
if let Some(connection) = self.connection_mut(server) {
connection.send(message);
}
}

pub fn get_channel_users(&self, server: &Server, channel: &str) -> Vec<User> {
let mut users = self
.connection(server)
pub fn get_channel_users<'a>(&'a self, server: &Server, channel: &str) -> &'a [User] {
self.connection(server)
.map(|connection| connection.users(channel))
.unwrap_or_default();
users.sort();

users
}

pub fn get_channels(&self) -> BTreeMap<Server, Vec<String>> {
self.0
.iter()
.filter_map(|(server, state)| match state {
State::Disconnected => None,
State::Ready(connection) => Some((server.clone(), connection.channels())),
})
.collect()
.unwrap_or_default()
}

pub fn iter(&self) -> std::collections::btree_map::Iter<Server, State> {
Expand Down
2 changes: 1 addition & 1 deletion src/buffer/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ mod nick_list {
use crate::theme;
use crate::widget::Element;

pub fn view<'a>(users: Vec<User>) -> Element<'a, Message> {
pub fn view(users: &[User]) -> Element<Message> {
let column = column(
users
.iter()
Expand Down
4 changes: 4 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ impl Application for Halloy {
}
});

// Must be called after receiving message batches to ensure
// user & channel lists are in sync
self.clients.sync();

Command::none()
}
},
Expand Down