Export with_type and impl FluentBuilder for Notification. (#154)
This commit is contained in:
parent
57dab4d15a
commit
b3f62bf096
6 changed files with 45 additions and 509 deletions
|
|
@ -485,10 +485,10 @@ impl Render for ModalStory {
|
|||
Button::new("show-notify-warning", cx)
|
||||
.label("Warning Notify...")
|
||||
.on_click(cx.listener(|_, _, cx| {
|
||||
cx.push_notification((
|
||||
NotificationType::Warning,
|
||||
struct WarningNotification;
|
||||
cx.push_notification(Notification::warning(
|
||||
"The network is not stable, please check your connection.",
|
||||
))
|
||||
).id1::<WarningNotification>("test"))
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
|
|
@ -501,7 +501,7 @@ impl Render for ModalStory {
|
|||
Notification::new(
|
||||
"你已经成功保存了文件,但是有一些警告信息需要你注意。",
|
||||
)
|
||||
.type_id::<TestNotification>()
|
||||
.id::<TestNotification>()
|
||||
.title("保存成功")
|
||||
.icon(IconName::Inbox)
|
||||
.autohide(false)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::{any::TypeId, sync::Arc, time::Duration};
|
||||
|
||||
use gpui::{
|
||||
div, prelude::FluentBuilder as _, px, Animation, AnimationExt, ClickEvent, DismissEvent,
|
||||
div, prelude::FluentBuilder, px, Animation, AnimationExt, ClickEvent, DismissEvent, ElementId,
|
||||
EventEmitter, InteractiveElement as _, IntoElement, ParentElement as _, Render, SharedString,
|
||||
StatefulInteractiveElement, Styled, View, ViewContext, VisualContext, WindowContext,
|
||||
};
|
||||
|
|
@ -21,25 +21,19 @@ pub enum NotificationType {
|
|||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub(crate) enum NotificationId {
|
||||
Type(TypeId),
|
||||
Id(SharedString),
|
||||
Id(TypeId),
|
||||
IdAndElementId(TypeId, ElementId),
|
||||
}
|
||||
|
||||
impl From<TypeId> for NotificationId {
|
||||
fn from(type_id: TypeId) -> Self {
|
||||
Self::Type(type_id)
|
||||
Self::Id(type_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SharedString> for NotificationId {
|
||||
fn from(id: SharedString) -> Self {
|
||||
Self::Id(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&'static str> for NotificationId {
|
||||
fn from(id: &'static str) -> Self {
|
||||
Self::Id(id.into())
|
||||
impl From<(TypeId, ElementId)> for NotificationId {
|
||||
fn from((type_id, id): (TypeId, ElementId)) -> Self {
|
||||
Self::IdAndElementId(type_id, id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +45,7 @@ pub struct Notification {
|
|||
id: NotificationId,
|
||||
type_: NotificationType,
|
||||
title: Option<SharedString>,
|
||||
content: SharedString,
|
||||
message: SharedString,
|
||||
icon: Option<Icon>,
|
||||
autohide: bool,
|
||||
on_click: Option<Arc<dyn Fn(&ClickEvent, &mut WindowContext)>>,
|
||||
|
|
@ -81,17 +75,19 @@ impl From<(NotificationType, SharedString)> for Notification {
|
|||
}
|
||||
}
|
||||
|
||||
struct DefaultIdType;
|
||||
impl Notification {
|
||||
/// Create a new notification with the given content.
|
||||
///
|
||||
/// default width is 320px.
|
||||
pub fn new(content: impl Into<SharedString>) -> Self {
|
||||
pub fn new(message: impl Into<SharedString>) -> Self {
|
||||
let id: SharedString = uuid::Uuid::new_v4().to_string().into();
|
||||
let id = (TypeId::of::<DefaultIdType>(), id.into());
|
||||
|
||||
Self {
|
||||
id: id.into(),
|
||||
title: None,
|
||||
content: content.into(),
|
||||
message: message.into(),
|
||||
type_: NotificationType::Info,
|
||||
icon: None,
|
||||
autohide: true,
|
||||
|
|
@ -99,22 +95,36 @@ impl Notification {
|
|||
}
|
||||
}
|
||||
|
||||
/// Set the id of the notification, used to uniquely identify the notification.
|
||||
pub fn id(mut self, id: impl Into<SharedString>) -> Self {
|
||||
let id: SharedString = id.into();
|
||||
self.id = id.into();
|
||||
self
|
||||
pub fn info(message: impl Into<SharedString>) -> Self {
|
||||
Self::new(message).with_type(NotificationType::Info)
|
||||
}
|
||||
|
||||
/// Set the type id of the notification, used to uniquely identify the notification.
|
||||
pub fn success(message: impl Into<SharedString>) -> Self {
|
||||
Self::new(message).with_type(NotificationType::Success)
|
||||
}
|
||||
|
||||
pub fn warning(message: impl Into<SharedString>) -> Self {
|
||||
Self::new(message).with_type(NotificationType::Warning)
|
||||
}
|
||||
|
||||
pub fn error(message: impl Into<SharedString>) -> Self {
|
||||
Self::new(message).with_type(NotificationType::Error)
|
||||
}
|
||||
|
||||
/// Set the type for unique identification of the notification.
|
||||
///
|
||||
/// ```rs
|
||||
/// struct MyNotificationKind;
|
||||
/// let notification = Notification::new("Hello").type_id::<MyNotificationKind>();
|
||||
/// let notification = Notification::new("Hello").id::<MyNotificationKind>();
|
||||
/// ```
|
||||
pub fn type_id<T: Sized + 'static>(mut self) -> Self {
|
||||
let type_id = TypeId::of::<T>();
|
||||
self.id = type_id.into();
|
||||
pub fn id<T: Sized + 'static>(mut self) -> Self {
|
||||
self.id = TypeId::of::<T>().into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the type and id of the notification, used to uniquely identify the notification.
|
||||
pub fn id1<T: Sized + 'static>(mut self, key: impl Into<ElementId>) -> Self {
|
||||
self.id = (TypeId::of::<T>(), key.into()).into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -134,31 +144,12 @@ impl Notification {
|
|||
self
|
||||
}
|
||||
|
||||
fn with_type(mut self, type_: NotificationType) -> Self {
|
||||
/// Set the type of the notification, default is NotificationType::Info.
|
||||
pub fn with_type(mut self, type_: NotificationType) -> Self {
|
||||
self.type_ = type_;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn info(mut self) -> Self {
|
||||
self.type_ = NotificationType::Info;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn success(mut self) -> Self {
|
||||
self.type_ = NotificationType::Success;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn warning(mut self) -> Self {
|
||||
self.type_ = NotificationType::Warning;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn error(mut self) -> Self {
|
||||
self.type_ = NotificationType::Error;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the auto hide of the notification, default is true.
|
||||
pub fn autohide(mut self, autohide: bool) -> Self {
|
||||
self.autohide = autohide;
|
||||
|
|
@ -192,7 +183,7 @@ impl Notification {
|
|||
}
|
||||
}
|
||||
impl EventEmitter<DismissEvent> for Notification {}
|
||||
|
||||
impl FluentBuilder for Notification {}
|
||||
impl Render for Notification {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let group_id = "notification-group";
|
||||
|
|
@ -245,7 +236,7 @@ impl Render for Notification {
|
|||
this.child(div().text_sm().font_semibold().child(title))
|
||||
})
|
||||
.overflow_hidden()
|
||||
.child(div().text_sm().child(self.content.clone())),
|
||||
.child(div().text_sm().child(self.message.clone())),
|
||||
)
|
||||
.when_some(self.on_click.clone(), |this, on_click| {
|
||||
this.cursor_pointer()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
pub mod dock;
|
||||
pub mod item;
|
||||
pub mod model_layer;
|
||||
pub mod notification;
|
||||
pub mod pane;
|
||||
pub mod pane_group;
|
||||
mod title_bar;
|
||||
|
|
|
|||
|
|
@ -1,179 +0,0 @@
|
|||
use gpui::{
|
||||
div, prelude::*, px, AnyView, DismissEvent, FocusHandle, ManagedView, Render, Subscription,
|
||||
View, ViewContext, WindowContext,
|
||||
};
|
||||
use ui::theme::ActiveTheme as _;
|
||||
use ui::{h_flex, v_flex};
|
||||
|
||||
pub enum DismissDecision {
|
||||
Dismiss(bool),
|
||||
Pending,
|
||||
}
|
||||
|
||||
pub trait ModalView: ManagedView {
|
||||
fn on_before_dismiss(&mut self, _: &mut ViewContext<Self>) -> DismissDecision {
|
||||
DismissDecision::Dismiss(true)
|
||||
}
|
||||
|
||||
fn fade_out_background(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
trait ModalViewHandle {
|
||||
fn on_before_dismiss(&mut self, cx: &mut WindowContext) -> DismissDecision;
|
||||
fn view(&self) -> AnyView;
|
||||
fn fade_out_background(&self, cx: &WindowContext) -> bool;
|
||||
}
|
||||
|
||||
impl<V: ModalView> ModalViewHandle for View<V> {
|
||||
fn on_before_dismiss(&mut self, cx: &mut WindowContext) -> DismissDecision {
|
||||
self.update(cx, |this, cx| this.on_before_dismiss(cx))
|
||||
}
|
||||
|
||||
fn view(&self) -> AnyView {
|
||||
self.clone().into()
|
||||
}
|
||||
|
||||
fn fade_out_background(&self, cx: &WindowContext) -> bool {
|
||||
self.read(cx).fade_out_background()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ActiveModal {
|
||||
modal: Box<dyn ModalViewHandle>,
|
||||
_subscriptions: [Subscription; 2],
|
||||
previous_focus_handle: Option<FocusHandle>,
|
||||
focus_handle: FocusHandle,
|
||||
}
|
||||
|
||||
pub struct ModalLayer {
|
||||
active_modal: Option<ActiveModal>,
|
||||
dismiss_on_focus_lost: bool,
|
||||
}
|
||||
|
||||
impl ModalLayer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
active_modal: None,
|
||||
dismiss_on_focus_lost: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toggle_modal<V, B>(&mut self, cx: &mut ViewContext<Self>, build_view: B)
|
||||
where
|
||||
V: ModalView,
|
||||
B: FnOnce(&mut ViewContext<V>) -> V,
|
||||
{
|
||||
if let Some(active_modal) = &self.active_modal {
|
||||
let is_close = active_modal.modal.view().downcast::<V>().is_ok();
|
||||
let did_close = self.hide_modal(cx);
|
||||
if is_close || !did_close {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let new_modal = cx.new_view(build_view);
|
||||
self.show_modal(new_modal, cx);
|
||||
}
|
||||
|
||||
fn show_modal<V>(&mut self, new_modal: View<V>, cx: &mut ViewContext<Self>)
|
||||
where
|
||||
V: ModalView,
|
||||
{
|
||||
let focus_handle = cx.focus_handle();
|
||||
self.active_modal = Some(ActiveModal {
|
||||
modal: Box::new(new_modal.clone()),
|
||||
_subscriptions: [
|
||||
cx.subscribe(&new_modal, |this, _, _: &DismissEvent, cx| {
|
||||
this.hide_modal(cx);
|
||||
}),
|
||||
cx.on_focus_out(&focus_handle, |this, _event, cx| {
|
||||
if this.dismiss_on_focus_lost {
|
||||
this.hide_modal(cx);
|
||||
}
|
||||
}),
|
||||
],
|
||||
previous_focus_handle: cx.focused(),
|
||||
focus_handle,
|
||||
});
|
||||
cx.defer(move |_, cx| {
|
||||
cx.focus_view(&new_modal);
|
||||
});
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn hide_modal(&mut self, cx: &mut ViewContext<Self>) -> bool {
|
||||
let Some(active_modal) = self.active_modal.as_mut() else {
|
||||
self.dismiss_on_focus_lost = false;
|
||||
return false;
|
||||
};
|
||||
|
||||
match active_modal.modal.on_before_dismiss(cx) {
|
||||
DismissDecision::Dismiss(dismiss) => {
|
||||
self.dismiss_on_focus_lost = !dismiss;
|
||||
if !dismiss {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DismissDecision::Pending => {
|
||||
self.dismiss_on_focus_lost = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(active_modal) = self.active_modal.take() {
|
||||
if let Some(previous_focus) = active_modal.previous_focus_handle {
|
||||
if active_modal.focus_handle.contains_focused(cx) {
|
||||
previous_focus.focus(cx);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn active_modal<V>(&self) -> Option<View<V>>
|
||||
where
|
||||
V: 'static,
|
||||
{
|
||||
let active_modal = self.active_modal.as_ref()?;
|
||||
active_modal.modal.view().downcast::<V>().ok()
|
||||
}
|
||||
|
||||
pub fn has_active_modal(&self) -> bool {
|
||||
self.active_modal.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for ModalLayer {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let Some(active_modal) = &self.active_modal else {
|
||||
return div();
|
||||
};
|
||||
|
||||
div()
|
||||
.absolute()
|
||||
.size_full()
|
||||
.top_0()
|
||||
.left_0()
|
||||
.when(active_modal.modal.fade_out_background(cx), |el| {
|
||||
let mut background = cx.theme().popover;
|
||||
background.fade_out(0.2);
|
||||
el.bg(background)
|
||||
.occlude()
|
||||
.on_mouse_down_out(cx.listener(|this, _, cx| {
|
||||
this.hide_modal(cx);
|
||||
}))
|
||||
})
|
||||
.child(
|
||||
v_flex()
|
||||
.h(px(0.0))
|
||||
.top_20()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.items_center()
|
||||
.track_focus(&active_modal.focus_handle)
|
||||
.child(h_flex().occlude().child(active_modal.modal.view())),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,235 +0,0 @@
|
|||
use std::any::TypeId;
|
||||
use std::borrow::Cow;
|
||||
use std::sync::Arc;
|
||||
|
||||
use gpui::{
|
||||
div, AnyView, DismissEvent, ElementId, Entity, EntityId, EventEmitter, InteractiveElement,
|
||||
IntoElement, ParentElement, Render, SharedString, StatefulInteractiveElement, Styled, View,
|
||||
ViewContext, VisualContext, WindowContext,
|
||||
};
|
||||
|
||||
use ui::{h_flex, label::Label, theme::ActiveTheme, v_flex, Icon, IconName};
|
||||
|
||||
use crate::Workspace;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct NotificationId {
|
||||
/// A [`TypeId`] used to uniquely identify this notification.
|
||||
type_id: TypeId,
|
||||
/// A supplementary ID used to distinguish between multiple
|
||||
/// notifications that have the same [`type_id`](Self::type_id);
|
||||
id: Option<ElementId>,
|
||||
}
|
||||
|
||||
impl NotificationId {
|
||||
/// Returns a unique [`NotificationId`] for the given type.
|
||||
pub fn unique<T: 'static>() -> Self {
|
||||
Self {
|
||||
type_id: TypeId::of::<T>(),
|
||||
id: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a [`NotificationId`] for the given type that is also identified
|
||||
/// by the provided ID.
|
||||
pub fn identified<T: 'static>(id: impl Into<ElementId>) -> Self {
|
||||
Self {
|
||||
type_id: TypeId::of::<T>(),
|
||||
id: Some(id.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Workspace {
|
||||
pub fn show_notification<V: Notification>(
|
||||
&mut self,
|
||||
id: NotificationId,
|
||||
cx: &mut ViewContext<Self>,
|
||||
build_notification: impl FnOnce(&mut ViewContext<Self>) -> View<V>,
|
||||
) {
|
||||
self.dismiss_notification_internal(&id, cx);
|
||||
|
||||
let notification = build_notification(cx);
|
||||
cx.subscribe(¬ification, {
|
||||
let id = id.clone();
|
||||
move |this, _, _: &DismissEvent, cx| {
|
||||
this.dismiss_notification_internal(&id, cx);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
self.notifications.push((id, Box::new(notification)));
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn dismiss_notification(&mut self, id: &NotificationId, cx: &mut ViewContext<Self>) {
|
||||
self.dismiss_notification_internal(id, cx)
|
||||
}
|
||||
|
||||
fn dismiss_notification_internal(&mut self, id: &NotificationId, cx: &mut ViewContext<Self>) {
|
||||
self.notifications.retain(|(existing_id, _)| {
|
||||
if existing_id == id {
|
||||
cx.notify();
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn show_toast(&mut self, toast: Toast, cx: &mut ViewContext<Self>) {
|
||||
self.dismiss_notification(&toast.id, cx);
|
||||
self.show_notification(toast.id, cx, |cx| {
|
||||
cx.new_view(|_cx| match toast.on_click.as_ref() {
|
||||
Some((click_msg, on_click)) => {
|
||||
let on_click = on_click.clone();
|
||||
MessageNotification::new(toast.msg.clone())
|
||||
.with_click_message(click_msg.clone())
|
||||
.on_click(move |cx| on_click(cx))
|
||||
}
|
||||
None => MessageNotification::new(toast.msg.clone()),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn dismiss_toast(&mut self, id: &NotificationId, cx: &mut ViewContext<Self>) {
|
||||
self.dismiss_notification(id, cx);
|
||||
}
|
||||
|
||||
pub fn clear_all_notifications(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.notifications.clear();
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Toast {
|
||||
id: NotificationId,
|
||||
msg: Cow<'static, str>,
|
||||
on_click: Option<(Cow<'static, str>, Arc<dyn Fn(&mut WindowContext)>)>,
|
||||
}
|
||||
|
||||
impl Toast {
|
||||
pub fn new<I: Into<Cow<'static, str>>>(id: NotificationId, msg: I) -> Self {
|
||||
Toast {
|
||||
id,
|
||||
msg: msg.into(),
|
||||
on_click: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_click<F, M>(mut self, message: M, on_click: F) -> Self
|
||||
where
|
||||
M: Into<Cow<'static, str>>,
|
||||
F: Fn(&mut WindowContext) + 'static,
|
||||
{
|
||||
self.on_click = Some((message.into(), Arc::new(on_click)));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Toast {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
&& self.msg == other.msg
|
||||
&& self.on_click.is_some() == other.on_click.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Toast {
|
||||
fn clone(&self) -> Self {
|
||||
Toast {
|
||||
id: self.id.clone(),
|
||||
msg: self.msg.clone(),
|
||||
on_click: self.on_click.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Notification: EventEmitter<DismissEvent> + Render {}
|
||||
|
||||
impl<V: EventEmitter<DismissEvent> + Render> Notification for V {}
|
||||
|
||||
pub trait NotificationHandle: Send {
|
||||
fn id(&self) -> EntityId;
|
||||
fn to_any(&self) -> AnyView;
|
||||
}
|
||||
|
||||
impl<T: Notification> NotificationHandle for View<T> {
|
||||
fn id(&self) -> EntityId {
|
||||
self.entity_id()
|
||||
}
|
||||
|
||||
fn to_any(&self) -> AnyView {
|
||||
self.clone().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&dyn NotificationHandle> for AnyView {
|
||||
fn from(val: &dyn NotificationHandle) -> Self {
|
||||
val.to_any()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MessageNotification {
|
||||
message: SharedString,
|
||||
on_click: Option<Arc<dyn Fn(&mut ViewContext<Self>)>>,
|
||||
click_message: Option<SharedString>,
|
||||
}
|
||||
|
||||
impl EventEmitter<DismissEvent> for MessageNotification {}
|
||||
|
||||
impl MessageNotification {
|
||||
pub fn new(message: impl Into<SharedString>) -> Self {
|
||||
Self {
|
||||
message: message.into(),
|
||||
on_click: None,
|
||||
click_message: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_click_message<S>(mut self, message: S) -> Self
|
||||
where
|
||||
S: Into<SharedString>,
|
||||
{
|
||||
self.click_message = Some(message.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_click<F>(mut self, on_click: F) -> Self
|
||||
where
|
||||
F: 'static + Fn(&mut ViewContext<Self>),
|
||||
{
|
||||
self.on_click = Some(Arc::new(on_click));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn dismiss(&mut self, cx: &mut ViewContext<Self>) {
|
||||
cx.emit(DismissEvent);
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for MessageNotification {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.bg(cx.theme().popover)
|
||||
.border_1()
|
||||
.border_color(cx.theme().border)
|
||||
.shadow_xl()
|
||||
.rounded_xl()
|
||||
.p_4()
|
||||
.max_w_80()
|
||||
.bg(cx.theme().background)
|
||||
.child(
|
||||
h_flex()
|
||||
.justify_between()
|
||||
.gap_2()
|
||||
.child(div().max_w_80().child(Label::new(self.message.clone())))
|
||||
.child(
|
||||
div()
|
||||
.id("cancel")
|
||||
.child(Icon::new(IconName::Close))
|
||||
.cursor_pointer()
|
||||
.on_click(cx.listener(|this, _, cx| this.dismiss(cx))),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,6 @@ use std::{
|
|||
|
||||
use crate::{
|
||||
dock::{Panel, PanelHandle},
|
||||
model_layer::ModalLayer,
|
||||
notification::{NotificationHandle, NotificationId},
|
||||
pane_group,
|
||||
};
|
||||
use anyhow::Result;
|
||||
|
|
@ -33,7 +31,6 @@ actions!(
|
|||
[
|
||||
ActivateNextPane,
|
||||
ActivatePreviousPane,
|
||||
ClearAllNotifications,
|
||||
CloseAllDocks,
|
||||
ToggleBottomDock,
|
||||
ToggleCenteredLayout,
|
||||
|
|
@ -83,8 +80,6 @@ pub struct Workspace {
|
|||
pub(crate) zoomed_position: Option<DockPosition>,
|
||||
database_id: Option<WorkspaceId>,
|
||||
bounds: Bounds<Pixels>,
|
||||
pub(crate) notifications: Vec<(NotificationId, Box<dyn NotificationHandle>)>,
|
||||
modal_layer: View<ModalLayer>,
|
||||
workspace_actions: Vec<Box<dyn Fn(Div, &mut ViewContext<Self>) -> Div>>,
|
||||
bounds_save_task_queued: Option<Task<()>>,
|
||||
_subscriptions: Vec<Subscription>,
|
||||
|
|
@ -243,9 +238,7 @@ impl Render for Workspace {
|
|||
Some(DockPosition::Bottom) => div.top_2().border_t_1(),
|
||||
None => div.top_2().bottom_2().left_2().right_2().border_1(),
|
||||
})
|
||||
}))
|
||||
.child(self.modal_layer.clone())
|
||||
.children(self.render_notifications(cx)),
|
||||
})),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -275,8 +268,6 @@ impl Workspace {
|
|||
// let bottom_dock_buttons = cx.new_view(|cx| PanelButtons::new(bottom_dock.clone(), cx));
|
||||
// let right_dock_buttons = cx.new_view(|cx| PanelButtons::new(right_dock.clone(), cx));
|
||||
|
||||
let modal_layer = cx.new_view(|_| ModalLayer::new());
|
||||
|
||||
let subscriptions = vec![
|
||||
cx.observe_window_activation(Self::on_window_activation_changed),
|
||||
cx.observe_window_bounds(move |this, cx| {
|
||||
|
|
@ -337,8 +328,6 @@ impl Workspace {
|
|||
panes_by_item: Default::default(),
|
||||
active_pane: center_pane.clone(),
|
||||
last_active_center_pane: Some(center_pane.downgrade()),
|
||||
modal_layer,
|
||||
notifications: Default::default(),
|
||||
left_dock,
|
||||
bottom_dock,
|
||||
right_dock,
|
||||
|
|
@ -425,11 +414,6 @@ impl Workspace {
|
|||
workspace.close_all_docks(cx);
|
||||
}),
|
||||
)
|
||||
.on_action(
|
||||
cx.listener(|workspace: &mut Workspace, _: &ClearAllNotifications, cx| {
|
||||
workspace.clear_all_notifications(cx);
|
||||
}),
|
||||
)
|
||||
.on_action(cx.listener(Workspace::activate_pane_at_index))
|
||||
.on_action(
|
||||
cx.listener(|_workspace: &mut Workspace, _: &ReopenClosedItem, _cx| {
|
||||
|
|
@ -1020,27 +1004,4 @@ impl Workspace {
|
|||
// }));
|
||||
// }
|
||||
}
|
||||
|
||||
fn render_notifications(&self, _cx: &ViewContext<Self>) -> Option<Div> {
|
||||
if self.notifications.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
div()
|
||||
.absolute()
|
||||
.right_3()
|
||||
.bottom_3()
|
||||
.h_full()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.justify_end()
|
||||
.gap_2()
|
||||
.children(
|
||||
self.notifications
|
||||
.iter()
|
||||
.map(|(_, notification)| notification.to_any()),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue