Scope worktree creation spinner to the thread that initiated it (#53544)
The "Creating Worktree…" spinner, error banner, and disabled selector state were stored as panel-wide state. This meant switching to a different thread while a worktree was being created would still show the spinner on the new thread. Release Notes: - N/A
This commit is contained in:
1 parent
5d32b56e07
commit
78c2e0d778
1 file changed
+43
-20
@@ -56,8 +56,9 @@ use extension_host::ExtensionStore;
|
||||
use fs::Fs;
|
||||
use gpui::{
|
||||
Action, Animation, AnimationExt, AnyElement, App, AsyncWindowContext, ClipboardItem, Corner,
|
||||
DismissEvent, Entity, EventEmitter, ExternalPaths, FocusHandle, Focusable, KeyContext, Pixels,
|
||||
Subscription, Task, UpdateGlobal, WeakEntity, prelude::*, pulsating_between,
|
||||
DismissEvent, Entity, EntityId, EventEmitter, ExternalPaths, FocusHandle, Focusable,
|
||||
KeyContext, Pixels, Subscription, Task, UpdateGlobal, WeakEntity, prelude::*,
|
||||
pulsating_between,
|
||||
};
|
||||
use language::LanguageRegistry;
|
||||
use language_model::LanguageModelRegistry;
|
||||
@@ -819,7 +820,7 @@ pub struct AgentPanel {
|
||||
agent_layout_onboarding_dismissed: AtomicBool,
|
||||
selected_agent: Agent,
|
||||
start_thread_in: StartThreadIn,
|
||||
worktree_creation_status: Option<WorktreeCreationStatus>,
|
||||
worktree_creation_status: Option<(EntityId, WorktreeCreationStatus)>,
|
||||
_thread_view_subscription: Option<Subscription>,
|
||||
_active_thread_focus_subscription: Option<Subscription>,
|
||||
_worktree_creation_task: Option<Task<()>>,
|
||||
@@ -2903,7 +2904,9 @@ impl AgentPanel {
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.worktree_creation_status = Some(WorktreeCreationStatus::Error(message));
|
||||
if let Some((_, status)) = &mut self.worktree_creation_status {
|
||||
*status = WorktreeCreationStatus::Error(message);
|
||||
}
|
||||
if matches!(self.active_view, ActiveView::Uninitialized) {
|
||||
let selected_agent = self.selected_agent.clone();
|
||||
self.new_agent_thread(selected_agent, window, cx);
|
||||
@@ -2920,12 +2923,17 @@ impl AgentPanel {
|
||||
) {
|
||||
if matches!(
|
||||
self.worktree_creation_status,
|
||||
Some(WorktreeCreationStatus::Creating)
|
||||
Some((_, WorktreeCreationStatus::Creating))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.worktree_creation_status = Some(WorktreeCreationStatus::Creating);
|
||||
let conversation_view_id = self
|
||||
.active_conversation_view()
|
||||
.map(|v| v.entity_id())
|
||||
.unwrap_or_else(|| EntityId::from(0u64));
|
||||
self.worktree_creation_status =
|
||||
Some((conversation_view_id, WorktreeCreationStatus::Creating));
|
||||
cx.notify();
|
||||
|
||||
let (git_repos, non_git_paths) = self.classify_worktrees(cx);
|
||||
@@ -3441,7 +3449,7 @@ impl Panel for AgentPanel {
|
||||
&& matches!(self.active_view, ActiveView::Uninitialized)
|
||||
&& !matches!(
|
||||
self.worktree_creation_status,
|
||||
Some(WorktreeCreationStatus::Creating)
|
||||
Some((_, WorktreeCreationStatus::Creating))
|
||||
)
|
||||
{
|
||||
let selected_agent = self.selected_agent.clone();
|
||||
@@ -3681,13 +3689,19 @@ impl AgentPanel {
|
||||
!self.project.read(cx).repositories(cx).is_empty()
|
||||
}
|
||||
|
||||
fn is_active_view_creating_worktree(&self, _cx: &App) -> bool {
|
||||
match &self.worktree_creation_status {
|
||||
Some((view_id, WorktreeCreationStatus::Creating)) => {
|
||||
self.active_conversation_view().map(|v| v.entity_id()) == Some(*view_id)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn render_start_thread_in_selector(&self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let focus_handle = self.focus_handle(cx);
|
||||
|
||||
let is_creating = matches!(
|
||||
self.worktree_creation_status,
|
||||
Some(WorktreeCreationStatus::Creating)
|
||||
);
|
||||
let is_creating = self.is_active_view_creating_worktree(cx);
|
||||
|
||||
let trigger_parts = self
|
||||
.start_thread_in
|
||||
@@ -3740,10 +3754,7 @@ impl AgentPanel {
|
||||
}
|
||||
|
||||
fn render_new_worktree_branch_selector(&self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let is_creating = matches!(
|
||||
self.worktree_creation_status,
|
||||
Some(WorktreeCreationStatus::Creating)
|
||||
);
|
||||
let is_creating = self.is_active_view_creating_worktree(cx);
|
||||
|
||||
let project_ref = self.project.read(cx);
|
||||
let trigger_parts = self
|
||||
@@ -4211,7 +4222,11 @@ impl AgentPanel {
|
||||
}
|
||||
|
||||
fn render_worktree_creation_status(&self, cx: &mut Context<Self>) -> Option<AnyElement> {
|
||||
let status = self.worktree_creation_status.as_ref()?;
|
||||
let (view_id, status) = self.worktree_creation_status.as_ref()?;
|
||||
let active_view_id = self.active_conversation_view().map(|v| v.entity_id());
|
||||
if active_view_id != Some(*view_id) {
|
||||
return None;
|
||||
}
|
||||
match status {
|
||||
WorktreeCreationStatus::Creating => Some(
|
||||
h_flex()
|
||||
@@ -4751,10 +4766,11 @@ impl AgentPanel {
|
||||
///
|
||||
/// This is a test-only helper for visual tests.
|
||||
pub fn worktree_creation_status_for_tests(&self) -> Option<&WorktreeCreationStatus> {
|
||||
self.worktree_creation_status.as_ref()
|
||||
self.worktree_creation_status.as_ref().map(|(_, s)| s)
|
||||
}
|
||||
|
||||
/// Sets the worktree creation status directly.
|
||||
/// Sets the worktree creation status directly, associating it with the
|
||||
/// currently active conversation view.
|
||||
///
|
||||
/// This is a test-only helper for visual tests that need to show the
|
||||
/// "Creating worktree…" spinner or error banners.
|
||||
@@ -4763,7 +4779,13 @@ impl AgentPanel {
|
||||
status: Option<WorktreeCreationStatus>,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.worktree_creation_status = status;
|
||||
self.worktree_creation_status = status.map(|s| {
|
||||
let view_id = self
|
||||
.active_conversation_view()
|
||||
.map(|v| v.entity_id())
|
||||
.unwrap_or_else(|| EntityId::from(0u64));
|
||||
(view_id, s)
|
||||
});
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
@@ -6011,7 +6033,8 @@ mod tests {
|
||||
|
||||
// Simulate worktree creation in progress and reset to Uninitialized
|
||||
panel.update_in(cx, |panel, window, cx| {
|
||||
panel.worktree_creation_status = Some(WorktreeCreationStatus::Creating);
|
||||
panel.worktree_creation_status =
|
||||
Some((EntityId::from(0u64), WorktreeCreationStatus::Creating));
|
||||
panel.active_view = ActiveView::Uninitialized;
|
||||
Panel::set_active(panel, true, window, cx);
|
||||
assert!(
|
||||
|
||||
Reference in new issue
Block a user