summaryrefslogtreecommitdiffstats
path: root/src/lib.rs
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@bunny.garden>2025-05-24 12:03:57 +0100
committerLibravatar cel 🌸 <cel@bunny.garden>2025-05-24 12:03:57 +0100
commit5f5edccaf327727662db027b9fc4cdf86365e20b (patch)
tree31acfd8d32b7e26486e40603e1d721cb13f13167 /src/lib.rs
parenteff7045e9f871c0ec6eb0401c77ab4209b36d636 (diff)
downloadmacaw-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.rs90
1 files changed, 81 insertions, 9 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 570d2f6..92c764d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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,