summaryrefslogblamecommitdiffstats
path: root/src/user_presences.rs
blob: 1a719a2074871452c0c93578e64135416188aef5 (plain) (tree)




































































































































                                                                                                                                                              
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()),
            }
        }
    }
}