From eff7045e9f871c0ec6eb0401c77ab4209b36d636 Mon Sep 17 00:00:00 2001 From: cel 🌸 Date: Fri, 23 May 2025 16:00:54 +0100 Subject: feat: subscription request badges --- assets/style.scss | 30 ++++++++++++++++++++++++++++++ src/lib.rs | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/assets/style.scss b/assets/style.scss index df90e7c..245e5c7 100644 --- a/assets/style.scss +++ b/assets/style.scss @@ -510,6 +510,11 @@ p { .dock .shortcuts .dock-item img { width: 64px; height: 64px; +} + +.dock-icon { + width: 64px; + height: 64px; padding: 4px 8px; } @@ -712,6 +717,31 @@ hr { flex: 0 0 auto; } +.icon-with-badge { + position: relative; +} + +.badge { + position: absolute; + top: 0; + right: 0; + border-radius: 50%; + background-color: #C1173C; + color: #dcdcdc; + height: 1em; + min-width: 1em; + padding: 2px; + display: flex; + justify-content: center; + align-items: center; +} + +.header-icon .badge { + height: 8px; + width: 8px; + min-width: revert; +} + /* font-families */ /* thai */ diff --git a/src/lib.rs b/src/lib.rs index 90cae4e..570d2f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -649,6 +649,7 @@ fn Macaw( // TODO: timestamp incoming/outgoing subscription requests let (subscription_requests, set_subscription_requests)= signal(HashSet::::new()); provide_context(subscription_requests); + provide_context(set_subscription_requests); // TODO: get cached contacts on login before getting the updated contacts @@ -769,6 +770,8 @@ pub fn toggle_open(state: &mut Option, open: SidebarOpen) -> bool { #[component] pub fn Sidebar() -> impl IntoView { + let requests: ReadSignal> = use_context().expect("no pending subscriptions in context"); + // for what has been clicked open (in the background) let (open, set_open) = signal(None::); // for what is just in the hovered state (not clicked to be pinned open yet necessarily) @@ -795,7 +798,21 @@ pub fn Sidebar() -> impl IntoView { }) }>
- +
+
+ + {move || { + let len = requests.read().len(); + if len > 0 { + view! { +
{len}
+ }.into_any() + } else { + view! {}.into_any() + } + }} +
+
) -> impl IntoView { #[component] fn RosterList() -> impl IntoView { + let requests: ReadSignal> = use_context().expect("no pending subscriptions in context"); + let roster: Store = use_context().expect("no roster in context"); let (open_add_contact, set_open_add_contact) = signal(false); @@ -2176,6 +2195,15 @@ fn RosterList() -> impl IntoView {

Roster

+ {move || { + if !requests.read().is_empty() { + view! { +
+ }.into_any() + } else { + view! {}.into_any() + } + }}
{move || { @@ -2211,6 +2239,7 @@ pub enum AddContactError { #[component] fn AddContact() -> impl IntoView { let requests: ReadSignal> = use_context().expect("no pending subscriptions in context"); + let set_requests: WriteSignal> = use_context().expect("no pending subscriptions write signal in context"); let roster: Store = use_context().expect("no roster in context"); let jid = RwSignal::new("".to_string()); @@ -2306,7 +2335,8 @@ fn AddContact() -> impl IntoView { let jid = jid.clone(); async move { // TODO: error - client.unsubscribe_contact(jid).await; + client.unsubscribe_contact(jid.clone()).await; + set_requests.write().remove(&jid); } }); @@ -2352,7 +2382,7 @@ fn AddContact() -> impl IntoView { let jid_string = move || request.to_string(); view! {
{jid_string}
-
Accept
Accept
+
Accept
Reject
} } -- cgit