diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 74fad79fe8..7c7909fed0 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -23,7 +23,7 @@ use util::{ test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker}, }; use workspace::{ - item::{FollowableItem, ItemHandle}, + item::{FollowableItem, Item, ItemHandle}, NavigationEntry, Pane, ViewId, }; @@ -3973,7 +3973,7 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) { editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); assert!(cx.read(|cx| editor.is_dirty(cx))); - let save = cx.update(|cx| editor.save(project.clone(), cx)); + let save = editor.update(cx, |editor, cx| editor.save(project.clone(), cx)); fake_server .handle_request::(move |params, _| async move { assert_eq!( @@ -4008,7 +4008,7 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) { futures::future::pending::<()>().await; unreachable!() }); - let save = cx.update(|cx| editor.save(project.clone(), cx)); + let save = editor.update(cx, |editor, cx| editor.save(project.clone(), cx)); cx.foreground().advance_clock(super::FORMAT_TIMEOUT); cx.foreground().start_waiting(); save.await.unwrap(); @@ -4031,7 +4031,7 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) { }) }); - let save = cx.update(|cx| editor.save(project.clone(), cx)); + let save = editor.update(cx, |editor, cx| editor.save(project.clone(), cx)); fake_server .handle_request::(move |params, _| async move { assert_eq!( @@ -4087,7 +4087,7 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) { editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); assert!(cx.read(|cx| editor.is_dirty(cx))); - let save = cx.update(|cx| editor.save(project.clone(), cx)); + let save = editor.update(cx, |editor, cx| editor.save(project.clone(), cx)); fake_server .handle_request::(move |params, _| async move { assert_eq!( @@ -4124,7 +4124,7 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) { unreachable!() }, ); - let save = cx.update(|cx| editor.save(project.clone(), cx)); + let save = editor.update(cx, |editor, cx| editor.save(project.clone(), cx)); cx.foreground().advance_clock(super::FORMAT_TIMEOUT); cx.foreground().start_waiting(); save.await.unwrap(); @@ -4147,7 +4147,7 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) { }) }); - let save = cx.update(|cx| editor.save(project.clone(), cx)); + let save = editor.update(cx, |editor, cx| editor.save(project.clone(), cx)); fake_server .handle_request::(move |params, _| async move { assert_eq!( diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 820a593e17..53b131d53b 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -352,7 +352,7 @@ impl AsyncAppContext { self.0.borrow_mut().update(callback) } - fn update_window T>( + pub fn update_window T>( &mut self, window_id: usize, callback: F, diff --git a/crates/workspace/src/item.rs b/crates/workspace/src/item.rs index 179555b48f..32e414aa3a 100644 --- a/crates/workspace/src/item.rs +++ b/crates/workspace/src/item.rs @@ -17,7 +17,7 @@ use anyhow::Result; use client::{proto, Client}; use gpui::{ fonts::HighlightStyle, AnyViewHandle, AppContext, Element, ModelHandle, Task, View, - ViewContext, ViewHandle, WeakViewHandle, + ViewContext, ViewHandle, WeakViewHandle, WindowContext, }; use project::{Project, ProjectEntryId, ProjectPath}; use settings::{Autosave, Settings}; @@ -170,7 +170,7 @@ pub trait Item: View { pub trait ItemHandle: 'static + fmt::Debug { fn subscribe_to_item_events( &self, - cx: &mut AppContext, + cx: &mut WindowContext, handler: Box, ) -> gpui::Subscription; fn tab_description<'a>(&self, detail: usize, cx: &'a AppContext) -> Option>; @@ -189,7 +189,7 @@ pub trait ItemHandle: 'static + fmt::Debug { fn clone_on_split( &self, workspace_id: WorkspaceId, - cx: &mut AppContext, + cx: &mut WindowContext, ) -> Option>; fn added_to_pane( &self, @@ -197,27 +197,27 @@ pub trait ItemHandle: 'static + fmt::Debug { pane: ViewHandle, cx: &mut ViewContext, ); - fn deactivated(&self, cx: &mut AppContext); - fn workspace_deactivated(&self, cx: &mut AppContext); - fn navigate(&self, data: Box, cx: &mut AppContext) -> bool; + fn deactivated(&self, cx: &mut WindowContext); + fn workspace_deactivated(&self, cx: &mut WindowContext); + fn navigate(&self, data: Box, cx: &mut WindowContext) -> bool; fn id(&self) -> usize; fn window_id(&self) -> usize; fn as_any(&self) -> &AnyViewHandle; fn is_dirty(&self, cx: &AppContext) -> bool; fn has_conflict(&self, cx: &AppContext) -> bool; fn can_save(&self, cx: &AppContext) -> bool; - fn save(&self, project: ModelHandle, cx: &mut AppContext) -> Task>; + fn save(&self, project: ModelHandle, cx: &mut WindowContext) -> Task>; fn save_as( &self, project: ModelHandle, abs_path: PathBuf, - cx: &mut AppContext, + cx: &mut WindowContext, ) -> Task>; - fn reload(&self, project: ModelHandle, cx: &mut AppContext) -> Task>; + fn reload(&self, project: ModelHandle, cx: &mut WindowContext) -> Task>; fn git_diff_recalc( &self, project: ModelHandle, - cx: &mut AppContext, + cx: &mut WindowContext, ) -> Task>; fn act_as_type<'a>(&'a self, type_id: TypeId, cx: &'a AppContext) -> Option<&'a AnyViewHandle>; fn to_followable_item_handle(&self, cx: &AppContext) -> Option>; @@ -253,7 +253,7 @@ impl dyn ItemHandle { impl ItemHandle for ViewHandle { fn subscribe_to_item_events( &self, - cx: &mut AppContext, + cx: &mut WindowContext, handler: Box, ) -> gpui::Subscription { cx.subscribe(self, move |_, event, cx| { @@ -320,7 +320,7 @@ impl ItemHandle for ViewHandle { fn clone_on_split( &self, workspace_id: WorkspaceId, - cx: &mut AppContext, + cx: &mut WindowContext, ) -> Option> { self.update(cx, |item, cx| { cx.add_option_view(|cx| item.clone_on_split(workspace_id, cx)) @@ -435,16 +435,9 @@ impl ItemHandle for ViewHandle { { let delay = Duration::from_millis(milliseconds); let item = item.clone(); - pending_autosave.fire_new( - delay, - workspace, - cx, - |project, mut cx| async move { - cx.update(|cx| Pane::autosave_item(&item, project, cx)) - .await - .log_err(); - }, - ); + pending_autosave.fire_new(delay, cx, move |workspace, cx| { + Pane::autosave_item(&item, workspace.project().clone(), cx) + }); } let settings = cx.global::(); @@ -460,22 +453,24 @@ impl ItemHandle for ViewHandle { pending_git_update.fire_new( duration, - workspace, cx, - |project, mut cx| async move { - cx.update(|cx| item.git_diff_recalc(project, cx)) - .await - .log_err(); + move |workspace, cx| { + item.git_diff_recalc(workspace.project().clone(), cx) }, ); } else { - let project = workspace.project().downgrade(); - cx.spawn_weak(|_, mut cx| async move { - if let Some(project) = project.upgrade(&cx) { - cx.update(|cx| item.git_diff_recalc(project, cx)) - .await - .log_err(); - } + cx.spawn_weak(|workspace, mut cx| async move { + workspace + .upgrade(&cx)? + .update(&mut cx, |workspace, cx| { + item.git_diff_recalc( + workspace.project().clone(), + cx, + ) + }) + .await + .log_err()?; + Some(()) }) .detach(); } @@ -507,15 +502,15 @@ impl ItemHandle for ViewHandle { }); } - fn deactivated(&self, cx: &mut AppContext) { + fn deactivated(&self, cx: &mut WindowContext) { self.update(cx, |this, cx| this.deactivated(cx)); } - fn workspace_deactivated(&self, cx: &mut AppContext) { + fn workspace_deactivated(&self, cx: &mut WindowContext) { self.update(cx, |this, cx| this.workspace_deactivated(cx)); } - fn navigate(&self, data: Box, cx: &mut AppContext) -> bool { + fn navigate(&self, data: Box, cx: &mut WindowContext) -> bool { self.update(cx, |this, cx| this.navigate(data, cx)) } @@ -543,7 +538,7 @@ impl ItemHandle for ViewHandle { self.read(cx).can_save(cx) } - fn save(&self, project: ModelHandle, cx: &mut AppContext) -> Task> { + fn save(&self, project: ModelHandle, cx: &mut WindowContext) -> Task> { self.update(cx, |item, cx| item.save(project, cx)) } @@ -551,19 +546,19 @@ impl ItemHandle for ViewHandle { &self, project: ModelHandle, abs_path: PathBuf, - cx: &mut AppContext, + cx: &mut WindowContext, ) -> Task> { self.update(cx, |item, cx| item.save_as(project, abs_path, cx)) } - fn reload(&self, project: ModelHandle, cx: &mut AppContext) -> Task> { + fn reload(&self, project: ModelHandle, cx: &mut WindowContext) -> Task> { self.update(cx, |item, cx| item.reload(project, cx)) } fn git_diff_recalc( &self, project: ModelHandle, - cx: &mut AppContext, + cx: &mut WindowContext, ) -> Task> { self.update(cx, |item, cx| item.git_diff_recalc(project, cx)) } diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 9bdcacb91c..7f937d9aed 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -24,7 +24,7 @@ use gpui::{ keymap_matcher::KeymapContext, platform::{CursorStyle, MouseButton, NavigationDirection, PromptLevel}, Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, ModelHandle, - MouseRegion, Quad, Task, View, ViewContext, ViewHandle, WeakViewHandle, + MouseRegion, Quad, Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext, }; use project::{Project, ProjectEntryId, ProjectPath}; use serde::Deserialize; @@ -1106,8 +1106,8 @@ impl Pane { ) }); match answer.next().await { - Some(0) => cx.update(|cx| item.save(project, cx)).await?, - Some(1) => cx.update(|cx| item.reload(project, cx)).await?, + Some(0) => pane.update(cx, |_, cx| item.save(project, cx)).await?, + Some(1) => pane.update(cx, |_, cx| item.reload(project, cx)).await?, _ => return Ok(false), } } else if is_dirty && (can_save || is_singleton) { @@ -1137,7 +1137,7 @@ impl Pane { if should_save { if can_save { - cx.update(|cx| item.save(project, cx)).await?; + pane.update(cx, |_, cx| item.save(project, cx)).await?; } else if is_singleton { let start_abs_path = project .read_with(cx, |project, cx| { @@ -1148,7 +1148,8 @@ impl Pane { let mut abs_path = cx.update(|cx| cx.prompt_for_new_path(&start_abs_path)); if let Some(abs_path) = abs_path.next().await.flatten() { - cx.update(|cx| item.save_as(project, abs_path, cx)).await?; + pane.update(cx, |_, cx| item.save_as(project, abs_path, cx)) + .await?; } else { return Ok(false); } @@ -1166,7 +1167,7 @@ impl Pane { pub fn autosave_item( item: &dyn ItemHandle, project: ModelHandle, - cx: &mut AppContext, + cx: &mut WindowContext, ) -> Task> { if Self::can_autosave_item(item, cx) { item.save(project, cx) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index f65fb0077f..ded8b05a13 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -561,27 +561,19 @@ impl DelayedDebouncedEditAction { } } - fn fire_new( - &mut self, - delay: Duration, - workspace: &Workspace, - cx: &mut ViewContext, - f: F, - ) where - F: FnOnce(ModelHandle, AsyncAppContext) -> Fut + 'static, - Fut: 'static + Future, + fn fire_new(&mut self, delay: Duration, cx: &mut ViewContext, f: F) + where + F: 'static + FnOnce(&mut Workspace, &mut ViewContext) -> Task>, { if let Some(channel) = self.cancel_channel.take() { _ = channel.send(()); } - let project = workspace.project().downgrade(); - let (sender, mut receiver) = oneshot::channel::<()>(); self.cancel_channel = Some(sender); let previous_task = self.task.take(); - self.task = Some(cx.spawn_weak(|_, cx| async move { + self.task = Some(cx.spawn_weak(|workspace, mut cx| async move { let mut timer = cx.background().timer(delay).fuse(); if let Some(previous_task) = previous_task { previous_task.await; @@ -592,8 +584,11 @@ impl DelayedDebouncedEditAction { _ = timer => {} } - if let Some(project) = project.upgrade(&cx) { - (f)(project, cx).await; + if let Some(workspace) = workspace.upgrade(&cx) { + workspace + .update(&mut cx, |workspace, cx| (f)(workspace, cx)) + .await + .log_err(); } })); } @@ -1412,15 +1407,16 @@ impl Workspace { CONFLICT_MESSAGE, &["Overwrite", "Cancel"], ); - cx.spawn(|_, mut cx| async move { + cx.spawn(|this, mut cx| async move { let answer = answer.recv().await; if answer == Some(0) { - cx.update(|cx| item.save(project, cx)).await?; + this.update(&mut cx, |this, cx| item.save(this.project.clone(), cx)) + .await?; } Ok(()) }) } else { - item.save(project, cx) + item.save(self.project.clone(), cx) } } else if item.is_singleton(cx) { let worktree = self.worktrees(cx).next(); @@ -1429,9 +1425,10 @@ impl Workspace { .map_or(Path::new(""), |w| w.abs_path()) .to_path_buf(); let mut abs_path = cx.prompt_for_new_path(&start_abs_path); - cx.spawn(|_, mut cx| async move { + cx.spawn(|this, mut cx| async move { if let Some(abs_path) = abs_path.recv().await.flatten() { - cx.update(|cx| item.save_as(project, abs_path, cx)).await?; + this.update(&mut cx, |_, cx| item.save_as(project, abs_path, cx)) + .await?; } Ok(()) })