From 756358b9c76c6af10d986af6afa69cd1859c5b4f Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Wed, 2 Jul 2025 14:16:27 -0600 Subject: [PATCH] Handle loading outside of a project --- crates/acp/src/thread_view.rs | 96 +++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/crates/acp/src/thread_view.rs b/crates/acp/src/thread_view.rs index 4c570c9c073a8fe3bbd7c8bfeb0b76a3817b307c..5dbeb57bc29cf885226b294ce8a9524ee21c6062 100644 --- a/crates/acp/src/thread_view.rs +++ b/crates/acp/src/thread_view.rs @@ -47,13 +47,64 @@ enum ThreadState { impl AcpThreadView { pub fn new(project: Entity, window: &mut Window, cx: &mut Context) -> Self { + let message_editor = cx.new(|cx| { + let buffer = cx.new(|cx| Buffer::local("", cx)); + let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx)); + + let mut editor = Editor::new( + editor::EditorMode::AutoHeight { + min_lines: 4, + max_lines: None, + }, + buffer, + None, + window, + cx, + ); + editor.set_placeholder_text("Send a message", cx); + editor.set_soft_wrap(); + editor + }); + + let list_state = ListState::new( + 0, + gpui::ListAlignment::Bottom, + px(2048.0), + cx.processor({ + move |this: &mut Self, item: usize, window, cx| { + let Some(entry) = this + .thread() + .and_then(|thread| thread.read(cx).entries.get(item)) + else { + return Empty.into_any(); + }; + this.render_entry(entry, window, cx) + } + }), + ); + + Self { + thread_state: Self::initial_state(project, window, cx), + message_editor, + send_task: None, + list_state: list_state, + } + } + + fn initial_state( + project: Entity, + window: &mut Window, + cx: &mut Context, + ) -> ThreadState { let Some(root_dir) = project .read(cx) .visible_worktrees(cx) .next() .map(|worktree| worktree.read(cx).abs_path()) else { - todo!(); + return ThreadState::LoadError( + "Gemini threads must be created within a project".into(), + ); }; let cli_path = @@ -70,25 +121,6 @@ impl AcpThreadView { .spawn() .unwrap(); - let message_editor = cx.new(|cx| { - let buffer = cx.new(|cx| Buffer::local("", cx)); - let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx)); - - let mut editor = Editor::new( - editor::EditorMode::AutoHeight { - min_lines: 4, - max_lines: None, - }, - buffer, - None, - window, - cx, - ); - editor.set_placeholder_text("Send a message", cx); - editor.set_soft_wrap(); - editor - }); - let project = project.clone(); let load_task = cx.spawn_in(window, async move |this, cx| { let agent = AcpServer::stdio(child, project, cx); @@ -136,29 +168,7 @@ impl AcpThreadView { .log_err(); }); - let list_state = ListState::new( - 0, - gpui::ListAlignment::Bottom, - px(2048.0), - cx.processor({ - move |this: &mut Self, item: usize, window, cx| { - let Some(entry) = this - .thread() - .and_then(|thread| thread.read(cx).entries.get(item)) - else { - return Empty.into_any(); - }; - this.render_entry(entry, window, cx) - } - }), - ); - - Self { - thread_state: ThreadState::Loading { _task: load_task }, - message_editor, - send_task: None, - list_state: list_state, - } + ThreadState::Loading { _task: load_task } } fn thread(&self) -> Option<&Entity> {