diff options
author | 2025-05-24 12:03:57 +0100 | |
---|---|---|
committer | 2025-05-24 12:03:57 +0100 | |
commit | 5f5edccaf327727662db027b9fc4cdf86365e20b (patch) | |
tree | 31acfd8d32b7e26486e40603e1d721cb13f13167 /src/lib.rs | |
parent | eff7045e9f871c0ec6eb0401c77ab4209b36d636 (diff) | |
download | macaw-web-5f5edccaf327727662db027b9fc4cdf86365e20b.tar.gz macaw-web-5f5edccaf327727662db027b9fc4cdf86365e20b.tar.bz2 macaw-web-5f5edccaf327727662db027b9fc4cdf86365e20b.zip |
feat: modal
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 90 |
1 files changed, 81 insertions, 9 deletions
@@ -20,7 +20,7 @@ use futures::stream::StreamExt; use indexmap::IndexMap; use jid::JID; use leptos::{ - ev::{Event, KeyboardEvent, SubmitEvent}, + ev::{Event, KeyboardEvent, MouseEvent, SubmitEvent}, html::{self, Div, Input, Pre, Textarea}, prelude::*, tachys::{dom::document, reactive_graph::bind::GetValue}, @@ -633,6 +633,8 @@ fn Macaw( let open_chats = Store::new(OpenChatsPanel::default()); provide_context(open_chats); + let show_settings = RwSignal::new(None::<SettingsPage>); + provide_context(show_settings); let user_presences = Store::new(UserPresences::new()); provide_context(user_presences); @@ -740,6 +742,11 @@ fn Macaw( <Sidebar /> // <ChatsList /> <OpenChatsPanelView /> + {move || if let Some(_) = *show_settings.read() { + view! { <Settings /> }.into_any() + } else { + view! {}.into_any() + }} } } @@ -902,7 +909,7 @@ pub fn PersonalStatus() -> impl IntoView { if open { view! { <Overlay set_open> - <PersonalStatusMenu user /> + <PersonalStatusMenu user set_open/> </Overlay> }.into_any() } else { @@ -915,7 +922,8 @@ pub fn PersonalStatus() -> impl IntoView { } #[component] -pub fn PersonalStatusMenu(user: Store<User>) -> impl IntoView { +pub fn PersonalStatusMenu(user: Store<User>, set_open: WriteSignal<bool>) -> impl IntoView { + 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"); @@ -1019,10 +1027,16 @@ pub fn PersonalStatusMenu(user: Store<User>) -> impl IntoView { </select> </div> <hr /> - <div class="menu-item"> + <div class="menu-item" on:click=move |_| { + show_settings.set(Some(SettingsPage::Profile)); + set_open.set(false); + }> Profile </div> - <div class="menu-item"> + <div class="menu-item" on:click=move |_| { + show_settings.set(Some(SettingsPage::Account)); + set_open.set(false); + }> Settings </div> <hr /> @@ -1047,15 +1061,69 @@ pub fn Overlay(set_open: WriteSignal<bool>, children: Children) -> impl IntoView } #[component] -pub fn Modal(set_open: WriteSignal<bool>, children: Children) -> impl IntoView { +pub fn Modal(on_background_click: impl Fn(MouseEvent) + 'static, children: Children) -> impl IntoView { view! { - <div class="modal"> - <div class="modal-background" on:click=move |_| set_open.update(|state| *state = false)></div> - <div class="modal-content">{children()}</div> + <div class="modal" on:click=move |e| { + if e.current_target() == e.target() { + on_background_click(e) + } + }> + {children()} </div> } } +#[derive(Clone, Copy, Debug)] +pub enum SettingsPage { + Account, + Chat, + Profile, + Privacy, +} + +#[component] +pub fn Settings() -> impl IntoView { + let show_settings: RwSignal<Option<SettingsPage>> = use_context().unwrap(); + + view! { + <Modal on_background_click=move |_| { show_settings.set(None); }> + <div class="settings panel"> + <div class="header"> + <h2>Settings</h2> + <div class="header-icon close"> + <IconComponent icon=Icon::Close24 on:click=move |_| show_settings.set(None)/> + </div> + </div> + <div class="settings-main"> + <div class="settings-sidebar"> + <div on:click=move |_| show_settings.set(Some(SettingsPage::Account))>Account</div> + <div on:click=move |_| show_settings.set(Some(SettingsPage::Chat))>Chat</div> + <div on:click=move |_| show_settings.set(Some(SettingsPage::Privacy))>Privacy</div> + <div on:click=move |_| show_settings.set(Some(SettingsPage::Profile))>Profile</div> + </div> + <div class="settings-main"> + {move || if let Some(page) = show_settings.get() { + match page { + SettingsPage::Account => view! { <div>"account"</div> }.into_any(), + SettingsPage::Chat => view! { <div>"chat"</div> }.into_any(), + SettingsPage::Profile => view! { <div>"profile"</div> }.into_any(), + SettingsPage::Privacy => view! { <div>"privacy"</div> }.into_any(), + } + } else { + view! {}.into_any() + }} + </div> + </div> + </div> + </Modal> + } +} + +#[component] +pub fn ProfileSettings() -> impl IntoView { + view! {} +} + #[component] pub fn OpenChatsPanelView() -> impl IntoView { let open_chats: Store<OpenChatsPanel> = use_context().expect("no open chats panel in context"); @@ -1340,6 +1408,7 @@ pub enum Icon { Bubble16, Bubble16Color, Bubble24, + Close24, Contact24, Delivered16, Dnd16, @@ -1368,6 +1437,7 @@ impl Icon { Icon::Bubble16 => format!("{}bubble16.svg", ICONS_SRC), Icon::Bubble16Color => format!("{}bubble16color.svg", ICONS_SRC), Icon::Bubble24 => format!("{}bubble24.svg", ICONS_SRC), + Icon::Close24 => format!("{}close24.svg", ICONS_SRC), Icon::Contact24 => format!("{}contact24.svg", ICONS_SRC), Icon::Delivered16 => format!("{}delivered16.svg", ICONS_SRC), Icon::Dnd16 => format!("{}dnd16.svg", ICONS_SRC), @@ -1394,6 +1464,7 @@ impl Icon { Icon::Bubble16 => 16, Icon::Bubble16Color => 16, Icon::Bubble24 => 24, + Icon::Close24 => 24, Icon::Contact24 => 24, Icon::Delivered16 => 16, Icon::Dnd16 => 16, @@ -1420,6 +1491,7 @@ impl Icon { Icon::Bubble16 => true, Icon::Bubble16Color => false, Icon::Bubble24 => true, + Icon::Close24 => true, Icon::Contact24 => true, Icon::Delivered16 => true, Icon::Dnd16 => true, |