Remove `Toast` and `DismissToast` internal actions

Antonio Scandurra created

Change summary

crates/copilot/src/copilot.rs               |  2 
crates/copilot_button/src/copilot_button.rs | 87 +++++++++++++---------
crates/workspace/src/notifications.rs       | 28 ++++++-
crates/workspace/src/workspace.rs           | 31 --------
4 files changed, 75 insertions(+), 73 deletions(-)

Detailed changes

crates/copilot/src/copilot.rs 🔗

@@ -443,7 +443,7 @@ impl Copilot {
         }
     }
 
-    fn sign_in(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+    pub fn sign_in(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
         if let CopilotServer::Running(server) = &mut self.server {
             let task = match &server.sign_in_status {
                 SignInStatus::Authorized { .. } | SignInStatus::Unauthorized { .. } => {

crates/copilot_button/src/copilot_button.rs 🔗

@@ -10,12 +10,13 @@ use gpui::{
     ViewHandle,
 };
 use settings::{settings_file::SettingsFile, Settings};
+use util::ResultExt;
 use workspace::{
-    item::ItemHandle, notifications::simple_message_notification::OsOpen, DismissToast,
-    StatusItemView,
+    item::ItemHandle, notifications::simple_message_notification::OsOpen, StatusItemView, Toast,
+    Workspace,
 };
 
-use copilot::{Copilot, Reinstall, SignIn, SignOut, Status};
+use copilot::{Copilot, Reinstall, SignOut, Status};
 
 const COPILOT_SETTINGS_URL: &str = "https://github.com/settings/copilot";
 const COPILOT_STARTING_TOAST_ID: usize = 1337;
@@ -101,41 +102,43 @@ pub fn init(cx: &mut AppContext) {
 
         match status {
             Status::Starting { task } => {
-                cx.dispatch_action(workspace::Toast::new(
-                    COPILOT_STARTING_TOAST_ID,
-                    "Copilot is starting...",
-                ));
-                let window_id = cx.window_id();
-                let task = task.to_owned();
-                cx.spawn(|handle, mut cx| async move {
+                let Some(workspace) = cx.root_view().clone().downcast::<Workspace>() else {
+                    return;
+                };
+
+                workspace.update(cx, |workspace, cx| {
+                    workspace.show_toast(
+                        Toast::new(COPILOT_STARTING_TOAST_ID, "Copilot is starting..."),
+                        cx,
+                    )
+                });
+                let workspace = workspace.downgrade();
+                cx.spawn(|_, mut cx| async move {
                     task.await;
-                    cx.update(|cx| {
-                        if let Some(copilot) = Copilot::global(cx) {
-                            let status = copilot.read(cx).status();
-                            match status {
-                                Status::Authorized => cx.dispatch_action_at(
-                                    window_id,
-                                    handle.id(),
-                                    workspace::Toast::new(
-                                        COPILOT_STARTING_TOAST_ID,
-                                        "Copilot has started!",
-                                    ),
+                    if let Some(copilot) = cx.read(Copilot::global) {
+                        workspace
+                            .update(&mut cx, |workspace, cx| match copilot.read(cx).status() {
+                                Status::Authorized => workspace.show_toast(
+                                    Toast::new(COPILOT_STARTING_TOAST_ID, "Copilot has started!"),
+                                    cx,
                                 ),
                                 _ => {
-                                    cx.dispatch_action_at(
-                                        window_id,
-                                        handle.id(),
-                                        DismissToast::new(COPILOT_STARTING_TOAST_ID),
-                                    );
-                                    cx.dispatch_action_at(window_id, handle.id(), SignIn)
+                                    workspace.dismiss_toast(COPILOT_STARTING_TOAST_ID, cx);
+                                    copilot
+                                        .update(cx, |copilot, cx| copilot.sign_in(cx))
+                                        .detach_and_log_err(cx);
                                 }
-                            }
-                        }
-                    })
+                            })
+                            .log_err();
+                    }
                 })
                 .detach();
             }
-            _ => cx.dispatch_action(SignIn),
+            _ => {
+                copilot
+                    .update(cx, |copilot, cx| copilot.sign_in(cx))
+                    .detach_and_log_err(cx);
+            }
         }
     })
 }
@@ -219,12 +222,22 @@ impl View for CopilotButton {
                     let status = status.clone();
                     move |_, _, cx| match status {
                         Status::Authorized => cx.dispatch_action(DeployCopilotMenu),
-                        Status::Error(ref e) => cx.dispatch_action(workspace::Toast::new_action(
-                            COPILOT_ERROR_TOAST_ID,
-                            format!("Copilot can't be started: {}", e),
-                            "Reinstall Copilot",
-                            Reinstall,
-                        )),
+                        Status::Error(ref e) => {
+                            if let Some(workspace) = cx.root_view().clone().downcast::<Workspace>()
+                            {
+                                workspace.update(cx, |workspace, cx| {
+                                    workspace.show_toast(
+                                        Toast::new_action(
+                                            COPILOT_ERROR_TOAST_ID,
+                                            format!("Copilot can't be started: {}", e),
+                                            "Reinstall Copilot",
+                                            Reinstall,
+                                        ),
+                                        cx,
+                                    );
+                                });
+                            }
+                        }
                         _ => cx.dispatch_action(DeployCopilotStartMenu),
                     }
                 })

crates/workspace/src/notifications.rs 🔗

@@ -1,9 +1,7 @@
-use std::{any::TypeId, ops::DerefMut};
-
+use crate::{Toast, Workspace};
 use collections::HashSet;
 use gpui::{AnyViewHandle, AppContext, Entity, View, ViewContext, ViewHandle};
-
-use crate::Workspace;
+use std::{any::TypeId, ops::DerefMut};
 
 pub fn init(cx: &mut AppContext) {
     cx.set_global(NotificationTracker::new());
@@ -113,6 +111,28 @@ impl Workspace {
         self.dismiss_notification_internal(type_id, id, cx)
     }
 
+    pub fn show_toast(&mut self, toast: Toast, cx: &mut ViewContext<Self>) {
+        self.dismiss_notification::<simple_message_notification::MessageNotification>(toast.id, cx);
+        self.show_notification(toast.id, cx, |cx| {
+            cx.add_view(|_cx| match &toast.click {
+                Some((click_msg, action)) => {
+                    simple_message_notification::MessageNotification::new_boxed_action(
+                        toast.msg.clone(),
+                        action.boxed_clone(),
+                        click_msg.clone(),
+                    )
+                }
+                None => {
+                    simple_message_notification::MessageNotification::new_message(toast.msg.clone())
+                }
+            })
+        })
+    }
+
+    pub fn dismiss_toast(&mut self, id: usize, cx: &mut ViewContext<Self>) {
+        self.dismiss_notification::<simple_message_notification::MessageNotification>(id, cx);
+    }
+
     fn dismiss_notification_internal(
         &mut self,
         type_id: TypeId,

crates/workspace/src/workspace.rs 🔗

@@ -220,17 +220,6 @@ impl Clone for Toast {
     }
 }
 
-#[derive(Clone, PartialEq)]
-pub struct DismissToast {
-    id: usize,
-}
-
-impl DismissToast {
-    pub fn new(id: usize) -> Self {
-        DismissToast { id }
-    }
-}
-
 pub type WorkspaceId = i64;
 
 impl_internal_actions!(
@@ -244,8 +233,6 @@ impl_internal_actions!(
         SplitWithItem,
         SplitWithProjectEntry,
         OpenProjectEntryInPane,
-        Toast,
-        DismissToast
     ]
 );
 impl_actions!(workspace, [ActivatePane]);
@@ -431,24 +418,6 @@ pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
         .detach();
     });
 
-    cx.add_action(|workspace: &mut Workspace, alert: &Toast, cx| {
-        workspace.dismiss_notification::<MessageNotification>(alert.id, cx);
-        workspace.show_notification(alert.id, cx, |cx| {
-            cx.add_view(|_cx| match &alert.click {
-                Some((click_msg, action)) => MessageNotification::new_boxed_action(
-                    alert.msg.clone(),
-                    action.boxed_clone(),
-                    click_msg.clone(),
-                ),
-                None => MessageNotification::new_message(alert.msg.clone()),
-            })
-        })
-    });
-
-    cx.add_action(|workspace: &mut Workspace, alert: &DismissToast, cx| {
-        workspace.dismiss_notification::<MessageNotification>(alert.id, cx);
-    });
-
     let client = &app_state.client;
     client.add_view_request_handler(Workspace::handle_follow);
     client.add_view_message_handler(Workspace::handle_unfollow);