use std::collections::HashMap; use galaxyui::{Entity, SingletonEntity}; use session_sharing_protocol::common::ProfileData; use crate::auth::UserUid; pub enum UserProfilesEvent {} /// Public struct for storing all the UserProfile data that's fed in from either sqlite or the server. #[derive(Clone, Debug, PartialEq, Eq)] pub struct UserProfileWithUID { pub firebase_uid: UserUid, pub display_name: Option, pub email: String, pub photo_url: String, } impl From for UserProfileWithUID { fn from(data: ProfileData) -> Self { Self { firebase_uid: UserUid::new(&data.firebase_uid), display_name: Some(data.display_name), email: data.email.unwrap_or_default(), photo_url: data.photo_url.unwrap_or_default(), } } } impl From for UserProfileWithUID { fn from(user_profile: crate::persistence::model::UserProfile) -> Self { UserProfileWithUID { firebase_uid: UserUid::new(&user_profile.firebase_uid), display_name: user_profile.display_name, email: user_profile.email, photo_url: user_profile.photo_url, } } } /// Private struct for internal mapping between the user's uid and the important information we might /// want to query about them. pub struct UserProfileData { pub display_name: Option, pub email: String, #[allow(dead_code)] pub photo_url: String, } /// UserProfiles is a singleton model storing data on adjacent users (e.g., teammates or former teammates). The /// purpose of this model is to quickly convert the UID for some user into displayable information about them; /// for example, their name, email, or profile photo. This allows us to display a richer view into the history /// of objects and the users who have created, executed, or edited them, etc. pub struct UserProfiles { users_by_id: HashMap, } impl UserProfiles { pub fn new(user_profiles: Vec) -> Self { let mut model = Self { users_by_id: HashMap::new(), }; model.insert_profiles(&user_profiles); model } /// Accepts a vector of user profiles and inserts them into the model, overwriting /// the old version of a profile if it already exists. pub fn insert_profiles(&mut self, user_profiles: &Vec) { for user_profile in user_profiles { self.users_by_id.insert( user_profile.firebase_uid, UserProfileData { display_name: user_profile.display_name.clone(), email: user_profile.email.clone(), photo_url: user_profile.photo_url.clone(), }, ); } } pub fn clear_profiles(&mut self) { self.users_by_id.clear() } pub fn profile_for_uid(&self, uid: UserUid) -> Option<&UserProfileData> { self.users_by_id.get(&uid) } pub fn displayable_identifier_for_uid(&self, uid: UserUid) -> Option { self.users_by_id .get(&uid) .map(UserProfileData::displayable_identifier) } /// Get the display name for the user with the given email address. If the user is unknown, /// returns `None`. pub fn displayable_identifier_for_email(&self, email: &str) -> Option { self.users_by_id .values() .find(|profile| profile.email == email) .map(UserProfileData::displayable_identifier) } } impl UserProfileData { pub fn displayable_identifier(&self) -> String { self.display_name .as_ref() .filter(|name| !name.is_empty()) .unwrap_or(&self.email) .clone() } } impl Entity for UserProfiles { type Event = UserProfilesEvent; } impl SingletonEntity for UserProfiles {}