Simplify workspace notification code (#23414)

Michael Sloan created

* Remove `NotificationHandle` trait in favor of just passing `AnyView` -
id field wasn't used.

* Remove `show_notification_once`, doesn't seem to be needed for its
only use.

Release Notes:

- N/A

Change summary

crates/workspace/src/notifications.rs | 88 +---------------------------
crates/workspace/src/workspace.rs     | 11 +--
2 files changed, 8 insertions(+), 91 deletions(-)

Detailed changes

crates/workspace/src/notifications.rs 🔗

@@ -1,20 +1,14 @@
 use crate::{Toast, Workspace};
 use anyhow::Context;
 use anyhow::{anyhow, Result};
-use collections::HashMap;
 use gpui::{
-    svg, AnyView, AppContext, AsyncWindowContext, ClipboardItem, DismissEvent, Entity, EntityId,
-    EventEmitter, Global, PromptLevel, Render, ScrollHandle, Task, View, ViewContext,
-    VisualContext, WindowContext,
+    svg, AppContext, AsyncWindowContext, ClipboardItem, DismissEvent, EventEmitter, PromptLevel,
+    Render, ScrollHandle, Task, View, ViewContext, VisualContext, WindowContext,
 };
-use std::{any::TypeId, ops::DerefMut, time::Duration};
+use std::{any::TypeId, time::Duration};
 use ui::{prelude::*, Tooltip};
 use util::ResultExt;
 
-pub fn init(cx: &mut AppContext) {
-    cx.set_global(NotificationTracker::new());
-}
-
 #[derive(Debug, PartialEq, Clone)]
 pub enum NotificationId {
     Unique(TypeId),
@@ -44,81 +38,7 @@ 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(crate) struct NotificationTracker {
-    notifications_sent: HashMap<TypeId, Vec<NotificationId>>,
-}
-
-impl Global for NotificationTracker {}
-
-impl std::ops::Deref for NotificationTracker {
-    type Target = HashMap<TypeId, Vec<NotificationId>>;
-
-    fn deref(&self) -> &Self::Target {
-        &self.notifications_sent
-    }
-}
-
-impl DerefMut for NotificationTracker {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        &mut self.notifications_sent
-    }
-}
-
-impl NotificationTracker {
-    fn new() -> Self {
-        Self {
-            notifications_sent: Default::default(),
-        }
-    }
-}
-
 impl Workspace {
-    pub fn has_shown_notification_once<V: Notification>(
-        &self,
-        id: &NotificationId,
-        cx: &ViewContext<Self>,
-    ) -> bool {
-        cx.global::<NotificationTracker>()
-            .get(&TypeId::of::<V>())
-            .map(|ids| ids.contains(id))
-            .unwrap_or(false)
-    }
-
-    pub fn show_notification_once<V: Notification>(
-        &mut self,
-        id: NotificationId,
-        cx: &mut ViewContext<Self>,
-        build_notification: impl FnOnce(&mut ViewContext<Self>) -> View<V>,
-    ) {
-        if !self.has_shown_notification_once::<V>(&id, cx) {
-            let tracker = cx.global_mut::<NotificationTracker>();
-            let entry = tracker.entry(TypeId::of::<V>()).or_default();
-            entry.push(id.clone());
-            self.show_notification::<V>(id, cx, build_notification)
-        }
-    }
-
     #[cfg(any(test, feature = "test-support"))]
     pub fn notification_ids(&self) -> Vec<NotificationId> {
         self.notifications
@@ -144,7 +64,7 @@ impl Workspace {
             }
         })
         .detach();
-        self.notifications.push((id, Box::new(notification)));
+        self.notifications.push((id, notification.into()));
         cx.notify();
     }
 

crates/workspace/src/workspace.rs 🔗

@@ -47,9 +47,7 @@ use itertools::Itertools;
 use language::{LanguageRegistry, Rope};
 pub use modal_layer::*;
 use node_runtime::NodeRuntime;
-use notifications::{
-    simple_message_notification::MessageNotification, DetachAndPromptErr, NotificationHandle,
-};
+use notifications::{simple_message_notification::MessageNotification, DetachAndPromptErr};
 pub use pane::*;
 pub use pane_group::*;
 pub use persistence::{
@@ -370,7 +368,6 @@ fn prompt_and_open_paths(
 
 pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
     init_settings(cx);
-    notifications::init(cx);
     theme_preview::init(cx);
 
     cx.on_action(Workspace::close_global);
@@ -785,7 +782,7 @@ pub struct Workspace {
     status_bar: View<StatusBar>,
     modal_layer: View<ModalLayer>,
     titlebar_item: Option<AnyView>,
-    notifications: Vec<(NotificationId, Box<dyn NotificationHandle>)>,
+    notifications: Vec<(NotificationId, AnyView)>,
     project: Model<Project>,
     follower_states: HashMap<PeerId, FollowerState>,
     last_leaders_by_pane: HashMap<WeakView<Pane>, PeerId>,
@@ -3640,7 +3637,7 @@ impl Workspace {
                     .children(
                         self.notifications
                             .iter()
-                            .map(|(_, notification)| notification.to_any()),
+                            .map(|(_, notification)| notification.clone().into_any()),
                     ),
             )
         }
@@ -4895,7 +4892,7 @@ fn notify_if_database_failed(workspace: WindowHandle<Workspace>, cx: &mut AsyncA
             if (*db::ALL_FILE_DB_FAILED).load(std::sync::atomic::Ordering::Acquire) {
                 struct DatabaseFailedNotification;
 
-                workspace.show_notification_once(
+                workspace.show_notification(
                     NotificationId::unique::<DatabaseFailedNotification>(),
                     cx,
                     |cx| {