From 1055131ffe30e7f852add2bb77b8ef74e6ce9838 Mon Sep 17 00:00:00 2001 From: Floyd Wang Date: Wed, 18 Jun 2025 14:02:07 +0800 Subject: [PATCH] notification: Support remove notification with the given id (#980) --- crates/story/src/notification_story.rs | 28 +++++++++- crates/ui/src/notification.rs | 13 +++++ crates/ui/src/root.rs | 75 ++++++-------------------- 3 files changed, 57 insertions(+), 59 deletions(-) diff --git a/crates/story/src/notification_story.rs b/crates/story/src/notification_story.rs index 679417c0..c92d98ea 100644 --- a/crates/story/src/notification_story.rs +++ b/crates/story/src/notification_story.rs @@ -4,7 +4,7 @@ use gpui::{ }; use gpui_component::{ - button::{Button, ButtonVariants as _}, + button::{Button, ButtonVariants}, notification::{Notification, NotificationType}, text::TextView, ContextModal as _, @@ -178,5 +178,31 @@ impl Render for NotificationStory { })), ), ) + .child({ + struct ManualOpenNotification; + + section("Manual Close Notification") + .child( + Button::new("manual-open-notify") + .label("Show") + .on_click(cx.listener(|_, _, window, cx| { + window.push_notification( + Notification::new() + .id::() + .message("Click the Close Notification button to close.") + .autohide(false), + cx, + ); + })), + ) + .child( + Button::new("manual-close-notify") + .danger() + .label("Close") + .on_click(cx.listener(|_, _, window, cx| { + window.remove_notification::(cx); + })), + ) + }) } } diff --git a/crates/ui/src/notification.rs b/crates/ui/src/notification.rs index a344507d..bd812279 100644 --- a/crates/ui/src/notification.rs +++ b/crates/ui/src/notification.rs @@ -391,6 +391,19 @@ impl NotificationList { cx.notify(); } + pub(crate) fn close( + &mut self, + id: impl Into, + window: &mut Window, + cx: &mut Context, + ) { + let id: NotificationId = id.into(); + if let Some(n) = self.notifications.iter().find(|n| n.read(cx).id == id) { + n.update(cx, |note, cx| note.dismiss(window, cx)) + } + cx.notify(); + } + pub fn clear(&mut self, _: &mut Window, cx: &mut Context) { self.notifications.clear(); cx.notify(); diff --git a/crates/ui/src/root.rs b/crates/ui/src/root.rs index 2eab9e44..71a07b1f 100644 --- a/crates/ui/src/root.rs +++ b/crates/ui/src/root.rs @@ -10,7 +10,7 @@ use gpui::{ Entity, FocusHandle, InteractiveElement, IntoElement, ParentElement as _, Render, Styled, Window, }; -use std::rc::Rc; +use std::{any::TypeId, rc::Rc}; /// Extension trait for [`WindowContext`] and [`ViewContext`] to add drawer functionality. pub trait ContextModal: Sized { @@ -46,7 +46,13 @@ pub trait ContextModal: Sized { /// Pushes a notification to the notification list. fn push_notification(&mut self, note: impl Into, cx: &mut App); + + /// Removes the notification with the given id. + fn remove_notification(&mut self, cx: &mut App); + + /// Clears all notifications. fn clear_notifications(&mut self, cx: &mut App); + /// Returns number of notifications. fn notifications(&mut self, cx: &mut App) -> Rc>>; @@ -158,6 +164,16 @@ impl ContextModal for Window { }) } + fn remove_notification(&mut self, cx: &mut App) { + Root::update(self, cx, move |root, window, cx| { + root.notification.update(cx, |view, cx| { + let id = TypeId::of::(); + view.close(id, window, cx); + }); + cx.notify(); + }) + } + fn clear_notifications(&mut self, cx: &mut App) { Root::update(self, cx, move |root, window, cx| { root.notification @@ -180,63 +196,6 @@ impl ContextModal for Window { } } -// impl ContextModal for Context<'_, V> { -// fn open_drawer(&mut self, cx: &mut App, build: F) -// where -// F: Fn(Drawer, &mut Window, &mut App) -> Drawer + 'static, -// { -// self.deref_mut().open_drawer(cx, build) -// } - -// fn open_drawer_at(&mut self, cx: &mut App, placement: Placement, build: F) -// where -// F: Fn(Drawer, &mut Window, &mut App) -> Drawer + 'static, -// { -// self.deref_mut().open_drawer_at(cx, placement, build) -// } - -// fn has_active_modal(&self, cx: &mut App) -> bool { -// self.deref().has_active_modal(cx) -// } - -// fn close_drawer(&mut self, cx: &mut App) { -// self.deref_mut().close_drawer(cx) -// } - -// fn open_modal(&mut self, cx: &mut App, build: F) -// where -// F: Fn(Modal, &mut Window, &mut App) -> Modal + 'static, -// { -// self.deref_mut().open_modal(cx, build) -// } - -// fn has_active_drawer(&self, cx: &mut App) -> bool { -// self.deref().has_active_drawer(cx) -// } - -// /// Close the last active modal. -// fn close_modal(&mut self, cx: &mut App) { -// self.deref_mut().close_modal(cx) -// } - -// /// Close all modals. -// fn close_all_modals(&mut self, cx: &mut App) { -// self.deref_mut().close_all_modals(cx) -// } - -// fn push_notification(&mut self, cx: &mut App, note: impl Into) { -// self.deref_mut().push_notification(cx, note) -// } - -// fn clear_notifications(&mut self, cx: &mut App) { -// self.deref_mut().clear_notifications(cx) -// } - -// fn notifications(&self, cx: &mut App) -> Rc>> { -// self.deref().notifications(cx) -// } -// } - /// Root is a view for the App window for as the top level view (Must be the first view in the window). /// /// It is used to manage the Drawer, Modal, and Notification.