Added user notifications
This commit is contained in:
parent
ffcad4e4e2
commit
a1f273278b
7 changed files with 375 additions and 68 deletions
|
@ -4,6 +4,7 @@
|
|||
/// specific locations.
|
||||
pub mod dock;
|
||||
pub mod item;
|
||||
pub mod notifications;
|
||||
pub mod pane;
|
||||
pub mod pane_group;
|
||||
mod persistence;
|
||||
|
@ -41,7 +42,9 @@ use gpui::{
|
|||
};
|
||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem};
|
||||
use language::LanguageRegistry;
|
||||
|
||||
use log::{error, warn};
|
||||
use notifications::NotificationHandle;
|
||||
pub use pane::*;
|
||||
pub use pane_group::*;
|
||||
use persistence::{model::SerializedItem, DB};
|
||||
|
@ -61,7 +64,10 @@ use theme::{Theme, ThemeRegistry};
|
|||
pub use toolbar::{ToolbarItemLocation, ToolbarItemView};
|
||||
use util::ResultExt;
|
||||
|
||||
use crate::persistence::model::{SerializedPane, SerializedPaneGroup, SerializedWorkspace};
|
||||
use crate::{
|
||||
notifications::simple_message_notification::{MessageNotification, OsOpen},
|
||||
persistence::model::{SerializedPane, SerializedPaneGroup, SerializedWorkspace},
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct RemoveWorktreeFromProject(pub WorktreeId);
|
||||
|
@ -151,6 +157,7 @@ impl_actions!(workspace, [ActivatePane]);
|
|||
pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
|
||||
pane::init(cx);
|
||||
dock::init(cx);
|
||||
notifications::init(cx);
|
||||
|
||||
cx.add_global_action(open);
|
||||
cx.add_global_action({
|
||||
|
@ -453,31 +460,6 @@ impl DelayedDebouncedEditAction {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait Notification: View {
|
||||
fn should_dismiss_notification_on_event(&self, event: &<Self as Entity>::Event) -> bool;
|
||||
}
|
||||
|
||||
pub trait NotificationHandle {
|
||||
fn id(&self) -> usize;
|
||||
fn to_any(&self) -> AnyViewHandle;
|
||||
}
|
||||
|
||||
impl<T: Notification> NotificationHandle for ViewHandle<T> {
|
||||
fn id(&self) -> usize {
|
||||
self.id()
|
||||
}
|
||||
|
||||
fn to_any(&self) -> AnyViewHandle {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&dyn NotificationHandle> for AnyViewHandle {
|
||||
fn from(val: &dyn NotificationHandle) -> Self {
|
||||
val.to_any()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct LeaderState {
|
||||
followers: HashSet<PeerId>,
|
||||
|
@ -732,6 +714,8 @@ impl Workspace {
|
|||
workspace
|
||||
});
|
||||
|
||||
notify_if_database_failed(&workspace, &mut cx);
|
||||
|
||||
// Call open path for each of the project paths
|
||||
// (this will bring them to the front if they were in the serialized workspace)
|
||||
debug_assert!(paths_to_open.len() == project_paths.len());
|
||||
|
@ -1115,45 +1099,6 @@ impl Workspace {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn show_notification<V: Notification>(
|
||||
&mut self,
|
||||
id: usize,
|
||||
cx: &mut ViewContext<Self>,
|
||||
build_notification: impl FnOnce(&mut ViewContext<Self>) -> ViewHandle<V>,
|
||||
) {
|
||||
let type_id = TypeId::of::<V>();
|
||||
if self
|
||||
.notifications
|
||||
.iter()
|
||||
.all(|(existing_type_id, existing_id, _)| {
|
||||
(*existing_type_id, *existing_id) != (type_id, id)
|
||||
})
|
||||
{
|
||||
let notification = build_notification(cx);
|
||||
cx.subscribe(¬ification, move |this, handle, event, cx| {
|
||||
if handle.read(cx).should_dismiss_notification_on_event(event) {
|
||||
this.dismiss_notification(type_id, id, cx);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
self.notifications
|
||||
.push((type_id, id, Box::new(notification)));
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
fn dismiss_notification(&mut self, type_id: TypeId, id: usize, cx: &mut ViewContext<Self>) {
|
||||
self.notifications
|
||||
.retain(|(existing_type_id, existing_id, _)| {
|
||||
if (*existing_type_id, *existing_id) == (type_id, id) {
|
||||
cx.notify();
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn items<'a>(
|
||||
&'a self,
|
||||
cx: &'a AppContext,
|
||||
|
@ -2436,6 +2381,47 @@ impl Workspace {
|
|||
}
|
||||
}
|
||||
|
||||
fn notify_if_database_failed(workspace: &ViewHandle<Workspace>, cx: &mut AsyncAppContext) {
|
||||
if (*db::ALL_FILE_DB_FAILED).load(std::sync::atomic::Ordering::Acquire) {
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
workspace.show_notification_once(0, cx, |cx| {
|
||||
cx.add_view(|_| {
|
||||
MessageNotification::new(
|
||||
indoc::indoc! {"
|
||||
Failed to load any database file :(
|
||||
"},
|
||||
OsOpen("https://github.com/zed-industries/feedback/issues/new?assignees=&labels=defect%2Ctriage&template=2_bug_report.yml".to_string()),
|
||||
"Click to let us know about this error"
|
||||
)
|
||||
})
|
||||
});
|
||||
});
|
||||
} else {
|
||||
let backup_path = (*db::BACKUP_DB_PATH).read();
|
||||
if let Some(backup_path) = &*backup_path {
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
workspace.show_notification_once(0, cx, |cx| {
|
||||
cx.add_view(|_| {
|
||||
let backup_path = backup_path.to_string_lossy();
|
||||
MessageNotification::new(
|
||||
format!(
|
||||
indoc::indoc! {"
|
||||
Database file was corrupted :(
|
||||
Old database backed up to:
|
||||
{}
|
||||
"},
|
||||
backup_path
|
||||
),
|
||||
OsOpen(backup_path.to_string()),
|
||||
"Click to show old database in finder",
|
||||
)
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity for Workspace {
|
||||
type Event = Event;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue