diff options
author | 2025-06-01 16:10:26 +0100 | |
---|---|---|
committer | 2025-06-01 17:27:40 +0100 | |
commit | 6ee4190a26f32bfa953302ee363ad3bb6c384ebb (patch) | |
tree | 2c3182c29d5780a0ad9c9770b5e546312bea49b4 /src/components/personal_status.rs | |
parent | f76c80c1d23177ab00c81240ee3a75d3bcda0e3b (diff) | |
download | macaw-web-6ee4190a26f32bfa953302ee363ad3bb6c384ebb.tar.gz macaw-web-6ee4190a26f32bfa953302ee363ad3bb6c384ebb.tar.bz2 macaw-web-6ee4190a26f32bfa953302ee363ad3bb6c384ebb.zip |
refactor: reorganise code
Diffstat (limited to 'src/components/personal_status.rs')
-rw-r--r-- | src/components/personal_status.rs | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/components/personal_status.rs b/src/components/personal_status.rs new file mode 100644 index 0000000..f830a1b --- /dev/null +++ b/src/components/personal_status.rs @@ -0,0 +1,178 @@ +use filamento::{presence::{Offline, Online, PresenceType, Show}, user::{User, UserStoreFields}}; +use leptos::{html, prelude::*}; +use reactive_stores::{ArcStore, Store}; +use tracing::{debug, error}; + +use crate::{client::Client, components::{avatar::AvatarWithPresence, overlay::Overlay}, user::{get_name, MacawUser}, user_presences::UserPresences, views::{macaw::settings::SettingsPage, AppState}}; + +#[component] +pub fn PersonalStatus() -> impl IntoView { + let user: LocalResource<MacawUser> = use_context().expect("no local user in context"); + + let (open, set_open) = signal(false); + move || if let Some(user) = user.get() { + let user: Store<User> = <ArcStore<filamento::user::User> as Clone>::clone(&(*user.user)).into(); + view! { + <div class="dock-item" class:focused=move || *open.read() on:click=move |_| { + debug!("set open to true"); + set_open.update(|state| *state = !*state) + }> + <AvatarWithPresence user=user /> + <div class="dock-pill"></div> + </div> + {move || { + let open = open.get(); + debug!("open = {:?}", open); + if open { + view! { + <Overlay set_open> + <PersonalStatusMenu user set_open/> + </Overlay> + }.into_any() + } else { + view! {}.into_any() + }}} + }.into_any() + } else { + view! {}.into_any() + } +} + +#[component] +pub fn PersonalStatusMenu(user: Store<User>, set_open: WriteSignal<bool>) -> impl IntoView { + let set_app: WriteSignal<AppState> = use_context().unwrap(); + let show_settings: RwSignal<Option<SettingsPage>> = use_context().unwrap(); + let user_presences: Store<UserPresences> = use_context().expect("no user presence store"); + + let client = use_context::<Client>().expect("client not in context"); + let client1 = client.clone(); + let (show_value, set_show_value) = signal({ + let show = match user_presences.write().get_user_presences(&user.jid().read()).write().resource_presence(client.resource.read().clone().unwrap_or_default()).presence { + PresenceType::Online(online) => match online.show { + Some(s) => match s { + Show::Away => 3, + Show::Chat => 0, + Show::DoNotDisturb => 2, + Show::ExtendedAway => 4, + }, + None => 1, + }, + PresenceType::Offline(_offline) => 5, + }; + debug!("initial show = {show}"); + show + }); + + let show_select: NodeRef<html::Select> = NodeRef::new(); + + let disconnect = Action::new_local(move |()| { + let client = client.clone(); + async move { + client.disconnect(Offline::default()).await; + } + }); + let set_status = Action::new_local(move |show_value: &i32| { + let show_value = show_value.to_owned(); + let client = client1.clone(); + async move { + if let Err(e) = match show_value { + 0 => { + if let Ok(r) = client.connect().await { + client.resource.set(Some(r)) + }; + client.set_status(Online { show: Some(Show::Chat), ..Default::default() }).await + }, + 1 => { + if let Ok(r) = client.connect().await { + client.resource.set(Some(r)) + }; + client.set_status(Online { show: None, ..Default::default() }).await + }, + 2 => { + if let Ok(r) = client.connect().await { + client.resource.set(Some(r)) + }; + client.set_status(Online { show: Some(Show::DoNotDisturb), ..Default::default() }).await + }, + 3 => { + if let Ok(r) = client.connect().await { + client.resource.set(Some(r)) + }; + client.set_status(Online { show: Some(Show::Away), ..Default::default() }).await + }, + 4 => { + if let Ok(r) = client.connect().await { + client.resource.set(Some(r)) + }; + client.set_status(Online { show: Some(Show::ExtendedAway), ..Default::default() }).await + }, + 5 => { + if let Ok(_) = client.disconnect(Offline::default()).await { + client.resource.set(None) + } + set_show_value.set(5); + return + } + _ => { + error!("invalid availability select"); + return + } + } { + error!("show set error: {e}"); + return + } + set_show_value.set(show_value); + } + }); + + view! { + <div class="personal-status-menu menu"> + <div class="user"> + <AvatarWithPresence user=user /> + <div class="user-info"> + <div class="nick">{move || get_name(user, false)}</div> + <div class="jid">{move || user.jid().with(|jid| jid.to_string())}</div> + </div> + </div> + <div class="status-edit"> + <select + node_ref=show_select + on:change:target=move |ev| { + let show_value = ev.target().value().parse().unwrap(); + set_status.dispatch(show_value); + } + prop:show_value=move || show_value.get().to_string() + > + <option value="0" selected=move || show_value.get_untracked() == 0>Available to Chat</option> + <option value="1" selected=move || show_value.get_untracked() == 1>Online</option> + <option value="2" selected=move || show_value.get_untracked() == 2>Do not disturb</option> + <option value="3" selected=move || show_value.get_untracked() == 3>Away</option> + <option value="4" selected=move || show_value.get_untracked() == 4>Extended Away</option> + <option value="5" selected=move || show_value.get_untracked() == 5>Offline</option> + </select> + </div> + <hr /> + <div class="menu-item" on:click=move |_| { + show_settings.set(Some(SettingsPage::Profile)); + set_open.set(false); + }> + Profile + </div> + <div class="menu-item" on:click=move |_| { + show_settings.set(Some(SettingsPage::Account)); + set_open.set(false); + }> + Settings + </div> + <hr /> + <div class="menu-item" on:click=move |_| { + // TODO: check if client is actually dropped/shutdown eventually + disconnect.dispatch(()); + set_app.set(AppState::LoggedOut) + }> + Log out + </div> + </div> + } +} + |