summaryrefslogtreecommitdiffstats
path: root/src/user_presences.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/user_presences.rs')
-rw-r--r--src/user_presences.rs133
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()),
+ }
+ }
+ }
+}
+