Merge branch 'main' into collab-panel

This commit is contained in:
Mikayla 2023-08-09 10:37:22 -07:00
commit 99daa73325
No known key found for this signature in database
93 changed files with 1908 additions and 1442 deletions

View file

@ -213,7 +213,7 @@ impl Dock {
pub fn panel_index_for_ui_name(&self, ui_name: &str, cx: &AppContext) -> Option<usize> {
self.panel_entries.iter().position(|entry| {
let panel = entry.panel.as_any();
cx.view_ui_name(panel.window_id(), panel.id()) == Some(ui_name)
cx.view_ui_name(panel.window(), panel.id()) == Some(ui_name)
})
}
@ -542,16 +542,15 @@ impl View for PanelButtons {
tooltip_action.as_ref().map(|action| action.boxed_clone());
move |_, this, cx| {
if let Some(tooltip_action) = &tooltip_action {
let window_id = cx.window_id();
let window = cx.window();
let view_id = this.workspace.id();
let tooltip_action = tooltip_action.boxed_clone();
cx.spawn(|_, mut cx| async move {
cx.dispatch_action(
window_id,
window.dispatch_action(
view_id,
&*tooltip_action,
)
.ok();
&mut cx,
);
})
.detach();
}

View file

@ -6,6 +6,7 @@ use crate::{AutosaveSetting, DelayedDebouncedEditAction, WorkspaceSettings};
use anyhow::Result;
use client::{proto, Client};
use gpui::geometry::vector::Vector2F;
use gpui::AnyWindowHandle;
use gpui::{
fonts::HighlightStyle, AnyElement, AnyViewHandle, AppContext, ModelHandle, Task, View,
ViewContext, ViewHandle, WeakViewHandle, WindowContext,
@ -250,7 +251,7 @@ pub trait ItemHandle: 'static + fmt::Debug {
fn workspace_deactivated(&self, cx: &mut WindowContext);
fn navigate(&self, data: Box<dyn Any>, cx: &mut WindowContext) -> bool;
fn id(&self) -> usize;
fn window_id(&self) -> usize;
fn window(&self) -> AnyWindowHandle;
fn as_any(&self) -> &AnyViewHandle;
fn is_dirty(&self, cx: &AppContext) -> bool;
fn has_conflict(&self, cx: &AppContext) -> bool;
@ -280,7 +281,7 @@ pub trait ItemHandle: 'static + fmt::Debug {
pub trait WeakItemHandle {
fn id(&self) -> usize;
fn window_id(&self) -> usize;
fn window(&self) -> AnyWindowHandle;
fn upgrade(&self, cx: &AppContext) -> Option<Box<dyn ItemHandle>>;
}
@ -542,8 +543,8 @@ impl<T: Item> ItemHandle for ViewHandle<T> {
self.id()
}
fn window_id(&self) -> usize {
self.window_id()
fn window(&self) -> AnyWindowHandle {
AnyViewHandle::window(self)
}
fn as_any(&self) -> &AnyViewHandle {
@ -649,8 +650,8 @@ impl<T: Item> WeakItemHandle for WeakViewHandle<T> {
self.id()
}
fn window_id(&self) -> usize {
self.window_id()
fn window(&self) -> AnyWindowHandle {
self.window()
}
fn upgrade(&self, cx: &AppContext) -> Option<Box<dyn ItemHandle>> {

View file

@ -25,8 +25,8 @@ use gpui::{
keymap_matcher::KeymapContext,
platform::{CursorStyle, MouseButton, NavigationDirection, PromptLevel},
Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext,
LayoutContext, ModelHandle, MouseRegion, Quad, Task, View, ViewContext, ViewHandle,
WeakViewHandle, WindowContext,
LayoutContext, ModelHandle, MouseRegion, PaintContext, Quad, Task, View, ViewContext,
ViewHandle, WeakViewHandle, WindowContext,
};
use project::{Project, ProjectEntryId, ProjectPath};
use serde::Deserialize;
@ -1900,7 +1900,7 @@ impl<V: View> Element<V> for PaneBackdrop<V> {
visible_bounds: RectF,
_: &mut Self::LayoutState,
view: &mut V,
cx: &mut ViewContext<V>,
cx: &mut PaintContext<V>,
) -> Self::PaintState {
let background = theme::current(cx).editor.background;
@ -1917,8 +1917,8 @@ impl<V: View> Element<V> for PaneBackdrop<V> {
MouseRegion::new::<Self>(child_view_id, 0, visible_bounds).on_down(
gpui::platform::MouseButton::Left,
move |_, _: &mut V, cx| {
let window_id = cx.window_id();
cx.app_context().focus(window_id, Some(child_view_id))
let window = cx.window();
cx.app_context().focus(window, Some(child_view_id))
},
),
);

View file

@ -28,11 +28,11 @@ where
let drag_and_drop = cx.global::<DragAndDrop<Workspace>>();
let drag_position = if (pane.can_drop)(drag_and_drop, cx) {
drag_and_drop
.currently_dragged::<DraggedItem>(cx.window_id())
.currently_dragged::<DraggedItem>(cx.window())
.map(|(drag_position, _)| drag_position)
.or_else(|| {
drag_and_drop
.currently_dragged::<ProjectEntryId>(cx.window_id())
.currently_dragged::<ProjectEntryId>(cx.window())
.map(|(drag_position, _)| drag_position)
})
} else {
@ -91,10 +91,10 @@ where
let drag_and_drop = cx.global::<DragAndDrop<Workspace>>();
if drag_and_drop
.currently_dragged::<DraggedItem>(cx.window_id())
.currently_dragged::<DraggedItem>(cx.window())
.is_some()
|| drag_and_drop
.currently_dragged::<ProjectEntryId>(cx.window_id())
.currently_dragged::<ProjectEntryId>(cx.window())
.is_some()
{
cx.notify();
@ -122,11 +122,11 @@ pub fn handle_dropped_item<V: View>(
}
let drag_and_drop = cx.global::<DragAndDrop<Workspace>>();
let action = if let Some((_, dragged_item)) =
drag_and_drop.currently_dragged::<DraggedItem>(cx.window_id())
drag_and_drop.currently_dragged::<DraggedItem>(cx.window())
{
Action::Move(dragged_item.pane.clone(), dragged_item.handle.id())
} else if let Some((_, project_entry)) =
drag_and_drop.currently_dragged::<ProjectEntryId>(cx.window_id())
drag_and_drop.currently_dragged::<ProjectEntryId>(cx.window())
{
Action::Open(*project_entry)
} else {

View file

@ -595,7 +595,7 @@ mod element {
platform::{CursorStyle, MouseButton},
scene::MouseDrag,
AnyElement, Axis, CursorRegion, Element, EventContext, LayoutContext, MouseRegion,
RectFExt, SceneBuilder, SizeConstraint, Vector2FExt, ViewContext,
PaintContext, RectFExt, SceneBuilder, SizeConstraint, Vector2FExt, ViewContext,
};
use crate::{
@ -856,7 +856,7 @@ mod element {
visible_bounds: RectF,
remaining_space: &mut Self::LayoutState,
view: &mut Workspace,
cx: &mut ViewContext<Workspace>,
cx: &mut PaintContext<Workspace>,
) -> Self::PaintState {
let can_resize = settings::get::<WorkspaceSettings>(cx).active_pane_magnification == 1.;
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();

View file

@ -235,7 +235,7 @@ impl From<&Box<dyn SearchableItemHandle>> for AnyViewHandle {
impl PartialEq for Box<dyn SearchableItemHandle> {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id() && self.window_id() == other.window_id()
self.id() == other.id() && self.window() == other.window()
}
}
@ -259,7 +259,7 @@ impl<T: SearchableItem> WeakSearchableItemHandle for WeakViewHandle<T> {
impl PartialEq for Box<dyn WeakSearchableItemHandle> {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id() && self.window_id() == other.window_id()
self.id() == other.id() && self.window() == other.window()
}
}
@ -267,6 +267,6 @@ impl Eq for Box<dyn WeakSearchableItemHandle> {}
impl std::hash::Hash for Box<dyn WeakSearchableItemHandle> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
(self.id(), self.window_id()).hash(state)
(self.id(), self.window().id()).hash(state)
}
}

View file

@ -8,8 +8,8 @@ use gpui::{
vector::{vec2f, Vector2F},
},
json::{json, ToJson},
AnyElement, AnyViewHandle, Entity, LayoutContext, SceneBuilder, SizeConstraint, Subscription,
View, ViewContext, ViewHandle, WindowContext,
AnyElement, AnyViewHandle, Entity, LayoutContext, PaintContext, SceneBuilder, SizeConstraint,
Subscription, View, ViewContext, ViewHandle, WindowContext,
};
pub trait StatusItemView: View {
@ -231,7 +231,7 @@ impl Element<StatusBar> for StatusBarElement {
visible_bounds: RectF,
_: &mut Self::LayoutState,
view: &mut StatusBar,
cx: &mut ViewContext<StatusBar>,
cx: &mut PaintContext<StatusBar>,
) -> Self::PaintState {
let origin_y = bounds.upper_right().y();
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();

View file

@ -37,7 +37,7 @@ use gpui::{
},
AnyModelHandle, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity,
ModelContext, ModelHandle, SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle,
WeakViewHandle, WindowContext,
WeakViewHandle, WindowContext, WindowHandle,
};
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem};
use itertools::Itertools;
@ -753,7 +753,7 @@ impl Workspace {
fn new_local(
abs_paths: Vec<PathBuf>,
app_state: Arc<AppState>,
requesting_window_id: Option<usize>,
requesting_window: Option<WindowHandle<Workspace>>,
cx: &mut AppContext,
) -> Task<(
WeakViewHandle<Workspace>,
@ -797,55 +797,60 @@ impl Workspace {
DB.next_id().await.unwrap_or(0)
};
let window = requesting_window_id.and_then(|window_id| {
cx.update(|cx| {
cx.replace_root_view(window_id, |cx| {
Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx)
})
})
});
let window = window.unwrap_or_else(|| {
let window_bounds_override = window_bounds_env_override(&cx);
let (bounds, display) = if let Some(bounds) = window_bounds_override {
(Some(bounds), None)
} else {
serialized_workspace
.as_ref()
.and_then(|serialized_workspace| {
let display = serialized_workspace.display?;
let mut bounds = serialized_workspace.bounds?;
let window = if let Some(window) = requesting_window {
window.replace_root(&mut cx, |cx| {
Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx)
});
window
} else {
{
let window_bounds_override = window_bounds_env_override(&cx);
let (bounds, display) = if let Some(bounds) = window_bounds_override {
(Some(bounds), None)
} else {
serialized_workspace
.as_ref()
.and_then(|serialized_workspace| {
let display = serialized_workspace.display?;
let mut bounds = serialized_workspace.bounds?;
// Stored bounds are relative to the containing display.
// So convert back to global coordinates if that screen still exists
if let WindowBounds::Fixed(mut window_bounds) = bounds {
if let Some(screen) = cx.platform().screen_by_id(display) {
let screen_bounds = screen.bounds();
window_bounds.set_origin_x(
window_bounds.origin_x() + screen_bounds.origin_x(),
);
window_bounds.set_origin_y(
window_bounds.origin_y() + screen_bounds.origin_y(),
);
bounds = WindowBounds::Fixed(window_bounds);
} else {
// Screen no longer exists. Return none here.
return None;
// Stored bounds are relative to the containing display.
// So convert back to global coordinates if that screen still exists
if let WindowBounds::Fixed(mut window_bounds) = bounds {
if let Some(screen) = cx.platform().screen_by_id(display) {
let screen_bounds = screen.bounds();
window_bounds.set_origin_x(
window_bounds.origin_x() + screen_bounds.origin_x(),
);
window_bounds.set_origin_y(
window_bounds.origin_y() + screen_bounds.origin_y(),
);
bounds = WindowBounds::Fixed(window_bounds);
} else {
// Screen no longer exists. Return none here.
return None;
}
}
}
Some((bounds, display))
})
.unzip()
};
Some((bounds, display))
})
.unzip()
};
// Use the serialized workspace to construct the new window
cx.add_window(
(app_state.build_window_options)(bounds, display, cx.platform().as_ref()),
|cx| {
Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx)
},
)
});
// Use the serialized workspace to construct the new window
cx.add_window(
(app_state.build_window_options)(bounds, display, cx.platform().as_ref()),
|cx| {
Workspace::new(
workspace_id,
project_handle.clone(),
app_state.clone(),
cx,
)
},
)
}
};
// We haven't yielded the main thread since obtaining the window handle,
// so the window exists.
@ -1231,14 +1236,14 @@ impl Workspace {
pub fn close_global(_: &CloseWindow, cx: &mut AppContext) {
cx.spawn(|mut cx| async move {
let id = cx
.window_ids()
let window = cx
.windows()
.into_iter()
.find(|&id| cx.window_is_active(id));
if let Some(id) = id {
.find(|window| window.is_active(&cx).unwrap_or(false));
if let Some(window) = window {
//This can only get called when the window's project connection has been lost
//so we don't need to prompt the user for anything and instead just close the window
cx.remove_window(id);
window.remove(&mut cx);
}
})
.detach();
@ -1249,11 +1254,11 @@ impl Workspace {
_: &CloseWindow,
cx: &mut ViewContext<Self>,
) -> Option<Task<Result<()>>> {
let window_id = cx.window_id();
let window = cx.window();
let prepare = self.prepare_to_close(false, cx);
Some(cx.spawn(|_, mut cx| async move {
if prepare.await? {
cx.remove_window(window_id);
window.remove(&mut cx);
}
Ok(())
}))
@ -1265,13 +1270,13 @@ impl Workspace {
cx: &mut ViewContext<Self>,
) -> Task<Result<bool>> {
let active_call = self.active_call().cloned();
let window_id = cx.window_id();
let window = cx.window();
cx.spawn(|this, mut cx| async move {
let workspace_count = cx
.window_ids()
.windows()
.into_iter()
.filter_map(|window_id| cx.root_view(window_id)?.clone().downcast::<Workspace>())
.filter(|window| window.root_is::<Workspace>())
.count();
if let Some(active_call) = active_call {
@ -1279,11 +1284,11 @@ impl Workspace {
&& workspace_count == 1
&& active_call.read_with(&cx, |call, _| call.room().is_some())
{
let answer = cx.prompt(
window_id,
let answer = window.prompt(
PromptLevel::Warning,
"Do you want to leave the current call?",
&["Close window and hang up", "Cancel"],
&mut cx,
);
if let Some(mut answer) = answer {
@ -1389,7 +1394,7 @@ impl Workspace {
paths: Vec<PathBuf>,
cx: &mut ViewContext<Self>,
) -> Task<Result<()>> {
let window_id = cx.window_id();
let window = cx.window().downcast::<Self>();
let is_remote = self.project.read(cx).is_remote();
let has_worktree = self.project.read(cx).worktrees(cx).next().is_some();
let has_dirty_items = self.items(cx).any(|item| item.is_dirty(cx));
@ -1401,15 +1406,15 @@ impl Workspace {
let app_state = self.app_state.clone();
cx.spawn(|_, mut cx| async move {
let window_id_to_replace = if let Some(close_task) = close_task {
let window_to_replace = if let Some(close_task) = close_task {
if !close_task.await? {
return Ok(());
}
Some(window_id)
window
} else {
None
};
cx.update(|cx| open_paths(&paths, &app_state, window_id_to_replace, cx))
cx.update(|cx| open_paths(&paths, &app_state, window_to_replace, cx))
.await?;
Ok(())
})
@ -3180,7 +3185,7 @@ impl Workspace {
let left_visible = left_dock.is_open();
let left_active_panel = left_dock.visible_panel().and_then(|panel| {
Some(
cx.view_ui_name(panel.as_any().window_id(), panel.id())?
cx.view_ui_name(panel.as_any().window(), panel.id())?
.to_string(),
)
});
@ -3193,7 +3198,7 @@ impl Workspace {
let right_visible = right_dock.is_open();
let right_active_panel = right_dock.visible_panel().and_then(|panel| {
Some(
cx.view_ui_name(panel.as_any().window_id(), panel.id())?
cx.view_ui_name(panel.as_any().window(), panel.id())?
.to_string(),
)
});
@ -3206,7 +3211,7 @@ impl Workspace {
let bottom_visible = bottom_dock.is_open();
let bottom_active_panel = bottom_dock.visible_panel().and_then(|panel| {
Some(
cx.view_ui_name(panel.as_any().window_id(), panel.id())?
cx.view_ui_name(panel.as_any().window(), panel.id())?
.to_string(),
)
});
@ -3841,9 +3846,9 @@ pub fn activate_workspace_for_project(
cx: &mut AsyncAppContext,
predicate: impl Fn(&mut Project, &mut ModelContext<Project>) -> bool,
) -> Option<WeakViewHandle<Workspace>> {
for window_id in cx.window_ids() {
let handle = cx
.update_window(window_id, |cx| {
for window in cx.windows() {
let handle = window
.update(cx, |cx| {
if let Some(workspace_handle) = cx.root_view().clone().downcast::<Workspace>() {
let project = workspace_handle.read(cx).project.clone();
if project.update(cx, &predicate) {
@ -3870,7 +3875,7 @@ pub async fn last_opened_workspace_paths() -> Option<WorkspaceLocation> {
pub fn open_paths(
abs_paths: &[PathBuf],
app_state: &Arc<AppState>,
requesting_window_id: Option<usize>,
requesting_window: Option<WindowHandle<Workspace>>,
cx: &mut AppContext,
) -> Task<
Result<(
@ -3898,7 +3903,7 @@ pub fn open_paths(
} else {
Ok(cx
.update(|cx| {
Workspace::new_local(abs_paths, app_state.clone(), requesting_window_id, cx)
Workspace::new_local(abs_paths, app_state.clone(), requesting_window, cx)
})
.await)
}
@ -3959,18 +3964,23 @@ pub fn join_remote_project(
) -> Task<Result<()>> {
cx.spawn(|mut cx| async move {
let existing_workspace = cx
.window_ids()
.windows()
.into_iter()
.filter_map(|window_id| cx.root_view(window_id)?.clone().downcast::<Workspace>())
.find(|workspace| {
cx.read_window(workspace.window_id(), |cx| {
workspace.read(cx).project().read(cx).remote_id() == Some(project_id)
.find_map(|window| {
window.downcast::<Workspace>().and_then(|window| {
window.read_root_with(&cx, |workspace, cx| {
if workspace.project().read(cx).remote_id() == Some(project_id) {
Some(cx.handle().downgrade())
} else {
None
}
})
})
.unwrap_or(false)
});
})
.flatten();
let workspace = if let Some(existing_workspace) = existing_workspace {
existing_workspace.downgrade()
existing_workspace
} else {
let active_call = cx.read(ActiveCall::global);
let room = active_call
@ -4009,7 +4019,7 @@ pub fn join_remote_project(
workspace.downgrade()
};
cx.activate_window(workspace.window_id());
workspace.window().activate(&mut cx);
cx.platform().activate(true);
workspace.update(&mut cx, |workspace, cx| {
@ -4048,29 +4058,22 @@ pub fn join_remote_project(
pub fn restart(_: &Restart, cx: &mut AppContext) {
let should_confirm = settings::get::<WorkspaceSettings>(cx).confirm_quit;
cx.spawn(|mut cx| async move {
let mut workspaces = cx
.window_ids()
let mut workspace_windows = cx
.windows()
.into_iter()
.filter_map(|window_id| {
Some(
cx.root_view(window_id)?
.clone()
.downcast::<Workspace>()?
.downgrade(),
)
})
.filter_map(|window| window.downcast::<Workspace>())
.collect::<Vec<_>>();
// If multiple windows have unsaved changes, and need a save prompt,
// prompt in the active window before switching to a different window.
workspaces.sort_by_key(|workspace| !cx.window_is_active(workspace.window_id()));
workspace_windows.sort_by_key(|window| window.is_active(&cx) == Some(false));
if let (true, Some(workspace)) = (should_confirm, workspaces.first()) {
let answer = cx.prompt(
workspace.window_id(),
if let (true, Some(window)) = (should_confirm, workspace_windows.first()) {
let answer = window.prompt(
PromptLevel::Info,
"Are you sure you want to restart?",
&["Restart", "Cancel"],
&mut cx,
);
if let Some(mut answer) = answer {
@ -4082,14 +4085,13 @@ pub fn restart(_: &Restart, cx: &mut AppContext) {
}
// If the user cancels any save prompt, then keep the app open.
for workspace in workspaces {
if !workspace
.update(&mut cx, |workspace, cx| {
workspace.prepare_to_close(true, cx)
})?
.await?
{
return Ok(());
for window in workspace_windows {
if let Some(close) = window.update_root(&mut cx, |workspace, cx| {
workspace.prepare_to_close(true, cx)
}) {
if !close.await? {
return Ok(());
}
}
}
cx.platform().restart();
@ -4214,17 +4216,11 @@ mod tests {
.map(|e| e.id)
);
});
assert_eq!(
cx.current_window_title(window.window_id()).as_deref(),
Some("one.txt — root1")
);
assert_eq!(window.current_title(cx).as_deref(), Some("one.txt — root1"));
// Add a second item to a non-empty pane
workspace.update(cx, |workspace, cx| workspace.add_item(Box::new(item2), cx));
assert_eq!(
cx.current_window_title(window.window_id()).as_deref(),
Some("two.txt — root1")
);
assert_eq!(window.current_title(cx).as_deref(), Some("two.txt — root1"));
project.read_with(cx, |project, cx| {
assert_eq!(
project.active_entry(),
@ -4240,10 +4236,7 @@ mod tests {
})
.await
.unwrap();
assert_eq!(
cx.current_window_title(window.window_id()).as_deref(),
Some("one.txt — root1")
);
assert_eq!(window.current_title(cx).as_deref(), Some("one.txt — root1"));
project.read_with(cx, |project, cx| {
assert_eq!(
project.active_entry(),
@ -4261,16 +4254,13 @@ mod tests {
.await
.unwrap();
assert_eq!(
cx.current_window_title(window.window_id()).as_deref(),
window.current_title(cx).as_deref(),
Some("one.txt — root1, root2")
);
// Remove a project folder
project.update(cx, |project, cx| project.remove_worktree(worktree_id, cx));
assert_eq!(
cx.current_window_title(window.window_id()).as_deref(),
Some("one.txt — root2")
);
assert_eq!(window.current_title(cx).as_deref(), Some("one.txt — root2"));
}
#[gpui::test]
@ -4304,9 +4294,9 @@ mod tests {
});
let task = workspace.update(cx, |w, cx| w.prepare_to_close(false, cx));
cx.foreground().run_until_parked();
cx.simulate_prompt_answer(window.window_id(), 2 /* cancel */);
window.simulate_prompt_answer(2, cx); // cancel
cx.foreground().run_until_parked();
assert!(!cx.has_pending_prompt(window.window_id()));
assert!(!window.has_pending_prompt(cx));
assert!(!task.await.unwrap());
}
@ -4365,10 +4355,10 @@ mod tests {
assert_eq!(pane.items_len(), 4);
assert_eq!(pane.active_item().unwrap().id(), item1.id());
});
assert!(cx.has_pending_prompt(window.window_id()));
assert!(window.has_pending_prompt(cx));
// Confirm saving item 1.
cx.simulate_prompt_answer(window.window_id(), 0);
window.simulate_prompt_answer(0, cx);
cx.foreground().run_until_parked();
// Item 1 is saved. There's a prompt to save item 3.
@ -4379,10 +4369,10 @@ mod tests {
assert_eq!(pane.items_len(), 3);
assert_eq!(pane.active_item().unwrap().id(), item3.id());
});
assert!(cx.has_pending_prompt(window.window_id()));
assert!(window.has_pending_prompt(cx));
// Cancel saving item 3.
cx.simulate_prompt_answer(window.window_id(), 1);
window.simulate_prompt_answer(1, cx);
cx.foreground().run_until_parked();
// Item 3 is reloaded. There's a prompt to save item 4.
@ -4393,10 +4383,10 @@ mod tests {
assert_eq!(pane.items_len(), 2);
assert_eq!(pane.active_item().unwrap().id(), item4.id());
});
assert!(cx.has_pending_prompt(window.window_id()));
assert!(window.has_pending_prompt(cx));
// Confirm saving item 4.
cx.simulate_prompt_answer(window.window_id(), 0);
window.simulate_prompt_answer(0, cx);
cx.foreground().run_until_parked();
// There's a prompt for a path for item 4.
@ -4499,7 +4489,7 @@ mod tests {
&[ProjectEntryId::from_proto(0)]
);
});
cx.simulate_prompt_answer(window.window_id(), 0);
window.simulate_prompt_answer(0, cx);
cx.foreground().run_until_parked();
left_pane.read_with(cx, |pane, cx| {
@ -4508,7 +4498,7 @@ mod tests {
&[ProjectEntryId::from_proto(2)]
);
});
cx.simulate_prompt_answer(window.window_id(), 0);
window.simulate_prompt_answer(0, cx);
cx.foreground().run_until_parked();
close.await.unwrap();
@ -4547,7 +4537,7 @@ mod tests {
});
// Deactivating the window saves the file.
cx.simulate_window_activation(None);
window.simulate_deactivation(cx);
deterministic.run_until_parked();
item.read_with(cx, |item, _| assert_eq!(item.save_count, 1));
@ -4568,12 +4558,12 @@ mod tests {
item.read_with(cx, |item, _| assert_eq!(item.save_count, 2));
// Deactivating the window still saves the file.
cx.simulate_window_activation(Some(window.window_id()));
window.simulate_activation(cx);
item.update(cx, |item, cx| {
cx.focus_self();
item.is_dirty = true;
});
cx.simulate_window_activation(None);
window.simulate_deactivation(cx);
deterministic.run_until_parked();
item.read_with(cx, |item, _| assert_eq!(item.save_count, 3));
@ -4610,7 +4600,7 @@ mod tests {
pane.update(cx, |pane, cx| pane.close_items(cx, move |id| id == item_id))
.await
.unwrap();
assert!(!cx.has_pending_prompt(window.window_id()));
assert!(!window.has_pending_prompt(cx));
item.read_with(cx, |item, _| assert_eq!(item.save_count, 5));
// Add the item again, ensuring autosave is prevented if the underlying file has been deleted.
@ -4631,7 +4621,7 @@ mod tests {
let _close_items =
pane.update(cx, |pane, cx| pane.close_items(cx, move |id| id == item_id));
deterministic.run_until_parked();
assert!(cx.has_pending_prompt(window.window_id()));
assert!(window.has_pending_prompt(cx));
item.read_with(cx, |item, _| assert_eq!(item.save_count, 5));
}