Detailed changes
@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.31947 5.03803L8.31947 9.28259" stroke="#C6CAD0" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M6.19576 7.67419L8.31948 9.79792L10.4432 7.67419" stroke="#C6CAD0" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M5.64894 12.8952C6.89401 13.5339 8.32626 13.7069 9.68759 13.383C11.0489 13.0592 12.2499 12.2598 13.0739 11.1288C13.8979 9.99787 14.291 8.60973 14.1821 7.21464C14.0733 5.81955 13.4698 4.5092 12.4803 3.51972C11.4908 2.53024 10.1805 1.92671 8.78535 1.81787C7.39026 1.70904 6.00218 2.10207 4.87122 2.92612C3.74026 3.75018 2.94082 4.95106 2.61695 6.3124C2.29307 7.67374 2.46606 9.10598 3.10475 10.3511L1.80005 14.1999L5.64894 12.8952Z" stroke="#C6CAD0" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
@@ -121,18 +121,6 @@ impl ThreadImportModal {
.collect()
}
- fn set_agent_checked(&mut self, agent_id: AgentId, state: ToggleState, cx: &mut Context<Self>) {
- match state {
- ToggleState::Selected => {
- self.unchecked_agents.remove(&agent_id);
- }
- ToggleState::Unselected | ToggleState::Indeterminate => {
- self.unchecked_agents.insert(agent_id);
- }
- }
- cx.notify();
- }
-
fn toggle_agent_checked(&mut self, agent_id: AgentId, cx: &mut Context<Self>) {
if self.unchecked_agents.contains(&agent_id) {
self.unchecked_agents.remove(&agent_id);
@@ -283,6 +271,11 @@ impl ModalView for ThreadImportModal {}
impl Render for ThreadImportModal {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ let has_agents = !self.agent_entries.is_empty();
+ let disabled_import_thread = self.is_importing
+ || !has_agents
+ || self.unchecked_agents.len() == self.agent_entries.len();
+
let agent_rows = self
.agent_entries
.iter()
@@ -295,6 +288,7 @@ impl Render for ThreadImportModal {
.rounded()
.spacing(ListItemSpacing::Sparse)
.focused(is_focused)
+ .disabled(self.is_importing)
.child(
h_flex()
.w_full()
@@ -311,22 +305,14 @@ impl Render for ThreadImportModal {
})
.child(Label::new(entry.display_name.clone())),
)
- .end_slot(
- Checkbox::new(
- ("thread-import-agent-checkbox", ix),
- if is_checked {
- ToggleState::Selected
- } else {
- ToggleState::Unselected
- },
- )
- .on_click({
- let agent_id = entry.agent_id.clone();
- cx.listener(move |this, state: &ToggleState, _window, cx| {
- this.set_agent_checked(agent_id.clone(), *state, cx);
- })
- }),
- )
+ .end_slot(Checkbox::new(
+ ("thread-import-agent-checkbox", ix),
+ if is_checked {
+ ToggleState::Selected
+ } else {
+ ToggleState::Unselected
+ },
+ ))
.on_click({
let agent_id = entry.agent_id.clone();
cx.listener(move |this, _event, _window, cx| {
@@ -336,11 +322,6 @@ impl Render for ThreadImportModal {
})
.collect::<Vec<_>>();
- let has_agents = !self.agent_entries.is_empty();
- let disabled_import_thread = self.is_importing
- || !has_agents
- || self.unchecked_agents.len() == self.agent_entries.len();
-
v_flex()
.id("thread-import-modal")
.key_context("ThreadImportModal")
@@ -373,7 +354,7 @@ impl Render for ThreadImportModal {
v_flex()
.id("thread-import-agent-list")
.max_h(rems_from_px(320.))
- .pb_2()
+ .pb_1()
.overflow_y_scroll()
.when(has_agents, |this| this.children(agent_rows))
.when(!has_agents, |this| {
@@ -1,5 +1,5 @@
use crate::agent_connection_store::AgentConnectionStore;
-use crate::thread_import::{AcpThreadImportOnboarding, ThreadImportModal};
+
use crate::thread_metadata_store::{ThreadMetadata, ThreadMetadataStore};
use crate::{Agent, RemoveSelectedThread};
@@ -15,15 +15,13 @@ use gpui::{
};
use itertools::Itertools as _;
use menu::{Confirm, SelectFirst, SelectLast, SelectNext, SelectPrevious};
-use project::{AgentId, AgentRegistryStore, AgentServerStore};
+use project::{AgentId, AgentServerStore};
use settings::Settings as _;
use theme::ActiveTheme;
use ui::ThreadItem;
use ui::{
Divider, KeyBinding, Tooltip, WithScrollbar, prelude::*, utils::platform_title_bar_height,
};
-use util::ResultExt;
-use workspace::{MultiWorkspace, Workspace};
use zed_actions::agents_sidebar::FocusSidebarFilter;
use zed_actions::editor::{MoveDown, MoveUp};
@@ -114,18 +112,12 @@ pub struct ThreadsArchiveView {
_refresh_history_task: Task<()>,
agent_connection_store: WeakEntity<AgentConnectionStore>,
agent_server_store: WeakEntity<AgentServerStore>,
- agent_registry_store: WeakEntity<AgentRegistryStore>,
- workspace: WeakEntity<Workspace>,
- multi_workspace: WeakEntity<MultiWorkspace>,
}
impl ThreadsArchiveView {
pub fn new(
agent_connection_store: WeakEntity<AgentConnectionStore>,
agent_server_store: WeakEntity<AgentServerStore>,
- agent_registry_store: WeakEntity<AgentRegistryStore>,
- workspace: WeakEntity<Workspace>,
- multi_workspace: WeakEntity<MultiWorkspace>,
window: &mut Window,
cx: &mut Context<Self>,
) -> Self {
@@ -184,11 +176,8 @@ impl ThreadsArchiveView {
thread_metadata_store_subscription,
],
_refresh_history_task: Task::ready(()),
- agent_registry_store,
agent_connection_store,
agent_server_store,
- workspace,
- multi_workspace,
};
this.update_items(cx);
@@ -550,43 +539,6 @@ impl ThreadsArchiveView {
.detach_and_log_err(cx);
}
- fn should_render_acp_import_onboarding(&self, cx: &App) -> bool {
- let has_external_agents = self
- .agent_server_store
- .upgrade()
- .map(|store| store.read(cx).has_external_agents())
- .unwrap_or(false);
-
- has_external_agents && !AcpThreadImportOnboarding::dismissed(cx)
- }
-
- fn show_thread_import_modal(&mut self, window: &mut Window, cx: &mut Context<Self>) {
- let Some(agent_server_store) = self.agent_server_store.upgrade() else {
- return;
- };
- let Some(agent_registry_store) = self.agent_registry_store.upgrade() else {
- return;
- };
-
- let workspace_handle = self.workspace.clone();
- let multi_workspace = self.multi_workspace.clone();
-
- self.workspace
- .update(cx, |workspace, cx| {
- workspace.toggle_modal(window, cx, |window, cx| {
- ThreadImportModal::new(
- agent_server_store,
- agent_registry_store,
- workspace_handle.clone(),
- multi_workspace.clone(),
- window,
- cx,
- )
- });
- })
- .log_err();
- }
-
fn render_header(&self, window: &Window, cx: &mut Context<Self>) -> impl IntoElement {
let has_query = !self.filter_editor.read(cx).text(cx).is_empty();
let sidebar_on_left = matches!(
@@ -729,28 +681,5 @@ impl Render for ThreadsArchiveView {
.size_full()
.child(self.render_header(window, cx))
.child(content)
- .when(!self.should_render_acp_import_onboarding(cx), |this| {
- this.child(
- div()
- .w_full()
- .p_1p5()
- .border_t_1()
- .border_color(cx.theme().colors().border)
- .child(
- Button::new("import-acp", "Import ACP Threads")
- .full_width()
- .style(ButtonStyle::OutlinedCustom(cx.theme().colors().border))
- .label_size(LabelSize::Small)
- .start_icon(
- Icon::new(IconName::ArrowDown)
- .size(IconSize::XSmall)
- .color(Color::Muted),
- )
- .on_click(cx.listener(|this, _, window, cx| {
- this.show_thread_import_modal(window, cx);
- })),
- ),
- )
- })
}
}
@@ -240,6 +240,7 @@ pub enum IconName {
ThinkingModeOff,
Thread,
ThreadFromSummary,
+ ThreadImport,
ThreadsSidebarLeftClosed,
ThreadsSidebarLeftOpen,
ThreadsSidebarRightClosed,
@@ -3309,10 +3309,24 @@ impl Sidebar {
}
fn render_sidebar_bottom_bar(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
- let on_right = self.side(cx) == SidebarSide::Right;
let is_archive = matches!(self.view, SidebarView::Archive(..));
+ let show_import_button = is_archive && !self.should_render_acp_import_onboarding(cx);
+ let on_right = self.side(cx) == SidebarSide::Right;
+
let action_buttons = h_flex()
.gap_1()
+ .when(on_right, |this| this.flex_row_reverse())
+ .when(show_import_button, |this| {
+ this.child(
+ IconButton::new("thread-import", IconName::ThreadImport)
+ .icon_size(IconSize::Small)
+ .tooltip(Tooltip::text("Import ACP Threads"))
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.show_archive(window, cx);
+ this.show_thread_import_modal(window, cx);
+ })),
+ )
+ })
.child(
IconButton::new("archive", IconName::Archive)
.icon_size(IconSize::Small)
@@ -3325,21 +3339,16 @@ impl Sidebar {
})),
)
.child(self.render_recent_projects_button(cx));
- let border_color = cx.theme().colors().border;
- let toggle_button = self.render_sidebar_toggle_button(cx);
- let bar = h_flex()
+ h_flex()
.p_1()
.gap_1()
+ .when(on_right, |this| this.flex_row_reverse())
.justify_between()
.border_t_1()
- .border_color(border_color);
-
- if on_right {
- bar.child(action_buttons).child(toggle_button)
- } else {
- bar.child(toggle_button).child(action_buttons)
- }
+ .border_color(cx.theme().colors().border)
+ .child(self.render_sidebar_toggle_button(cx))
+ .child(action_buttons)
}
fn active_workspace(&self, cx: &App) -> Option<Entity<Workspace>> {
@@ -3409,7 +3418,7 @@ impl Sidebar {
v_flex()
.min_w_0()
.w_full()
- .p_1p5()
+ .p_2()
.border_t_1()
.border_color(cx.theme().colors().border)
.bg(linear_gradient(
@@ -3437,8 +3446,8 @@ impl Sidebar {
.style(ButtonStyle::OutlinedCustom(cx.theme().colors().border))
.label_size(LabelSize::Small)
.start_icon(
- Icon::new(IconName::ArrowDown)
- .size(IconSize::XSmall)
+ Icon::new(IconName::ThreadImport)
+ .size(IconSize::Small)
.color(Color::Muted),
)
.on_click(cx.listener(|this, _, window, cx| {
@@ -3467,9 +3476,6 @@ impl Sidebar {
let Some(agent_panel) = active_workspace.read(cx).panel::<AgentPanel>(cx) else {
return;
};
- let Some(agent_registry_store) = AgentRegistryStore::try_global(cx) else {
- return;
- };
let agent_server_store = active_workspace
.read(cx)
@@ -3484,9 +3490,6 @@ impl Sidebar {
ThreadsArchiveView::new(
agent_connection_store.clone(),
agent_server_store.clone(),
- agent_registry_store.downgrade(),
- active_workspace.downgrade(),
- self.multi_workspace.clone(),
window,
cx,
)
@@ -234,9 +234,9 @@ impl RenderOnce for ListItem {
this.ml(self.indent_level as f32 * self.indent_step_size)
.px(DynamicSpacing::Base04.rems(cx))
})
- .when(!self.inset && !self.disabled, |this| {
+ .when(!self.inset, |this| {
this.when_some(self.focused, |this, focused| {
- if focused {
+ if focused && !self.disabled {
this.border_1()
.when(self.docked_right, |this| this.border_r_2())
.border_color(cx.theme().colors().border_focused)
@@ -244,7 +244,7 @@ impl RenderOnce for ListItem {
this.border_1()
}
})
- .when(self.selectable, |this| {
+ .when(self.selectable && !self.disabled, |this| {
this.hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
.active(|style| style.bg(cx.theme().colors().ghost_element_active))
.when(self.outlined, |this| this.rounded_sm())
@@ -268,16 +268,16 @@ impl RenderOnce for ListItem {
ListItemSpacing::ExtraDense => this.py_neg_px(),
ListItemSpacing::Sparse => this.py_1(),
})
- .when(self.inset && !self.disabled, |this| {
+ .when(self.inset, |this| {
this.when_some(self.focused, |this, focused| {
- if focused {
+ if focused && !self.disabled {
this.border_1()
.border_color(cx.theme().colors().border_focused)
} else {
this.border_1()
}
})
- .when(self.selectable, |this| {
+ .when(self.selectable && !self.disabled, |this| {
this.hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
.active(|style| style.bg(cx.theme().colors().ghost_element_active))
.when(self.selected, |this| {