diff options
Diffstat (limited to 'src/user_presences.rs')
-rw-r--r-- | src/user_presences.rs | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/user_presences.rs b/src/user_presences.rs new file mode 100644 index 0000000..1a719a2 --- /dev/null +++ b/src/user_presences.rs @@ -0,0 +1,133 @@ +use std::collections::HashMap; + +use chrono::Utc; +use filamento::presence::{Offline, Presence, PresenceType, Show}; +use indexmap::IndexMap; +use jid::BareJID; +use leptos::prelude::*; +use reactive_stores::Store; + +#[derive(Store)] +pub struct UserPresences { + #[store(key: BareJID = |(jid, _)| jid.clone())] + pub user_presences: HashMap<BareJID, ArcRwSignal<Presences>>, +} + +impl UserPresences { + pub fn clear(&mut self) { + for (_user, presences) in &mut self.user_presences { + presences.set(Presences::new()) + } + } + + // TODO: should be a bare jid + pub fn get_user_presences(&mut self, user: &BareJID) -> ArcRwSignal<Presences> { + if let Some(presences) = self.user_presences.get(user) { + presences.clone() + } else { + let presences = Presences::new(); + let signal = ArcRwSignal::new(presences); + self.user_presences.insert(user.clone(), signal.clone()); + signal + } + } +} + +impl UserPresences { + pub fn new() -> Self { + Self { + user_presences: HashMap::new(), + } + } +} + +pub struct Presences { + /// presences are sorted by time, first by type, then by last activity. + presences: IndexMap<String, Presence> +} + +impl Presences { + pub fn new() -> Self { + Self { + presences: IndexMap::new(), + } + } + + /// gets the highest priority presence + pub fn presence(&self) -> Option<(String, Presence)> { + if let Some((resource, presence)) = self.presences.iter().filter(|(_resource, presence)| if let PresenceType::Online(online) = &presence.presence { + online.show == Some(Show::DoNotDisturb) + } else { + false + }).next() { + return Some((resource.clone(), presence.clone())) + } + if let Some((resource, presence)) = self.presences.iter().filter(|(_resource, presence)| if let PresenceType::Online(online) = &presence.presence { + online.show == Some(Show::Chat) + } else { + false + }).next() { + return Some((resource.clone(), presence.clone())) + } + if let Some((resource, presence)) = self.presences.iter().filter(|(_resource, presence)| if let PresenceType::Online(online) = &presence.presence { + online.show == None + } else { + false + }).next() { + return Some((resource.clone(), presence.clone())) + } + if let Some((resource, presence)) = self.presences.iter().filter(|(_resource, presence)| if let PresenceType::Online(online) = &presence.presence { + online.show == Some(Show::Away) + } else { + false + }).next() { + return Some((resource.clone(), presence.clone())) + } + if let Some((resource, presence)) = self.presences.iter().filter(|(_resource, presence)| if let PresenceType::Online(online) = &presence.presence { + online.show == Some(Show::ExtendedAway) + } else { + false + }).next() { + return Some((resource.clone(), presence.clone())) + } + if let Some((resource, presence)) = self.presences.iter().filter(|(_resource, presence)| if let PresenceType::Offline(_offline) = &presence.presence { + true + } else { + false + }).next() { + return Some((resource.clone(), presence.clone())) + } else { + None + } + } + + pub fn update_presence(&mut self, resource: String, presence: Presence) { + let index = match self.presences.binary_search_by(|_, existing_presence| { + presence.timestamp + .cmp( + &existing_presence.timestamp + ) + }) { + Ok(i) => i, + Err(i) => i, + }; + self.presences.insert_before( + // TODO: check if this logic is correct + index, + resource, + presence, + ); + } + + pub fn resource_presence(&mut self, resource: String) -> Presence { + if let Some(presence) = self.presences.get(&resource) { + presence.clone() + } else { + Presence { + timestamp: Utc::now(), + presence: PresenceType::Offline(Offline::default()), + } + } + } +} + |