notification: Fix close animation not working when closed from content (#1578)

Currently, if dismiss is called from the content_builder or
action_builder, the closing animation doesn't play.

This is because the callback happens after the `closing` variable is
set, so the animation will only start on the next frame, (and for some
reason notify() doesn't trigger another frame?).

This change makes it so that the content_builder is called first, so the
closing animation starts playing immediately on the same frame.

This also adds a check to dismiss to prevent spawning unnecessary
futures if it is called multiple times
This commit is contained in:
Moulberry 2025-11-13 00:12:01 +08:00 committed by GitHub
parent f2ffece9fb
commit c62bb8b6a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -230,6 +230,9 @@ impl Notification {
/// Dismiss the notification. /// Dismiss the notification.
pub fn dismiss(&mut self, _: &mut Window, cx: &mut Context<Self>) { pub fn dismiss(&mut self, _: &mut Window, cx: &mut Context<Self>) {
if self.closing {
return;
}
self.closing = true; self.closing = true;
cx.notify(); cx.notify();
@ -266,6 +269,9 @@ impl Styled for Notification {
} }
impl Render for Notification { impl Render for Notification {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement { fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let content = self.content_builder.clone().map(|builder| builder(self, window, cx));
let action = self.action_builder.clone().map(|builder| builder(self, window, cx).small().mr_3p5());
let closing = self.closing; let closing = self.closing;
let icon = match self.type_ { let icon = match self.type_ {
None => self.icon.clone(), None => self.icon.clone(),
@ -302,12 +308,12 @@ impl Render for Notification {
.when_some(self.message.clone(), |this, message| { .when_some(self.message.clone(), |this, message| {
this.child(div().text_sm().child(message)) this.child(div().text_sm().child(message))
}) })
.when_some(self.content_builder.clone(), |this, child_builder| { .when_some(content, |this, content| {
this.child(child_builder(self, window, cx)) this.child(content)
}), }),
) )
.when_some(self.action_builder.clone(), |this, action_builder| { .when_some(action, |this, action| {
this.child(action_builder(self, window, cx).small().mr_3p5()) this.child(action)
}) })
.when_some(self.on_click.clone(), |this, on_click| { .when_some(self.on_click.clone(), |this, on_click| {
this.on_click(cx.listener(move |view, event, window, cx| { this.on_click(cx.listener(move |view, event, window, cx| {