assistant2: Focus prompt editor after dismissing context picker (#22786)

https://github.com/user-attachments/assets/6d0ac75e-fbc2-4bc2-be13-2d109f61361b




Release Notes:

- N/A
This commit is contained in:
Agus Zubiaga 2025-01-07 15:40:16 -03:00 committed by GitHub
parent d3fc00d5a0
commit deeccd2c63
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 109 additions and 46 deletions

View file

@ -1,7 +1,10 @@
use std::rc::Rc; use std::rc::Rc;
use editor::Editor; use editor::Editor;
use gpui::{AppContext, FocusHandle, Model, View, WeakModel, WeakView}; use gpui::{
AppContext, DismissEvent, EventEmitter, FocusHandle, Model, Subscription, View, WeakModel,
WeakView,
};
use language::Buffer; use language::Buffer;
use ui::{prelude::*, KeyBinding, PopoverMenu, PopoverMenuHandle, Tooltip}; use ui::{prelude::*, KeyBinding, PopoverMenu, PopoverMenuHandle, Tooltip};
use workspace::Workspace; use workspace::Workspace;
@ -21,6 +24,7 @@ pub struct ContextStrip {
focus_handle: FocusHandle, focus_handle: FocusHandle,
suggest_context_kind: SuggestContextKind, suggest_context_kind: SuggestContextKind,
workspace: WeakView<Workspace>, workspace: WeakView<Workspace>,
_context_picker_subscription: Subscription,
} }
impl ContextStrip { impl ContextStrip {
@ -33,21 +37,27 @@ impl ContextStrip {
suggest_context_kind: SuggestContextKind, suggest_context_kind: SuggestContextKind,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> Self { ) -> Self {
let context_picker = cx.new_view(|cx| {
ContextPicker::new(
workspace.clone(),
thread_store.clone(),
context_store.downgrade(),
ConfirmBehavior::KeepOpen,
cx,
)
});
let context_picker_subscription =
cx.subscribe(&context_picker, Self::handle_context_picker_event);
Self { Self {
context_store: context_store.clone(), context_store: context_store.clone(),
context_picker: cx.new_view(|cx| { context_picker,
ContextPicker::new(
workspace.clone(),
thread_store.clone(),
context_store.downgrade(),
ConfirmBehavior::KeepOpen,
cx,
)
}),
context_picker_menu_handle, context_picker_menu_handle,
focus_handle, focus_handle,
suggest_context_kind, suggest_context_kind,
workspace, workspace,
_context_picker_subscription: context_picker_subscription,
} }
} }
@ -107,6 +117,15 @@ impl ContextStrip {
thread: weak_active_thread, thread: weak_active_thread,
}) })
} }
fn handle_context_picker_event(
&mut self,
_picker: View<ContextPicker>,
_event: &DismissEvent,
cx: &mut ViewContext<Self>,
) {
cx.emit(ContextStripEvent::PickerDismissed);
}
} }
impl Render for ContextStrip { impl Render for ContextStrip {
@ -221,6 +240,12 @@ impl Render for ContextStrip {
} }
} }
pub enum ContextStripEvent {
PickerDismissed,
}
impl EventEmitter<ContextStripEvent> for ContextStrip {}
pub enum SuggestContextKind { pub enum SuggestContextKind {
File, File,
Thread, Thread,

View file

@ -2,7 +2,7 @@ use crate::assistant_model_selector::AssistantModelSelector;
use crate::buffer_codegen::BufferCodegen; use crate::buffer_codegen::BufferCodegen;
use crate::context_picker::ContextPicker; use crate::context_picker::ContextPicker;
use crate::context_store::ContextStore; use crate::context_store::ContextStore;
use crate::context_strip::{ContextStrip, SuggestContextKind}; use crate::context_strip::{ContextStrip, ContextStripEvent, SuggestContextKind};
use crate::terminal_codegen::TerminalCodegen; use crate::terminal_codegen::TerminalCodegen;
use crate::thread_store::ThreadStore; use crate::thread_store::ThreadStore;
use crate::{CycleNextInlineAssist, CyclePreviousInlineAssist}; use crate::{CycleNextInlineAssist, CyclePreviousInlineAssist};
@ -47,6 +47,7 @@ pub struct PromptEditor<T> {
pending_prompt: String, pending_prompt: String,
_codegen_subscription: Subscription, _codegen_subscription: Subscription,
editor_subscriptions: Vec<Subscription>, editor_subscriptions: Vec<Subscription>,
_context_strip_subscription: Subscription,
show_rate_limit_notice: bool, show_rate_limit_notice: bool,
_phantom: std::marker::PhantomData<T>, _phantom: std::marker::PhantomData<T>,
} }
@ -726,6 +727,16 @@ impl<T: 'static> PromptEditor<T> {
}) })
.into_any_element() .into_any_element()
} }
fn handle_context_strip_event(
&mut self,
_context_strip: View<ContextStrip>,
ContextStripEvent::PickerDismissed: &ContextStripEvent,
cx: &mut ViewContext<Self>,
) {
let editor_focus_handle = self.editor.focus_handle(cx);
cx.focus(&editor_focus_handle);
}
} }
pub enum PromptEditorMode { pub enum PromptEditorMode {
@ -803,19 +814,24 @@ impl PromptEditor<BufferCodegen> {
let context_picker_menu_handle = PopoverMenuHandle::default(); let context_picker_menu_handle = PopoverMenuHandle::default();
let model_selector_menu_handle = PopoverMenuHandle::default(); let model_selector_menu_handle = PopoverMenuHandle::default();
let context_strip = cx.new_view(|cx| {
ContextStrip::new(
context_store,
workspace.clone(),
thread_store.clone(),
prompt_editor.focus_handle(cx),
context_picker_menu_handle.clone(),
SuggestContextKind::Thread,
cx,
)
});
let context_strip_subscription =
cx.subscribe(&context_strip, Self::handle_context_strip_event);
let mut this: PromptEditor<BufferCodegen> = PromptEditor { let mut this: PromptEditor<BufferCodegen> = PromptEditor {
editor: prompt_editor.clone(), editor: prompt_editor.clone(),
context_strip: cx.new_view(|cx| { context_strip,
ContextStrip::new(
context_store,
workspace.clone(),
thread_store.clone(),
prompt_editor.focus_handle(cx),
context_picker_menu_handle.clone(),
SuggestContextKind::Thread,
cx,
)
}),
context_picker_menu_handle, context_picker_menu_handle,
model_selector: cx.new_view(|cx| { model_selector: cx.new_view(|cx| {
AssistantModelSelector::new(fs, model_selector_menu_handle.clone(), cx) AssistantModelSelector::new(fs, model_selector_menu_handle.clone(), cx)
@ -827,6 +843,7 @@ impl PromptEditor<BufferCodegen> {
pending_prompt: String::new(), pending_prompt: String::new(),
_codegen_subscription: codegen_subscription, _codegen_subscription: codegen_subscription,
editor_subscriptions: Vec::new(), editor_subscriptions: Vec::new(),
_context_strip_subscription: context_strip_subscription,
show_rate_limit_notice: false, show_rate_limit_notice: false,
mode, mode,
_phantom: Default::default(), _phantom: Default::default(),
@ -943,19 +960,24 @@ impl PromptEditor<TerminalCodegen> {
let context_picker_menu_handle = PopoverMenuHandle::default(); let context_picker_menu_handle = PopoverMenuHandle::default();
let model_selector_menu_handle = PopoverMenuHandle::default(); let model_selector_menu_handle = PopoverMenuHandle::default();
let context_strip = cx.new_view(|cx| {
ContextStrip::new(
context_store,
workspace.clone(),
thread_store.clone(),
prompt_editor.focus_handle(cx),
context_picker_menu_handle.clone(),
SuggestContextKind::Thread,
cx,
)
});
let context_strip_subscription =
cx.subscribe(&context_strip, Self::handle_context_strip_event);
let mut this = Self { let mut this = Self {
editor: prompt_editor.clone(), editor: prompt_editor.clone(),
context_strip: cx.new_view(|cx| { context_strip,
ContextStrip::new(
context_store,
workspace.clone(),
thread_store.clone(),
prompt_editor.focus_handle(cx),
context_picker_menu_handle.clone(),
SuggestContextKind::Thread,
cx,
)
}),
context_picker_menu_handle, context_picker_menu_handle,
model_selector: cx.new_view(|cx| { model_selector: cx.new_view(|cx| {
AssistantModelSelector::new(fs, model_selector_menu_handle.clone(), cx) AssistantModelSelector::new(fs, model_selector_menu_handle.clone(), cx)
@ -967,6 +989,7 @@ impl PromptEditor<TerminalCodegen> {
pending_prompt: String::new(), pending_prompt: String::new(),
_codegen_subscription: codegen_subscription, _codegen_subscription: codegen_subscription,
editor_subscriptions: Vec::new(), editor_subscriptions: Vec::new(),
_context_strip_subscription: context_strip_subscription,
mode, mode,
show_rate_limit_notice: false, show_rate_limit_notice: false,
_phantom: Default::default(), _phantom: Default::default(),

View file

@ -20,7 +20,7 @@ use workspace::Workspace;
use crate::assistant_model_selector::AssistantModelSelector; use crate::assistant_model_selector::AssistantModelSelector;
use crate::context_picker::{ConfirmBehavior, ContextPicker}; use crate::context_picker::{ConfirmBehavior, ContextPicker};
use crate::context_store::ContextStore; use crate::context_store::ContextStore;
use crate::context_strip::{ContextStrip, SuggestContextKind}; use crate::context_strip::{ContextStrip, ContextStripEvent, SuggestContextKind};
use crate::thread::{RequestKind, Thread}; use crate::thread::{RequestKind, Thread};
use crate::thread_store::ThreadStore; use crate::thread_store::ThreadStore;
use crate::{Chat, ToggleContextPicker, ToggleModelSelector}; use crate::{Chat, ToggleContextPicker, ToggleModelSelector};
@ -59,6 +59,7 @@ impl MessageEditor {
editor editor
}); });
let inline_context_picker = cx.new_view(|cx| { let inline_context_picker = cx.new_view(|cx| {
ContextPicker::new( ContextPicker::new(
workspace.clone(), workspace.clone(),
@ -68,29 +69,33 @@ impl MessageEditor {
cx, cx,
) )
}); });
let context_strip = cx.new_view(|cx| {
ContextStrip::new(
context_store.clone(),
workspace.clone(),
Some(thread_store.clone()),
editor.focus_handle(cx),
context_picker_menu_handle.clone(),
SuggestContextKind::File,
cx,
)
});
let subscriptions = vec![ let subscriptions = vec![
cx.subscribe(&editor, Self::handle_editor_event), cx.subscribe(&editor, Self::handle_editor_event),
cx.subscribe( cx.subscribe(
&inline_context_picker, &inline_context_picker,
Self::handle_inline_context_picker_event, Self::handle_inline_context_picker_event,
), ),
cx.subscribe(&context_strip, Self::handle_context_strip_event),
]; ];
Self { Self {
thread, thread,
editor: editor.clone(), editor: editor.clone(),
context_store: context_store.clone(), context_store,
context_strip: cx.new_view(|cx| { context_strip,
ContextStrip::new(
context_store,
workspace.clone(),
Some(thread_store.clone()),
editor.focus_handle(cx),
context_picker_menu_handle.clone(),
SuggestContextKind::File,
cx,
)
}),
context_picker_menu_handle, context_picker_menu_handle,
inline_context_picker, inline_context_picker,
inline_context_picker_menu_handle, inline_context_picker_menu_handle,
@ -195,6 +200,16 @@ impl MessageEditor {
let editor_focus_handle = self.editor.focus_handle(cx); let editor_focus_handle = self.editor.focus_handle(cx);
cx.focus(&editor_focus_handle); cx.focus(&editor_focus_handle);
} }
fn handle_context_strip_event(
&mut self,
_context_strip: View<ContextStrip>,
ContextStripEvent::PickerDismissed: &ContextStripEvent,
cx: &mut ViewContext<Self>,
) {
let editor_focus_handle = self.editor.focus_handle(cx);
cx.focus(&editor_focus_handle);
}
} }
impl FocusableView for MessageEditor { impl FocusableView for MessageEditor {