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