chore: audit components
This commit is contained in:
+89
-87
@@ -6,11 +6,12 @@ use std::time::Duration;
|
||||
use gpui::prelude::FluentBuilder as _;
|
||||
use gpui::{
|
||||
Animation, AnimationExt as _, App, Context, ElementId, Entity, InteractiveElement as _,
|
||||
IntoElement, ParentElement as _, RenderOnce, SharedString, StatefulInteractiveElement as _,
|
||||
Styled as _, Task, Window, deferred, div, ease_out_quint, px,
|
||||
IntoElement, ParentElement as _, RenderOnce, Role, SharedString,
|
||||
StatefulInteractiveElement as _, Styled as _, Task, Window, deferred, div, ease_out_quint, px,
|
||||
};
|
||||
use gpui_native_icons::{Icon, IconRole, icon};
|
||||
use gpui_native_theme::ActiveTheme as _;
|
||||
use gpui_native_icons::{Icon, IconRole};
|
||||
use gpui_native_theme::{ActiveTheme as _, TOAST_MAX_WIDTH};
|
||||
use gpui_native_utils::ResultLogErr as _;
|
||||
|
||||
use crate::button::{Button, ButtonVariant};
|
||||
use crate::common::{DismissHandler, Sizable as _};
|
||||
@@ -41,6 +42,7 @@ impl ToastAction {
|
||||
|
||||
/// A toast notification.
|
||||
#[derive(Clone)]
|
||||
#[must_use]
|
||||
pub struct Toast {
|
||||
message: SharedString,
|
||||
icon: Option<Icon>,
|
||||
@@ -133,7 +135,8 @@ impl Toasts {
|
||||
if let Some(duration) = duration.filter(|duration| !duration.is_zero()) {
|
||||
let task = cx.spawn(async move |this, cx| {
|
||||
cx.background_executor().timer(duration).await;
|
||||
this.update(cx, |toasts, cx| toasts.dismiss(id, cx)).ok();
|
||||
this.update(cx, |toasts, cx| toasts.dismiss(id, cx))
|
||||
.log_err();
|
||||
});
|
||||
self.tasks.push(task);
|
||||
}
|
||||
@@ -147,8 +150,7 @@ impl Toasts {
|
||||
self.finish_exit(cx);
|
||||
return;
|
||||
}
|
||||
if self.current.as_ref().is_some_and(|entry| entry.id == id) {
|
||||
let entry = self.current.take().expect("current checked above");
|
||||
if let Some(entry) = self.current.take_if(|entry| entry.id == id) {
|
||||
self.start_exit(entry, cx);
|
||||
}
|
||||
}
|
||||
@@ -177,7 +179,7 @@ impl Toasts {
|
||||
if let Some(previous) = self.exiting.take()
|
||||
&& let Some(on_dismiss) = &previous.toast.on_dismiss
|
||||
{
|
||||
(on_dismiss.clone())(cx);
|
||||
on_dismiss(cx);
|
||||
}
|
||||
|
||||
self.exiting = Some(entry);
|
||||
@@ -186,7 +188,8 @@ impl Toasts {
|
||||
let fade = cx.theme().motion.overlay;
|
||||
let task = cx.spawn(async move |this, cx| {
|
||||
cx.background_executor().timer(fade).await;
|
||||
this.update(cx, |toasts, cx| toasts.finish_exit(cx)).ok();
|
||||
this.update(cx, |toasts, cx| toasts.finish_exit(cx))
|
||||
.log_err();
|
||||
});
|
||||
self.tasks.push(task);
|
||||
}
|
||||
@@ -195,13 +198,15 @@ impl Toasts {
|
||||
if let Some(entry) = self.exiting.take() {
|
||||
cx.notify();
|
||||
if let Some(on_dismiss) = &entry.toast.on_dismiss {
|
||||
(on_dismiss.clone())(cx);
|
||||
on_dismiss(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The floating stack of toasts, bottom center.
|
||||
#[derive(IntoElement)]
|
||||
#[must_use]
|
||||
pub struct ToastsView {
|
||||
toasts: Entity<Toasts>,
|
||||
id: ElementId,
|
||||
@@ -239,7 +244,7 @@ impl RenderOnce for ToastsView {
|
||||
.items_center()
|
||||
.when_some(exiting, |column, entry| {
|
||||
let id = entry.id;
|
||||
column.child(pill(&entry, &self.toasts, cx).with_animation(
|
||||
column.child(entry.pill(&self.toasts, cx).with_animation(
|
||||
("toast-exit", id),
|
||||
Animation::new(fade),
|
||||
|pill, delta| pill.opacity(1. - delta),
|
||||
@@ -247,7 +252,7 @@ impl RenderOnce for ToastsView {
|
||||
})
|
||||
.when_some(current, |column, entry| {
|
||||
let id = entry.id;
|
||||
column.child(pill(&entry, &self.toasts, cx).with_animation(
|
||||
column.child(entry.pill(&self.toasts, cx).with_animation(
|
||||
("toast-enter", id),
|
||||
Animation::new(fade).with_easing(ease_out_quint()),
|
||||
|pill, delta| pill.opacity(delta),
|
||||
@@ -257,90 +262,87 @@ impl RenderOnce for ToastsView {
|
||||
}
|
||||
}
|
||||
|
||||
fn pill(entry: &ToastEntry, toasts: &Entity<Toasts>, cx: &App) -> gpui::Stateful<gpui::Div> {
|
||||
let theme = cx.theme();
|
||||
let surface = theme.colors.surface;
|
||||
let border = if theme.borders.overlays {
|
||||
theme.colors.border
|
||||
} else {
|
||||
surface
|
||||
};
|
||||
let foreground = theme.colors.foreground;
|
||||
let muted = theme.colors.muted;
|
||||
let radius = theme.radius.full;
|
||||
let shadows = theme.elevations.popover.shadows();
|
||||
let icon_size = theme.sizes.small.icon_size;
|
||||
let dense_icon_size = theme.sizes.small.dense_icon_size;
|
||||
let text_size = theme.sizes.small.text_size;
|
||||
let toast = &entry.toast;
|
||||
let toasts = toasts.clone();
|
||||
let id = entry.id;
|
||||
impl ToastEntry {
|
||||
/// The rendered pill for this toast.
|
||||
fn pill(&self, toasts: &Entity<Toasts>, cx: &App) -> gpui::Stateful<gpui::Div> {
|
||||
let theme = cx.theme();
|
||||
let surface = theme.colors.surface;
|
||||
let border = if theme.borders.overlays {
|
||||
theme.colors.border
|
||||
} else {
|
||||
surface
|
||||
};
|
||||
let foreground = theme.colors.foreground;
|
||||
let radius = theme.radius.full;
|
||||
let shadows = theme.elevations.popover.shadows();
|
||||
let icon_size = theme.sizes.small.icon_size;
|
||||
let text_size = theme.sizes.small.text_size;
|
||||
let toast = &self.toast;
|
||||
let toasts = toasts.clone();
|
||||
let id = self.id;
|
||||
|
||||
div()
|
||||
.id(("toast", id))
|
||||
.max_w(px(480.))
|
||||
.flex()
|
||||
.items_center()
|
||||
.py_1p5()
|
||||
.px_3()
|
||||
.bg(surface)
|
||||
.border_1()
|
||||
.border_color(border)
|
||||
.rounded(radius)
|
||||
.shadow(shadows.clone())
|
||||
.when_some(toast.icon.clone(), |pill, icon| {
|
||||
pill.child(
|
||||
div()
|
||||
.id(("toast", id))
|
||||
.role(Role::Alert)
|
||||
.aria_label(toast.message.clone())
|
||||
.max_w(TOAST_MAX_WIDTH)
|
||||
.flex()
|
||||
.items_center()
|
||||
.py_1p5()
|
||||
.px_3()
|
||||
.bg(surface)
|
||||
.border_1()
|
||||
.border_color(border)
|
||||
.rounded(radius)
|
||||
.shadow(shadows.clone())
|
||||
.when_some(toast.icon.clone(), |pill, icon| {
|
||||
pill.child(
|
||||
div()
|
||||
.flex_none()
|
||||
.mr_2()
|
||||
.flex()
|
||||
.items_center()
|
||||
.child(icon.size(icon_size).color(foreground)),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
div()
|
||||
.flex_none()
|
||||
.mr_2()
|
||||
.flex()
|
||||
.items_center()
|
||||
.child(icon.size(icon_size).color(foreground)),
|
||||
.min_w(px(0.))
|
||||
.truncate()
|
||||
.text_size(text_size)
|
||||
.text_color(foreground)
|
||||
.child(toast.message.clone()),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
div()
|
||||
.min_w(px(0.))
|
||||
.truncate()
|
||||
.text_size(text_size)
|
||||
.text_color(foreground)
|
||||
.child(toast.message.clone()),
|
||||
)
|
||||
.when_some(toast.action.clone(), |pill, action| {
|
||||
let toasts = toasts.clone();
|
||||
pill.child(
|
||||
div().flex_none().ml_2p5().child(
|
||||
Button::new(("toast-action", id))
|
||||
.label(action.label.clone())
|
||||
.variant(ButtonVariant::Primary)
|
||||
.when_some(toast.action.clone(), |pill, action| {
|
||||
let toasts = toasts.clone();
|
||||
pill.child(
|
||||
div().flex_none().ml_2p5().child(
|
||||
Button::new(("toast-action", id))
|
||||
.label(action.label.clone())
|
||||
.variant(ButtonVariant::Primary)
|
||||
.small()
|
||||
.on_click(move |_, _window, cx| {
|
||||
(action.handler)(cx);
|
||||
toasts.update(cx, |toasts, cx| {
|
||||
toasts.dismiss(id, cx);
|
||||
});
|
||||
}),
|
||||
),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
div().flex_none().ml_4().child(
|
||||
Button::new(("toast-close", id))
|
||||
.icon(IconRole::Close)
|
||||
.variant(ButtonVariant::Ghost)
|
||||
.small()
|
||||
.accessibility_label("Dismiss")
|
||||
.on_click(move |_, _window, cx| {
|
||||
(action.handler.clone())(cx);
|
||||
toasts.update(cx, |toasts, cx| {
|
||||
toasts.dismiss(id, cx);
|
||||
});
|
||||
}),
|
||||
),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
div()
|
||||
.id(("toast-close", id))
|
||||
.flex_none()
|
||||
.ml_4()
|
||||
.cursor_pointer()
|
||||
.p_1()
|
||||
.rounded(theme.radius.sm)
|
||||
.hover(|style| style.bg(muted))
|
||||
.child(
|
||||
icon(IconRole::Close)
|
||||
.size(dense_icon_size)
|
||||
.color(theme.colors.muted_foreground),
|
||||
)
|
||||
.on_click(move |_, _window, cx| {
|
||||
toasts.update(cx, |toasts, cx| {
|
||||
toasts.dismiss(id, cx);
|
||||
});
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user