mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-29 05:11:44 +03:00
gpui2: Notifications
This commit is contained in:
parent
700168467e
commit
039c933d8e
@ -1,12 +1,13 @@
|
||||
use gpui::{div, Div, EventEmitter, ParentElement, Render, SemanticVersion, ViewContext};
|
||||
use gpui::{
|
||||
div, DismissEvent, Div, EventEmitter, ParentElement, Render, SemanticVersion, ViewContext,
|
||||
};
|
||||
use menu::Cancel;
|
||||
use workspace::notifications::NotificationEvent;
|
||||
|
||||
pub struct UpdateNotification {
|
||||
_version: SemanticVersion,
|
||||
}
|
||||
|
||||
impl EventEmitter<NotificationEvent> for UpdateNotification {}
|
||||
impl EventEmitter<DismissEvent> for UpdateNotification {}
|
||||
|
||||
impl Render for UpdateNotification {
|
||||
type Element = Div;
|
||||
@ -82,6 +83,6 @@ impl UpdateNotification {
|
||||
}
|
||||
|
||||
pub fn _dismiss(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
|
||||
cx.emit(NotificationEvent::Dismiss);
|
||||
cx.emit(DismissEvent::Dismiss);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
use collections::{CommandPaletteFilter, HashMap};
|
||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||
use gpui::{
|
||||
actions, div, prelude::*, Action, AppContext, Div, EventEmitter, FocusHandle, FocusableView,
|
||||
Keystroke, Manager, ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView,
|
||||
actions, div, prelude::*, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle,
|
||||
FocusableView, Keystroke, ParentElement, Render, Styled, View, ViewContext, VisualContext,
|
||||
WeakView,
|
||||
};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
use std::{
|
||||
@ -68,7 +69,7 @@ impl CommandPalette {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<Manager> for CommandPalette {}
|
||||
impl EventEmitter<DismissEvent> for CommandPalette {}
|
||||
|
||||
impl FocusableView for CommandPalette {
|
||||
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
|
||||
@ -268,7 +269,7 @@ impl PickerDelegate for CommandPaletteDelegate {
|
||||
|
||||
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
||||
self.command_palette
|
||||
.update(cx, |_, cx| cx.emit(Manager::Dismiss))
|
||||
.update(cx, |_, cx| cx.emit(DismissEvent::Dismiss))
|
||||
.log_err();
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,8 @@ use collections::HashMap;
|
||||
use editor::{scroll::autoscroll::Autoscroll, Bias, Editor};
|
||||
use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
|
||||
use gpui::{
|
||||
actions, div, AppContext, Div, EventEmitter, FocusHandle, FocusableView, InteractiveElement,
|
||||
IntoElement, Manager, Model, ParentElement, Render, Styled, Task, View, ViewContext,
|
||||
actions, div, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView,
|
||||
InteractiveElement, IntoElement, Model, ParentElement, Render, Styled, Task, View, ViewContext,
|
||||
VisualContext, WeakView,
|
||||
};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
@ -111,7 +111,7 @@ impl FileFinder {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<Manager> for FileFinder {}
|
||||
impl EventEmitter<DismissEvent> for FileFinder {}
|
||||
impl FocusableView for FileFinder {
|
||||
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
|
||||
self.picker.focus_handle(cx)
|
||||
@ -690,7 +690,7 @@ impl PickerDelegate for FileFinderDelegate {
|
||||
}
|
||||
}
|
||||
finder
|
||||
.update(&mut cx, |_, cx| cx.emit(Manager::Dismiss))
|
||||
.update(&mut cx, |_, cx| cx.emit(DismissEvent::Dismiss))
|
||||
.ok()?;
|
||||
|
||||
Some(())
|
||||
@ -702,7 +702,7 @@ impl PickerDelegate for FileFinderDelegate {
|
||||
|
||||
fn dismissed(&mut self, cx: &mut ViewContext<Picker<FileFinderDelegate>>) {
|
||||
self.file_finder
|
||||
.update(cx, |_, cx| cx.emit(Manager::Dismiss))
|
||||
.update(cx, |_, cx| cx.emit(DismissEvent::Dismiss))
|
||||
.log_err();
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, Editor};
|
||||
use gpui::{
|
||||
actions, div, prelude::*, AppContext, Div, EventEmitter, FocusHandle, FocusableView, Manager,
|
||||
Render, SharedString, Styled, Subscription, View, ViewContext, VisualContext, WindowContext,
|
||||
actions, div, prelude::*, AppContext, DismissEvent, Div, EventEmitter, FocusHandle,
|
||||
FocusableView, Render, SharedString, Styled, Subscription, View, ViewContext, VisualContext,
|
||||
WindowContext,
|
||||
};
|
||||
use text::{Bias, Point};
|
||||
use theme::ActiveTheme;
|
||||
@ -28,7 +29,7 @@ impl FocusableView for GoToLine {
|
||||
self.active_editor.focus_handle(cx)
|
||||
}
|
||||
}
|
||||
impl EventEmitter<Manager> for GoToLine {}
|
||||
impl EventEmitter<DismissEvent> for GoToLine {}
|
||||
|
||||
impl GoToLine {
|
||||
fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
|
||||
@ -88,7 +89,7 @@ impl GoToLine {
|
||||
) {
|
||||
match event {
|
||||
// todo!() this isn't working...
|
||||
editor::EditorEvent::Blurred => cx.emit(Manager::Dismiss),
|
||||
editor::EditorEvent::Blurred => cx.emit(DismissEvent::Dismiss),
|
||||
editor::EditorEvent::BufferEdited { .. } => self.highlight_current_line(cx),
|
||||
_ => {}
|
||||
}
|
||||
@ -123,7 +124,7 @@ impl GoToLine {
|
||||
}
|
||||
|
||||
fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
|
||||
cx.emit(Manager::Dismiss);
|
||||
cx.emit(DismissEvent::Dismiss);
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
|
||||
@ -140,7 +141,7 @@ impl GoToLine {
|
||||
self.prev_scroll_position.take();
|
||||
}
|
||||
|
||||
cx.emit(Manager::Dismiss);
|
||||
cx.emit(DismissEvent::Dismiss);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, Context, FocusableView,
|
||||
ForegroundExecutor, Manager, Model, ModelContext, Render, Result, Task, View, ViewContext,
|
||||
VisualContext, WindowContext, WindowHandle,
|
||||
AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, Context, DismissEvent,
|
||||
FocusableView, ForegroundExecutor, Model, ModelContext, Render, Result, Task, View,
|
||||
ViewContext, VisualContext, WindowContext, WindowHandle,
|
||||
};
|
||||
use anyhow::{anyhow, Context as _};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
@ -326,7 +326,7 @@ impl VisualContext for AsyncWindowContext {
|
||||
V: crate::ManagedView,
|
||||
{
|
||||
self.window.update(self, |_, cx| {
|
||||
view.update(cx, |_, cx| cx.emit(Manager::Dismiss))
|
||||
view.update(cx, |_, cx| cx.emit(DismissEvent::Dismiss))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -611,7 +611,7 @@ impl<'a> VisualContext for VisualTestContext<'a> {
|
||||
{
|
||||
self.window
|
||||
.update(self.cx, |_, cx| {
|
||||
view.update(cx, |_, cx| cx.emit(crate::Manager::Dismiss))
|
||||
view.update(cx, |_, cx| cx.emit(crate::DismissEvent::Dismiss))
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
@ -193,11 +193,11 @@ pub trait FocusableView: 'static + Render {
|
||||
|
||||
/// ManagedView is a view (like a Modal, Popover, Menu, etc.)
|
||||
/// where the lifecycle of the view is handled by another view.
|
||||
pub trait ManagedView: FocusableView + EventEmitter<Manager> {}
|
||||
pub trait ManagedView: FocusableView + EventEmitter<DismissEvent> {}
|
||||
|
||||
impl<M: FocusableView + EventEmitter<Manager>> ManagedView for M {}
|
||||
impl<M: FocusableView + EventEmitter<DismissEvent>> ManagedView for M {}
|
||||
|
||||
pub enum Manager {
|
||||
pub enum DismissEvent {
|
||||
Dismiss,
|
||||
}
|
||||
|
||||
@ -1663,7 +1663,7 @@ impl VisualContext for WindowContext<'_> {
|
||||
where
|
||||
V: ManagedView,
|
||||
{
|
||||
self.update_view(view, |_, cx| cx.emit(Manager::Dismiss))
|
||||
self.update_view(view, |_, cx| cx.emit(DismissEvent::Dismiss))
|
||||
}
|
||||
}
|
||||
|
||||
@ -2349,7 +2349,7 @@ impl<'a, V: 'static> ViewContext<'a, V> {
|
||||
where
|
||||
V: ManagedView,
|
||||
{
|
||||
self.defer(|_, cx| cx.emit(Manager::Dismiss))
|
||||
self.defer(|_, cx| cx.emit(DismissEvent::Dismiss))
|
||||
}
|
||||
|
||||
pub fn listener<E>(
|
||||
|
@ -4,9 +4,9 @@ use std::rc::Rc;
|
||||
use crate::{prelude::*, v_stack, Label, List};
|
||||
use crate::{ListItem, ListSeparator, ListSubHeader};
|
||||
use gpui::{
|
||||
overlay, px, Action, AnchorCorner, AnyElement, AppContext, Bounds, ClickEvent, DispatchPhase,
|
||||
Div, EventEmitter, FocusHandle, FocusableView, IntoElement, LayoutId, ManagedView, Manager,
|
||||
MouseButton, MouseDownEvent, Pixels, Point, Render, View, VisualContext,
|
||||
overlay, px, Action, AnchorCorner, AnyElement, AppContext, Bounds, ClickEvent, DismissEvent,
|
||||
DispatchPhase, Div, EventEmitter, FocusHandle, FocusableView, IntoElement, LayoutId,
|
||||
ManagedView, MouseButton, MouseDownEvent, Pixels, Point, Render, View, VisualContext,
|
||||
};
|
||||
|
||||
pub enum ContextMenuItem {
|
||||
@ -26,7 +26,7 @@ impl FocusableView for ContextMenu {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<Manager> for ContextMenu {}
|
||||
impl EventEmitter<DismissEvent> for ContextMenu {}
|
||||
|
||||
impl ContextMenu {
|
||||
pub fn build(
|
||||
@ -74,11 +74,11 @@ impl ContextMenu {
|
||||
|
||||
pub fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
|
||||
// todo!()
|
||||
cx.emit(Manager::Dismiss);
|
||||
cx.emit(DismissEvent::Dismiss);
|
||||
}
|
||||
|
||||
pub fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
|
||||
cx.emit(Manager::Dismiss);
|
||||
cx.emit(DismissEvent::Dismiss);
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ impl Render for ContextMenu {
|
||||
}
|
||||
ContextMenuItem::Entry(entry, callback) => {
|
||||
let callback = callback.clone();
|
||||
let dismiss = cx.listener(|_, _, cx| cx.emit(Manager::Dismiss));
|
||||
let dismiss = cx.listener(|_, _, cx| cx.emit(DismissEvent::Dismiss));
|
||||
|
||||
ListItem::new(entry.clone())
|
||||
.child(Label::new(entry.clone()))
|
||||
@ -265,7 +265,7 @@ impl<M: ManagedView> Element for MenuHandle<M> {
|
||||
let new_menu = (builder)(cx);
|
||||
let menu2 = menu.clone();
|
||||
cx.subscribe(&new_menu, move |modal, e, cx| match e {
|
||||
&Manager::Dismiss => {
|
||||
&DismissEvent::Dismiss => {
|
||||
*menu2.borrow_mut() = None;
|
||||
cx.notify();
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ use crate::{
|
||||
};
|
||||
use dock::{Dock, DockPosition, Panel, PanelButtons, PanelHandle};
|
||||
use lazy_static::lazy_static;
|
||||
use notifications::{NotificationHandle, NotifyResultExt};
|
||||
use notifications::{simple_message_notification, NotificationHandle, NotifyResultExt};
|
||||
pub use pane::*;
|
||||
pub use pane_group::*;
|
||||
use persistence::{model::SerializedItem, DB};
|
||||
@ -776,7 +776,23 @@ impl Workspace {
|
||||
}),
|
||||
];
|
||||
|
||||
cx.defer(|this, cx| this.update_window_title(cx));
|
||||
cx.defer(|this, cx| {
|
||||
this.update_window_title(cx);
|
||||
|
||||
this.show_notification(0, cx, |cx| {
|
||||
cx.add_view(|_cx| {
|
||||
simple_message_notification::MessageNotification::new(format!(
|
||||
"Error: what happens if this message is very very very very very long "
|
||||
))
|
||||
.with_click_message("Click here because!")
|
||||
})
|
||||
});
|
||||
this.show_notification(1, cx, |cx| {
|
||||
cx.add_view(|_cx| {
|
||||
simple_message_notification::MessageNotification::new(format!("Nope"))
|
||||
})
|
||||
});
|
||||
});
|
||||
Workspace {
|
||||
weak_self: weak_handle.clone(),
|
||||
modal: None,
|
||||
|
@ -1,6 +1,9 @@
|
||||
use crate::{Toast, Workspace};
|
||||
use collections::HashMap;
|
||||
use gpui::{AnyView, AppContext, Entity, EntityId, EventEmitter, Render, View, ViewContext};
|
||||
use gpui::{
|
||||
AnyView, AppContext, AsyncWindowContext, DismissEvent, Entity, EntityId, EventEmitter, Render,
|
||||
View, ViewContext, VisualContext,
|
||||
};
|
||||
use std::{any::TypeId, ops::DerefMut};
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
@ -9,13 +12,9 @@ pub fn init(cx: &mut AppContext) {
|
||||
// simple_message_notification::init(cx);
|
||||
}
|
||||
|
||||
pub enum NotificationEvent {
|
||||
Dismiss,
|
||||
}
|
||||
pub trait Notification: EventEmitter<DismissEvent> + Render {}
|
||||
|
||||
pub trait Notification: EventEmitter<NotificationEvent> + Render {}
|
||||
|
||||
impl<V: EventEmitter<NotificationEvent> + Render> Notification for V {}
|
||||
impl<V: EventEmitter<DismissEvent> + Render> Notification for V {}
|
||||
|
||||
pub trait NotificationHandle: Send {
|
||||
fn id(&self) -> EntityId;
|
||||
@ -107,8 +106,8 @@ impl Workspace {
|
||||
let notification = build_notification(cx);
|
||||
cx.subscribe(
|
||||
¬ification,
|
||||
move |this, handle, event: &NotificationEvent, cx| match event {
|
||||
NotificationEvent::Dismiss => {
|
||||
move |this, handle, event: &DismissEvent, cx| match event {
|
||||
DismissEvent::Dismiss => {
|
||||
this.dismiss_notification_internal(type_id, id, cx);
|
||||
}
|
||||
},
|
||||
@ -120,6 +119,17 @@ impl Workspace {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show_error<E>(&mut self, err: &E, cx: &mut ViewContext<Self>)
|
||||
where
|
||||
E: std::fmt::Debug,
|
||||
{
|
||||
self.show_notification(0, cx, |cx| {
|
||||
cx.build_view(|_cx| {
|
||||
simple_message_notification::MessageNotification::new(format!("Error: {err:?}"))
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub fn dismiss_notification<V: Notification>(&mut self, id: usize, cx: &mut ViewContext<Self>) {
|
||||
let type_id = TypeId::of::<V>();
|
||||
|
||||
@ -166,13 +176,14 @@ impl Workspace {
|
||||
}
|
||||
|
||||
pub mod simple_message_notification {
|
||||
use super::NotificationEvent;
|
||||
use gpui::{AnyElement, AppContext, Div, EventEmitter, Render, TextStyle, ViewContext};
|
||||
use gpui::{
|
||||
div, AnyElement, AppContext, DismissEvent, Div, EventEmitter, InteractiveElement,
|
||||
ParentElement, Render, SharedString, StatefulInteractiveElement, Styled, TextStyle,
|
||||
ViewContext,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use std::{borrow::Cow, sync::Arc};
|
||||
|
||||
// todo!()
|
||||
// actions!(message_notifications, [CancelMessageNotification]);
|
||||
use ui::{h_stack, v_stack, Button, Icon, IconElement, Label, StyledExt};
|
||||
|
||||
#[derive(Clone, Default, Deserialize, PartialEq)]
|
||||
pub struct OsOpen(pub Cow<'static, str>);
|
||||
@ -197,22 +208,22 @@ pub mod simple_message_notification {
|
||||
// }
|
||||
|
||||
enum NotificationMessage {
|
||||
Text(Cow<'static, str>),
|
||||
Text(SharedString),
|
||||
Element(fn(TextStyle, &AppContext) -> AnyElement),
|
||||
}
|
||||
|
||||
pub struct MessageNotification {
|
||||
message: NotificationMessage,
|
||||
on_click: Option<Arc<dyn Fn(&mut ViewContext<Self>) + Send + Sync>>,
|
||||
click_message: Option<Cow<'static, str>>,
|
||||
click_message: Option<SharedString>,
|
||||
}
|
||||
|
||||
impl EventEmitter<NotificationMessage> for MessageNotification {}
|
||||
impl EventEmitter<DismissEvent> for MessageNotification {}
|
||||
|
||||
impl MessageNotification {
|
||||
pub fn new<S>(message: S) -> MessageNotification
|
||||
where
|
||||
S: Into<Cow<'static, str>>,
|
||||
S: Into<SharedString>,
|
||||
{
|
||||
Self {
|
||||
message: NotificationMessage::Text(message.into()),
|
||||
@ -221,19 +232,20 @@ pub mod simple_message_notification {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_element(
|
||||
message: fn(TextStyle, &AppContext) -> AnyElement,
|
||||
) -> MessageNotification {
|
||||
Self {
|
||||
message: NotificationMessage::Element(message),
|
||||
on_click: None,
|
||||
click_message: None,
|
||||
}
|
||||
}
|
||||
// not needed I think (only for the "new panel" toast, which is outdated now)
|
||||
// pub fn new_element(
|
||||
// message: fn(TextStyle, &AppContext) -> AnyElement,
|
||||
// ) -> MessageNotification {
|
||||
// Self {
|
||||
// message: NotificationMessage::Element(message),
|
||||
// on_click: None,
|
||||
// click_message: None,
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn with_click_message<S>(mut self, message: S) -> Self
|
||||
where
|
||||
S: Into<Cow<'static, str>>,
|
||||
S: Into<SharedString>,
|
||||
{
|
||||
self.click_message = Some(message.into());
|
||||
self
|
||||
@ -247,17 +259,43 @@ pub mod simple_message_notification {
|
||||
self
|
||||
}
|
||||
|
||||
// todo!()
|
||||
// pub fn dismiss(&mut self, _: &CancelMessageNotification, cx: &mut ViewContext<Self>) {
|
||||
// cx.emit(MessageNotificationEvent::Dismiss);
|
||||
// }
|
||||
pub fn dismiss(&mut self, cx: &mut ViewContext<Self>) {
|
||||
cx.emit(DismissEvent::Dismiss);
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for MessageNotification {
|
||||
type Element = Div;
|
||||
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||
todo!()
|
||||
v_stack()
|
||||
.elevation_3(cx)
|
||||
.p_4()
|
||||
.child(
|
||||
h_stack()
|
||||
.justify_between()
|
||||
.child(div().max_w_80().child(match &self.message {
|
||||
NotificationMessage::Text(text) => Label::new(text.clone()),
|
||||
NotificationMessage::Element(element) => {
|
||||
todo!()
|
||||
}
|
||||
}))
|
||||
.child(
|
||||
div()
|
||||
.id("cancel")
|
||||
.child(IconElement::new(Icon::Close))
|
||||
.cursor_pointer()
|
||||
.on_click(cx.listener(|this, event, cx| this.dismiss(cx))),
|
||||
),
|
||||
)
|
||||
.children(self.click_message.iter().map(|message| {
|
||||
Button::new(message.clone()).on_click(cx.listener(|this, _, cx| {
|
||||
if let Some(on_click) = this.on_click.as_ref() {
|
||||
(on_click)(cx)
|
||||
};
|
||||
this.dismiss(cx)
|
||||
}))
|
||||
}))
|
||||
}
|
||||
}
|
||||
// todo!()
|
||||
@ -359,8 +397,6 @@ pub mod simple_message_notification {
|
||||
// .into_any()
|
||||
// }
|
||||
// }
|
||||
|
||||
impl EventEmitter<NotificationEvent> for MessageNotification {}
|
||||
}
|
||||
|
||||
pub trait NotifyResultExt {
|
||||
@ -371,6 +407,8 @@ pub trait NotifyResultExt {
|
||||
workspace: &mut Workspace,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) -> Option<Self::Ok>;
|
||||
|
||||
fn notify_async_err(self, cx: &mut AsyncWindowContext) -> Option<Self::Ok>;
|
||||
}
|
||||
|
||||
impl<T, E> NotifyResultExt for Result<T, E>
|
||||
@ -384,14 +422,23 @@ where
|
||||
Ok(value) => Some(value),
|
||||
Err(err) => {
|
||||
log::error!("TODO {err:?}");
|
||||
// todo!()
|
||||
// workspace.show_notification(0, cx, |cx| {
|
||||
// cx.add_view(|_cx| {
|
||||
// simple_message_notification::MessageNotification::new(format!(
|
||||
// "Error: {err:?}",
|
||||
// ))
|
||||
// })
|
||||
// });
|
||||
workspace.show_error(&err, cx);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn notify_async_err(self, cx: &mut AsyncWindowContext) -> Option<T> {
|
||||
match self {
|
||||
Ok(value) => Some(value),
|
||||
Err(err) => {
|
||||
log::error!("TODO {err:?}");
|
||||
cx.update(|view, cx| {
|
||||
if let Ok(workspace) = view.downcast::<Workspace>() {
|
||||
workspace.update(cx, |workspace, cx| workspace.show_error(&err, cx))
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -683,7 +683,21 @@ impl Workspace {
|
||||
}),
|
||||
];
|
||||
|
||||
cx.defer(|this, cx| this.update_window_title(cx));
|
||||
cx.defer(|this, cx| {
|
||||
this.update_window_title(cx);
|
||||
// todo! @nate - these are useful for testing notifications
|
||||
// this.show_error(
|
||||
// &anyhow::anyhow!("what happens if this message is very very very very very long"),
|
||||
// cx,
|
||||
// );
|
||||
|
||||
// this.show_notification(1, cx, |cx| {
|
||||
// cx.build_view(|_cx| {
|
||||
// simple_message_notification::MessageNotification::new(format!("Error:"))
|
||||
// .with_click_message("click here because!")
|
||||
// })
|
||||
// });
|
||||
});
|
||||
Workspace {
|
||||
window_self: window_handle,
|
||||
weak_self: weak_handle.clone(),
|
||||
@ -2566,32 +2580,31 @@ impl Workspace {
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn render_notifications(
|
||||
// &self,
|
||||
// theme: &theme::Workspace,
|
||||
// cx: &AppContext,
|
||||
// ) -> Option<AnyElement<Workspace>> {
|
||||
// if self.notifications.is_empty() {
|
||||
// None
|
||||
// } else {
|
||||
// Some(
|
||||
// Flex::column()
|
||||
// .with_children(self.notifications.iter().map(|(_, _, notification)| {
|
||||
// ChildView::new(notification.as_any(), cx)
|
||||
// .contained()
|
||||
// .with_style(theme.notification)
|
||||
// }))
|
||||
// .constrained()
|
||||
// .with_width(theme.notifications.width)
|
||||
// .contained()
|
||||
// .with_style(theme.notifications.container)
|
||||
// .aligned()
|
||||
// .bottom()
|
||||
// .right()
|
||||
// .into_any(),
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
fn render_notifications(&self, cx: &ViewContext<Self>) -> Option<Div> {
|
||||
if self.notifications.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
div()
|
||||
.absolute()
|
||||
.z_index(100)
|
||||
.right_3()
|
||||
.bottom_3()
|
||||
.w_96()
|
||||
.h_full()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.justify_end()
|
||||
.gap_2()
|
||||
.children(self.notifications.iter().map(|(_, _, notification)| {
|
||||
div()
|
||||
.on_any_mouse_down(|_, cx| cx.stop_propagation())
|
||||
.on_any_mouse_up(|_, cx| cx.stop_propagation())
|
||||
.child(notification.to_any())
|
||||
})),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// // RPC handlers
|
||||
|
||||
@ -3653,7 +3666,6 @@ impl Render for Workspace {
|
||||
.bg(cx.theme().colors().background)
|
||||
.children(self.titlebar_item.clone())
|
||||
.child(
|
||||
// todo! should this be a component a view?
|
||||
div()
|
||||
.id("workspace")
|
||||
.relative()
|
||||
@ -3703,7 +3715,8 @@ impl Render for Workspace {
|
||||
.overflow_hidden()
|
||||
.child(self.right_dock.clone()),
|
||||
),
|
||||
),
|
||||
)
|
||||
.children(self.render_notifications(cx)),
|
||||
)
|
||||
.child(self.status_bar.clone())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user