mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
workspace: Make Item::clone_on_split async (#41211)
Split out from https://github.com/zed-industries/zed/pull/40774 to reduce the size of the reland of that PR (once I figure out the cause of the issue) Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
parent
b7cc597d28
commit
33ec545d1f
24 changed files with 217 additions and 157 deletions
|
|
@ -581,11 +581,13 @@ impl Item for AgentDiffPane {
|
|||
_workspace_id: Option<workspace::WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new(|cx| Self::new(self.thread.clone(), self.workspace.clone(), window, cx)))
|
||||
Task::ready(Some(cx.new(|cx| {
|
||||
Self::new(self.thread.clone(), self.workspace.clone(), window, cx)
|
||||
})))
|
||||
}
|
||||
|
||||
fn is_dirty(&self, cx: &App) -> bool {
|
||||
|
|
|
|||
|
|
@ -776,26 +776,30 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
|
|||
.unwrap();
|
||||
|
||||
// Clients A and B follow each other in split panes
|
||||
workspace_a.update_in(cx_a, |workspace, window, cx| {
|
||||
workspace.split_and_clone(
|
||||
workspace.active_pane().clone(),
|
||||
SplitDirection::Right,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
workspace_a
|
||||
.update_in(cx_a, |workspace, window, cx| {
|
||||
workspace.split_and_clone(
|
||||
workspace.active_pane().clone(),
|
||||
SplitDirection::Right,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await;
|
||||
workspace_a.update_in(cx_a, |workspace, window, cx| {
|
||||
workspace.follow(client_b.peer_id().unwrap(), window, cx)
|
||||
});
|
||||
executor.run_until_parked();
|
||||
workspace_b.update_in(cx_b, |workspace, window, cx| {
|
||||
workspace.split_and_clone(
|
||||
workspace.active_pane().clone(),
|
||||
SplitDirection::Right,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
workspace_b
|
||||
.update_in(cx_b, |workspace, window, cx| {
|
||||
workspace.split_and_clone(
|
||||
workspace.active_pane().clone(),
|
||||
SplitDirection::Right,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await;
|
||||
workspace_b.update_in(cx_b, |workspace, window, cx| {
|
||||
workspace.follow(client_a.peer_id().unwrap(), window, cx)
|
||||
});
|
||||
|
|
@ -1369,9 +1373,11 @@ async fn test_auto_unfollowing(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont
|
|||
);
|
||||
|
||||
// When client B activates a different pane, it continues following client A in the original pane.
|
||||
workspace_b.update_in(cx_b, |workspace, window, cx| {
|
||||
workspace.split_and_clone(pane_b.clone(), SplitDirection::Right, window, cx)
|
||||
});
|
||||
workspace_b
|
||||
.update_in(cx_b, |workspace, window, cx| {
|
||||
workspace.split_and_clone(pane_b.clone(), SplitDirection::Right, window, cx)
|
||||
})
|
||||
.await;
|
||||
assert_eq!(
|
||||
workspace_b.update(cx_b, |workspace, _| workspace.leader_for_pane(&pane_b)),
|
||||
Some(leader_id.into())
|
||||
|
|
|
|||
|
|
@ -6748,7 +6748,7 @@ async fn test_preview_tabs(cx: &mut TestAppContext) {
|
|||
pane.update(cx, |pane, cx| {
|
||||
pane.split(workspace::SplitDirection::Right, cx);
|
||||
});
|
||||
|
||||
cx.run_until_parked();
|
||||
let right_pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
||||
|
||||
pane.update(cx, |pane, cx| {
|
||||
|
|
|
|||
|
|
@ -498,8 +498,8 @@ impl Item for ChannelView {
|
|||
_: Option<WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>> {
|
||||
Some(cx.new(|cx| {
|
||||
) -> Task<Option<Entity<Self>>> {
|
||||
Task::ready(Some(cx.new(|cx| {
|
||||
Self::new(
|
||||
self.project.clone(),
|
||||
self.workspace.clone(),
|
||||
|
|
@ -508,7 +508,7 @@ impl Item for ChannelView {
|
|||
window,
|
||||
cx,
|
||||
)
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
fn navigate(
|
||||
|
|
|
|||
|
|
@ -693,11 +693,11 @@ impl Item for BufferDiagnosticsEditor {
|
|||
_workspace_id: Option<workspace::WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new(|cx| {
|
||||
Task::ready(Some(cx.new(|cx| {
|
||||
BufferDiagnosticsEditor::new(
|
||||
self.project_path.clone(),
|
||||
self.project.clone(),
|
||||
|
|
@ -706,7 +706,7 @@ impl Item for BufferDiagnosticsEditor {
|
|||
window,
|
||||
cx,
|
||||
)
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
fn deactivated(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
|
|
|
|||
|
|
@ -732,11 +732,11 @@ impl Item for ProjectDiagnosticsEditor {
|
|||
_workspace_id: Option<workspace::WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new(|cx| {
|
||||
Task::ready(Some(cx.new(|cx| {
|
||||
ProjectDiagnosticsEditor::new(
|
||||
self.include_warnings,
|
||||
self.project.clone(),
|
||||
|
|
@ -744,7 +744,7 @@ impl Item for ProjectDiagnosticsEditor {
|
|||
window,
|
||||
cx,
|
||||
)
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
fn is_dirty(&self, cx: &App) -> bool {
|
||||
|
|
|
|||
|
|
@ -762,11 +762,11 @@ impl Item for Editor {
|
|||
_workspace_id: Option<WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Editor>>
|
||||
) -> Task<Option<Entity<Editor>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new(|cx| self.clone(window, cx)))
|
||||
Task::ready(Some(cx.new(|cx| self.clone(window, cx))))
|
||||
}
|
||||
|
||||
fn set_nav_history(
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ use editor::{Editor, EditorEvent, MultiBuffer, SelectionEffects, multibuffer_con
|
|||
use git::repository::{CommitDetails, CommitDiff, RepoPath};
|
||||
use gpui::{
|
||||
Action, AnyElement, AnyView, App, AppContext as _, AsyncApp, AsyncWindowContext, Context,
|
||||
Entity, EventEmitter, FocusHandle, Focusable, IntoElement, PromptLevel, Render, WeakEntity,
|
||||
Window, actions,
|
||||
Entity, EventEmitter, FocusHandle, Focusable, IntoElement, PromptLevel, Render, Task,
|
||||
WeakEntity, Window, actions,
|
||||
};
|
||||
use language::{
|
||||
Anchor, Buffer, Capability, DiskState, File, LanguageRegistry, LineEnding, OffsetRangeExt as _,
|
||||
|
|
@ -561,11 +561,11 @@ impl Item for CommitView {
|
|||
_workspace_id: Option<workspace::WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new(|cx| {
|
||||
Task::ready(Some(cx.new(|cx| {
|
||||
let editor = cx.new(|cx| {
|
||||
self.editor
|
||||
.update(cx, |editor, cx| editor.clone(window, cx))
|
||||
|
|
@ -577,7 +577,7 @@ impl Item for CommitView {
|
|||
commit: self.commit.clone(),
|
||||
stash: self.stash,
|
||||
}
|
||||
}))
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -714,12 +714,16 @@ impl Item for ProjectDiff {
|
|||
_workspace_id: Option<workspace::WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let workspace = self.workspace.upgrade()?;
|
||||
Some(cx.new(|cx| ProjectDiff::new(self.project.clone(), workspace, window, cx)))
|
||||
let Some(workspace) = self.workspace.upgrade() else {
|
||||
return Task::ready(None);
|
||||
};
|
||||
Task::ready(Some(cx.new(|cx| {
|
||||
ProjectDiff::new(self.project.clone(), workspace, window, cx)
|
||||
})))
|
||||
}
|
||||
|
||||
fn is_dirty(&self, cx: &App) -> bool {
|
||||
|
|
|
|||
|
|
@ -179,15 +179,15 @@ impl Item for ImageView {
|
|||
_workspace_id: Option<WorkspaceId>,
|
||||
_: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new(|cx| Self {
|
||||
Task::ready(Some(cx.new(|cx| Self {
|
||||
image_item: self.image_item.clone(),
|
||||
project: self.project.clone(),
|
||||
focus_handle: cx.focus_handle(),
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
fn has_deleted_file(&self, cx: &App) -> bool {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use gpui::{
|
||||
Action, App, AppContext as _, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
KeyBindingContextPredicate, KeyContext, Keystroke, MouseButton, Render, Subscription, actions,
|
||||
KeyBindingContextPredicate, KeyContext, Keystroke, MouseButton, Render, Subscription, Task,
|
||||
actions,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use serde_json::json;
|
||||
|
|
@ -157,11 +158,11 @@ impl Item for KeyContextView {
|
|||
_workspace_id: Option<workspace::WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new(|cx| KeyContextView::new(window, cx)))
|
||||
Task::ready(Some(cx.new(|cx| KeyContextView::new(window, cx))))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use copilot::Copilot;
|
|||
use editor::{Editor, EditorEvent, actions::MoveToEnd, scroll::Autoscroll};
|
||||
use gpui::{
|
||||
AnyView, App, Context, Corner, Entity, EventEmitter, FocusHandle, Focusable, IntoElement,
|
||||
ParentElement, Render, Styled, Subscription, WeakEntity, Window, actions, div,
|
||||
ParentElement, Render, Styled, Subscription, Task, WeakEntity, Window, actions, div,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use language::{LanguageServerId, language_settings::SoftWrap};
|
||||
|
|
@ -763,11 +763,11 @@ impl Item for LspLogView {
|
|||
_workspace_id: Option<WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new(|cx| {
|
||||
Task::ready(Some(cx.new(|cx| {
|
||||
let mut new_view = Self::new(self.project.clone(), self.log_store.clone(), window, cx);
|
||||
if let Some(server_id) = self.current_server_id {
|
||||
match self.active_entry_kind {
|
||||
|
|
@ -778,7 +778,7 @@ impl Item for LspLogView {
|
|||
}
|
||||
}
|
||||
new_view
|
||||
}))
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use editor::{Anchor, Editor, ExcerptId, SelectionEffects, scroll::Autoscroll};
|
|||
use gpui::{
|
||||
App, AppContext as _, Context, Div, Entity, EntityId, EventEmitter, FocusHandle, Focusable,
|
||||
Hsla, InteractiveElement, IntoElement, MouseButton, MouseDownEvent, MouseMoveEvent,
|
||||
ParentElement, Render, ScrollStrategy, SharedString, Styled, UniformListScrollHandle,
|
||||
ParentElement, Render, ScrollStrategy, SharedString, Styled, Task, UniformListScrollHandle,
|
||||
WeakEntity, Window, actions, div, rems, uniform_list,
|
||||
};
|
||||
use language::{Buffer, OwnedSyntaxLayer};
|
||||
|
|
@ -573,17 +573,17 @@ impl Item for SyntaxTreeView {
|
|||
_: Option<workspace::WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new(|cx| {
|
||||
Task::ready(Some(cx.new(|cx| {
|
||||
let mut clone = Self::new(self.workspace_handle.clone(), None, window, cx);
|
||||
if let Some(editor) = &self.editor {
|
||||
clone.set_editor(editor.editor.clone(), window, cx)
|
||||
}
|
||||
clone
|
||||
}))
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -383,14 +383,14 @@ impl Item for Onboarding {
|
|||
_workspace_id: Option<WorkspaceId>,
|
||||
_: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>> {
|
||||
Some(cx.new(|cx| Onboarding {
|
||||
) -> Task<Option<Entity<Self>>> {
|
||||
Task::ready(Some(cx.new(|cx| Onboarding {
|
||||
workspace: self.workspace.clone(),
|
||||
user_store: self.user_store.clone(),
|
||||
scroll_handle: ScrollHandle::new(),
|
||||
focus_handle: cx.focus_handle(),
|
||||
_settings_subscription: cx.observe_global::<SettingsStore>(move |_, cx| cx.notify()),
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
|
||||
|
|
|
|||
|
|
@ -699,11 +699,13 @@ impl Item for NotebookEditor {
|
|||
_workspace_id: Option<workspace::WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new(|cx| Self::new(self.project.clone(), self.notebook_item.clone(), window, cx)))
|
||||
Task::ready(Some(cx.new(|cx| {
|
||||
Self::new(self.project.clone(), self.notebook_item.clone(), window, cx)
|
||||
})))
|
||||
}
|
||||
|
||||
fn buffer_kind(&self, _: &App) -> workspace::item::ItemBufferKind {
|
||||
|
|
|
|||
|
|
@ -572,12 +572,14 @@ impl Item for ProjectSearchView {
|
|||
_workspace_id: Option<WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let model = self.entity.update(cx, |model, cx| model.clone(cx));
|
||||
Some(cx.new(|cx| Self::new(self.workspace.clone(), model, window, cx, None)))
|
||||
Task::ready(Some(cx.new(|cx| {
|
||||
Self::new(self.workspace.clone(), model, window, cx, None)
|
||||
})))
|
||||
}
|
||||
|
||||
fn added_to_workspace(
|
||||
|
|
@ -3677,6 +3679,7 @@ pub mod tests {
|
|||
)
|
||||
})
|
||||
.unwrap()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(cx.update(|cx| second_pane.read(cx).items_len()), 1);
|
||||
|
||||
|
|
@ -3872,6 +3875,7 @@ pub mod tests {
|
|||
)
|
||||
})
|
||||
.unwrap()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(cx.update(|cx| second_pane.read(cx).items_len()), 1);
|
||||
assert!(
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ use ui::{
|
|||
prelude::*,
|
||||
scrollbars::{self, GlobalSetting, ScrollbarVisibility},
|
||||
};
|
||||
use util::ResultExt;
|
||||
use util::{ResultExt, maybe};
|
||||
use workspace::{
|
||||
CloseActiveItem, NewCenterTerminal, NewTerminal, ToolbarItemLocation, Workspace, WorkspaceId,
|
||||
delete_unloaded_items,
|
||||
|
|
@ -1218,27 +1218,29 @@ impl Item for TerminalView {
|
|||
workspace_id: Option<WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>> {
|
||||
let terminal = self
|
||||
.project
|
||||
.update(cx, |project, cx| {
|
||||
let cwd = project
|
||||
.active_project_directory(cx)
|
||||
.map(|it| it.to_path_buf());
|
||||
project.clone_terminal(self.terminal(), cx, cwd)
|
||||
})
|
||||
.ok()?
|
||||
.log_err()?;
|
||||
) -> Task<Option<Entity<Self>>> {
|
||||
Task::ready(maybe!({
|
||||
let terminal = self
|
||||
.project
|
||||
.update(cx, |project, cx| {
|
||||
let cwd = project
|
||||
.active_project_directory(cx)
|
||||
.map(|it| it.to_path_buf());
|
||||
project.clone_terminal(self.terminal(), cx, cwd)
|
||||
})
|
||||
.ok()?
|
||||
.log_err()?;
|
||||
|
||||
Some(cx.new(|cx| {
|
||||
TerminalView::new(
|
||||
terminal,
|
||||
self.workspace.clone(),
|
||||
workspace_id,
|
||||
self.project.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
Some(cx.new(|cx| {
|
||||
TerminalView::new(
|
||||
terminal,
|
||||
self.workspace.clone(),
|
||||
workspace_id,
|
||||
self.project.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}))
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ use anyhow::Result;
|
|||
use client::{Client, proto};
|
||||
use futures::{StreamExt, channel::mpsc};
|
||||
use gpui::{
|
||||
Action, AnyElement, AnyView, App, Context, Entity, EntityId, EventEmitter, FocusHandle,
|
||||
Focusable, Font, HighlightStyle, Pixels, Point, Render, SharedString, Task, WeakEntity, Window,
|
||||
Action, AnyElement, AnyView, App, AppContext, Context, Entity, EntityId, EventEmitter,
|
||||
FocusHandle, Focusable, Font, HighlightStyle, Pixels, Point, Render, SharedString, Task,
|
||||
WeakEntity, Window,
|
||||
};
|
||||
use project::{Project, ProjectEntryId, ProjectPath};
|
||||
pub use settings::{
|
||||
|
|
@ -217,11 +218,11 @@ pub trait Item: Focusable + EventEmitter<Self::Event> + Render + Sized {
|
|||
_workspace_id: Option<WorkspaceId>,
|
||||
_window: &mut Window,
|
||||
_: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
None
|
||||
Task::ready(None)
|
||||
}
|
||||
fn is_dirty(&self, _: &App) -> bool {
|
||||
false
|
||||
|
|
@ -422,7 +423,7 @@ pub trait ItemHandle: 'static + Send {
|
|||
workspace_id: Option<WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Option<Box<dyn ItemHandle>>;
|
||||
) -> Task<Option<Box<dyn ItemHandle>>>;
|
||||
fn added_to_pane(
|
||||
&self,
|
||||
workspace: &mut Workspace,
|
||||
|
|
@ -635,9 +636,12 @@ impl<T: Item> ItemHandle for Entity<T> {
|
|||
workspace_id: Option<WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Option<Box<dyn ItemHandle>> {
|
||||
self.update(cx, |item, cx| item.clone_on_split(workspace_id, window, cx))
|
||||
.map(|handle| Box::new(handle) as Box<dyn ItemHandle>)
|
||||
) -> Task<Option<Box<dyn ItemHandle>>> {
|
||||
let task = self.update(cx, |item, cx| item.clone_on_split(workspace_id, window, cx));
|
||||
cx.background_spawn(async move {
|
||||
task.await
|
||||
.map(|handle| Box::new(handle) as Box<dyn ItemHandle>)
|
||||
})
|
||||
}
|
||||
|
||||
fn added_to_pane(
|
||||
|
|
@ -1504,11 +1508,11 @@ pub mod test {
|
|||
_workspace_id: Option<WorkspaceId>,
|
||||
_: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new(|cx| Self {
|
||||
Task::ready(Some(cx.new(|cx| Self {
|
||||
state: self.state.clone(),
|
||||
label: self.label.clone(),
|
||||
save_count: self.save_count,
|
||||
|
|
@ -1525,7 +1529,7 @@ pub mod test {
|
|||
workspace_id: self.workspace_id,
|
||||
focus_handle: cx.focus_handle(),
|
||||
serialize: None,
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
fn is_dirty(&self, _: &App) -> bool {
|
||||
|
|
|
|||
|
|
@ -3292,11 +3292,18 @@ impl Pane {
|
|||
else {
|
||||
return;
|
||||
};
|
||||
if let Some(item) = item.clone_on_split(database_id, window, cx) {
|
||||
to_pane.update(cx, |pane, cx| {
|
||||
pane.add_item(item, true, true, None, window, cx);
|
||||
})
|
||||
}
|
||||
let task = item.clone_on_split(database_id, window, cx);
|
||||
let to_pane = to_pane.downgrade();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
if let Some(item) = task.await {
|
||||
to_pane
|
||||
.update_in(cx, |pane, window, cx| {
|
||||
pane.add_item(item, true, true, None, window, cx)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
} else {
|
||||
move_item(&from_pane, &to_pane, item_id, ix, true, window, cx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use call::{RemoteVideoTrack, RemoteVideoTrackView, Room};
|
|||
use client::{User, proto::PeerId};
|
||||
use gpui::{
|
||||
AppContext as _, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement,
|
||||
ParentElement, Render, SharedString, Styled, div,
|
||||
ParentElement, Render, SharedString, Styled, Task, div,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use ui::{Icon, IconName, prelude::*};
|
||||
|
|
@ -114,14 +114,14 @@ impl Item for SharedScreen {
|
|||
_workspace_id: Option<WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>> {
|
||||
Some(cx.new(|cx| Self {
|
||||
) -> Task<Option<Entity<Self>>> {
|
||||
Task::ready(Some(cx.new(|cx| Self {
|
||||
view: self.view.update(cx, |view, cx| view.clone(window, cx)),
|
||||
peer_id: self.peer_id,
|
||||
user: self.user.clone(),
|
||||
nav_history: Default::default(),
|
||||
focus: cx.focus_handle(),
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#![allow(unused, dead_code)]
|
||||
use gpui::{AnyElement, App, Entity, EventEmitter, FocusHandle, Focusable, Hsla, actions, hsla};
|
||||
use gpui::{
|
||||
AnyElement, App, Entity, EventEmitter, FocusHandle, Focusable, Hsla, Task, actions, hsla,
|
||||
};
|
||||
use strum::IntoEnumIterator;
|
||||
use theme::all_theme_colors;
|
||||
use ui::{
|
||||
|
|
@ -100,11 +102,11 @@ impl Item for ThemePreview {
|
|||
_workspace_id: Option<crate::WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>>
|
||||
) -> Task<Option<Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(cx.new(|cx| Self::new(window, cx)))
|
||||
Task::ready(Some(cx.new(|cx| Self::new(window, cx))))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3627,7 +3627,8 @@ impl Workspace {
|
|||
if let Some(pane) = panes.get(action.0).map(|p| (*p).clone()) {
|
||||
window.focus(&pane.focus_handle(cx));
|
||||
} else {
|
||||
self.split_and_clone(self.active_pane.clone(), SplitDirection::Right, window, cx);
|
||||
self.split_and_clone(self.active_pane.clone(), SplitDirection::Right, window, cx)
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3994,7 +3995,8 @@ impl Workspace {
|
|||
clone_active_item,
|
||||
} => {
|
||||
if *clone_active_item {
|
||||
self.split_and_clone(pane.clone(), *direction, window, cx);
|
||||
self.split_and_clone(pane.clone(), *direction, window, cx)
|
||||
.detach();
|
||||
} else {
|
||||
self.split_and_move(pane.clone(), *direction, window, cx);
|
||||
}
|
||||
|
|
@ -4135,21 +4137,27 @@ impl Workspace {
|
|||
direction: SplitDirection,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Entity<Pane>> {
|
||||
let item = pane.read(cx).active_item()?;
|
||||
let maybe_pane_handle =
|
||||
if let Some(clone) = item.clone_on_split(self.database_id(), window, cx) {
|
||||
let new_pane = self.add_pane(window, cx);
|
||||
new_pane.update(cx, |pane, cx| {
|
||||
pane.add_item(clone, true, true, None, window, cx)
|
||||
});
|
||||
self.center.split(&pane, &new_pane, direction).unwrap();
|
||||
cx.notify();
|
||||
Some(new_pane)
|
||||
) -> Task<Option<Entity<Pane>>> {
|
||||
let Some(item) = pane.read(cx).active_item() else {
|
||||
return Task::ready(None);
|
||||
};
|
||||
let task = item.clone_on_split(self.database_id(), window, cx);
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if let Some(clone) = task.await {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
let new_pane = this.add_pane(window, cx);
|
||||
new_pane.update(cx, |pane, cx| {
|
||||
pane.add_item(clone, true, true, None, window, cx)
|
||||
});
|
||||
this.center.split(&pane, &new_pane, direction).unwrap();
|
||||
cx.notify();
|
||||
new_pane
|
||||
})
|
||||
.ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
maybe_pane_handle
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn join_all_panes(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
|
|
@ -8217,19 +8225,27 @@ pub fn clone_active_item(
|
|||
let Some(active_item) = source.read(cx).active_item() else {
|
||||
return;
|
||||
};
|
||||
destination.update(cx, |target_pane, cx| {
|
||||
let Some(clone) = active_item.clone_on_split(workspace_id, window, cx) else {
|
||||
return;
|
||||
};
|
||||
target_pane.add_item(
|
||||
clone,
|
||||
focus_destination,
|
||||
focus_destination,
|
||||
Some(target_pane.items_len()),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
let destination = destination.downgrade();
|
||||
let task = active_item.clone_on_split(workspace_id, window, cx);
|
||||
window
|
||||
.spawn(cx, async move |cx| {
|
||||
let Some(clone) = task.await else {
|
||||
return;
|
||||
};
|
||||
destination
|
||||
.update_in(cx, |target_pane, window, cx| {
|
||||
target_pane.add_item(
|
||||
clone,
|
||||
focus_destination,
|
||||
focus_destination,
|
||||
Some(target_pane.items_len()),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.log_err();
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -8736,25 +8752,24 @@ mod tests {
|
|||
cx,
|
||||
);
|
||||
|
||||
let right_pane = workspace
|
||||
.split_and_clone(left_pane.clone(), SplitDirection::Right, window, cx)
|
||||
.unwrap();
|
||||
let right_pane =
|
||||
workspace.split_and_clone(left_pane.clone(), SplitDirection::Right, window, cx);
|
||||
|
||||
right_pane.update(cx, |pane, cx| {
|
||||
pane.add_item(
|
||||
single_entry_items[1].boxed_clone(),
|
||||
true,
|
||||
true,
|
||||
None,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
pane.add_item(Box::new(item_3_4.clone()), true, true, None, window, cx);
|
||||
let boxed_clone = single_entry_items[1].boxed_clone();
|
||||
let right_pane = window.spawn(cx, async move |cx| {
|
||||
right_pane.await.inspect(|right_pane| {
|
||||
right_pane
|
||||
.update_in(cx, |pane, window, cx| {
|
||||
pane.add_item(boxed_clone, true, true, None, window, cx);
|
||||
pane.add_item(Box::new(item_3_4.clone()), true, true, None, window, cx);
|
||||
})
|
||||
.unwrap();
|
||||
})
|
||||
});
|
||||
|
||||
(left_pane, right_pane)
|
||||
});
|
||||
|
||||
let right_pane = right_pane.await.unwrap();
|
||||
cx.focus(&right_pane);
|
||||
|
||||
let mut close = right_pane.update_in(cx, |pane, window, cx| {
|
||||
|
|
@ -10571,7 +10586,10 @@ mod tests {
|
|||
window,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
assert_eq!(workspace.panes.len(), 3, "Two new panes were created");
|
||||
for pane in workspace.panes() {
|
||||
assert_eq!(
|
||||
|
|
|
|||
|
|
@ -2854,14 +2854,16 @@ mod tests {
|
|||
});
|
||||
|
||||
// Split the pane with the first entry, then open the second entry again.
|
||||
window
|
||||
let (task1, task2) = window
|
||||
.update(cx, |w, window, cx| {
|
||||
w.split_and_clone(w.active_pane().clone(), SplitDirection::Right, window, cx);
|
||||
w.open_path(file2.clone(), None, true, window, cx)
|
||||
(
|
||||
w.split_and_clone(w.active_pane().clone(), SplitDirection::Right, window, cx),
|
||||
w.open_path(file2.clone(), None, true, window, cx),
|
||||
)
|
||||
})
|
||||
.unwrap()
|
||||
.await
|
||||
.unwrap();
|
||||
task1.await.unwrap();
|
||||
task2.await.unwrap();
|
||||
|
||||
window
|
||||
.read_with(cx, |w, cx| {
|
||||
|
|
@ -3484,7 +3486,13 @@ mod tests {
|
|||
SplitDirection::Right,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
)
|
||||
})
|
||||
.unwrap()
|
||||
.await
|
||||
.unwrap();
|
||||
window
|
||||
.update(cx, |workspace, window, cx| {
|
||||
workspace.open_path(
|
||||
(worktree.read(cx).id(), rel_path("the-new-name.rs")),
|
||||
None,
|
||||
|
|
|
|||
|
|
@ -720,7 +720,7 @@ impl Item for ComponentPreview {
|
|||
_workspace_id: Option<WorkspaceId>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<gpui::Entity<Self>>
|
||||
) -> Task<Option<gpui::Entity<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
|
@ -742,13 +742,13 @@ impl Item for ComponentPreview {
|
|||
cx,
|
||||
);
|
||||
|
||||
match self_result {
|
||||
Task::ready(match self_result {
|
||||
Ok(preview) => Some(cx.new(|_cx| preview)),
|
||||
Err(e) => {
|
||||
log::error!("Failed to clone component preview: {}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue