thread view: Add ability to expand message editor and fix scroll (#34766)
Release Notes: - N/A
This commit is contained in:
parent
88af35fe47
commit
56fd950d94
3 changed files with 135 additions and 51 deletions
|
@ -45,7 +45,8 @@ use ::acp_thread::{
|
||||||
use crate::acp::completion_provider::{ContextPickerCompletionProvider, MentionSet};
|
use crate::acp::completion_provider::{ContextPickerCompletionProvider, MentionSet};
|
||||||
use crate::acp::message_history::MessageHistory;
|
use crate::acp::message_history::MessageHistory;
|
||||||
use crate::agent_diff::AgentDiff;
|
use crate::agent_diff::AgentDiff;
|
||||||
use crate::{AgentDiffPane, Follow, KeepAll, OpenAgentDiff, RejectAll};
|
use crate::message_editor::{MAX_EDITOR_LINES, MIN_EDITOR_LINES};
|
||||||
|
use crate::{AgentDiffPane, ExpandMessageEditor, Follow, KeepAll, OpenAgentDiff, RejectAll};
|
||||||
|
|
||||||
const RESPONSE_PADDING_X: Pixels = px(19.);
|
const RESPONSE_PADDING_X: Pixels = px(19.);
|
||||||
|
|
||||||
|
@ -65,6 +66,7 @@ pub struct AcpThreadView {
|
||||||
expanded_tool_calls: HashSet<ToolCallId>,
|
expanded_tool_calls: HashSet<ToolCallId>,
|
||||||
expanded_thinking_blocks: HashSet<(usize, usize)>,
|
expanded_thinking_blocks: HashSet<(usize, usize)>,
|
||||||
edits_expanded: bool,
|
edits_expanded: bool,
|
||||||
|
editor_is_expanded: bool,
|
||||||
message_history: Rc<RefCell<MessageHistory<acp::SendUserMessageParams>>>,
|
message_history: Rc<RefCell<MessageHistory<acp::SendUserMessageParams>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +96,8 @@ impl AcpThreadView {
|
||||||
workspace: WeakEntity<Workspace>,
|
workspace: WeakEntity<Workspace>,
|
||||||
project: Entity<Project>,
|
project: Entity<Project>,
|
||||||
message_history: Rc<RefCell<MessageHistory<acp::SendUserMessageParams>>>,
|
message_history: Rc<RefCell<MessageHistory<acp::SendUserMessageParams>>>,
|
||||||
|
min_lines: usize,
|
||||||
|
max_lines: Option<usize>,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -113,8 +117,8 @@ impl AcpThreadView {
|
||||||
|
|
||||||
let mut editor = Editor::new(
|
let mut editor = Editor::new(
|
||||||
editor::EditorMode::AutoHeight {
|
editor::EditorMode::AutoHeight {
|
||||||
min_lines: 4,
|
min_lines,
|
||||||
max_lines: None,
|
max_lines: max_lines,
|
||||||
},
|
},
|
||||||
buffer,
|
buffer,
|
||||||
None,
|
None,
|
||||||
|
@ -182,6 +186,7 @@ impl AcpThreadView {
|
||||||
expanded_tool_calls: HashSet::default(),
|
expanded_tool_calls: HashSet::default(),
|
||||||
expanded_thinking_blocks: HashSet::default(),
|
expanded_thinking_blocks: HashSet::default(),
|
||||||
edits_expanded: false,
|
edits_expanded: false,
|
||||||
|
editor_is_expanded: false,
|
||||||
message_history,
|
message_history,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -321,6 +326,35 @@ impl AcpThreadView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn expand_message_editor(
|
||||||
|
&mut self,
|
||||||
|
_: &ExpandMessageEditor,
|
||||||
|
_window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) {
|
||||||
|
self.set_editor_is_expanded(!self.editor_is_expanded, cx);
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_editor_is_expanded(&mut self, is_expanded: bool, cx: &mut Context<Self>) {
|
||||||
|
self.editor_is_expanded = is_expanded;
|
||||||
|
self.message_editor.update(cx, |editor, _| {
|
||||||
|
if self.editor_is_expanded {
|
||||||
|
editor.set_mode(EditorMode::Full {
|
||||||
|
scale_ui_elements_with_buffer_font_size: false,
|
||||||
|
show_active_line_background: false,
|
||||||
|
sized_by_content: false,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
editor.set_mode(EditorMode::AutoHeight {
|
||||||
|
min_lines: MIN_EDITOR_LINES,
|
||||||
|
max_lines: Some(MAX_EDITOR_LINES),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
fn chat(&mut self, _: &Chat, window: &mut Window, cx: &mut Context<Self>) {
|
fn chat(&mut self, _: &Chat, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
self.last_error.take();
|
self.last_error.take();
|
||||||
|
|
||||||
|
@ -381,6 +415,7 @@ impl AcpThreadView {
|
||||||
|
|
||||||
let mention_set = self.mention_set.clone();
|
let mention_set = self.mention_set.clone();
|
||||||
|
|
||||||
|
self.set_editor_is_expanded(false, cx);
|
||||||
self.message_editor.update(cx, |editor, cx| {
|
self.message_editor.update(cx, |editor, cx| {
|
||||||
editor.clear(window, cx);
|
editor.clear(window, cx);
|
||||||
editor.remove_creases(mention_set.lock().drain(), cx)
|
editor.remove_creases(mention_set.lock().drain(), cx)
|
||||||
|
@ -1793,7 +1828,32 @@ impl AcpThreadView {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_message_editor(&mut self, cx: &mut Context<Self>) -> AnyElement {
|
fn render_message_editor(&mut self, window: &mut Window, cx: &mut Context<Self>) -> AnyElement {
|
||||||
|
let focus_handle = self.message_editor.focus_handle(cx);
|
||||||
|
let editor_bg_color = cx.theme().colors().editor_background;
|
||||||
|
let (expand_icon, expand_tooltip) = if self.editor_is_expanded {
|
||||||
|
(IconName::Minimize, "Minimize Message Editor")
|
||||||
|
} else {
|
||||||
|
(IconName::Maximize, "Expand Message Editor")
|
||||||
|
};
|
||||||
|
|
||||||
|
v_flex()
|
||||||
|
.on_action(cx.listener(Self::expand_message_editor))
|
||||||
|
.p_2()
|
||||||
|
.gap_2()
|
||||||
|
.border_t_1()
|
||||||
|
.border_color(cx.theme().colors().border)
|
||||||
|
.bg(editor_bg_color)
|
||||||
|
.when(self.editor_is_expanded, |this| {
|
||||||
|
this.h(vh(0.8, window)).size_full().justify_between()
|
||||||
|
})
|
||||||
|
.child(
|
||||||
|
v_flex()
|
||||||
|
.relative()
|
||||||
|
.size_full()
|
||||||
|
.pt_1()
|
||||||
|
.pr_2p5()
|
||||||
|
.child(div().flex_1().child({
|
||||||
let settings = ThemeSettings::get_global(cx);
|
let settings = ThemeSettings::get_global(cx);
|
||||||
let font_size = TextSize::Small
|
let font_size = TextSize::Small
|
||||||
.rems(cx)
|
.rems(cx)
|
||||||
|
@ -1813,13 +1873,50 @@ impl AcpThreadView {
|
||||||
EditorElement::new(
|
EditorElement::new(
|
||||||
&self.message_editor,
|
&self.message_editor,
|
||||||
EditorStyle {
|
EditorStyle {
|
||||||
background: cx.theme().colors().editor_background,
|
background: editor_bg_color,
|
||||||
local_player: cx.theme().players().local(),
|
local_player: cx.theme().players().local(),
|
||||||
text: text_style,
|
text: text_style,
|
||||||
syntax: cx.theme().syntax().clone(),
|
syntax: cx.theme().syntax().clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
}))
|
||||||
|
.child(
|
||||||
|
h_flex()
|
||||||
|
.absolute()
|
||||||
|
.top_0()
|
||||||
|
.right_0()
|
||||||
|
.opacity(0.5)
|
||||||
|
.hover(|this| this.opacity(1.0))
|
||||||
|
.child(
|
||||||
|
IconButton::new("toggle-height", expand_icon)
|
||||||
|
.icon_size(IconSize::XSmall)
|
||||||
|
.icon_color(Color::Muted)
|
||||||
|
.tooltip({
|
||||||
|
let focus_handle = focus_handle.clone();
|
||||||
|
move |window, cx| {
|
||||||
|
Tooltip::for_action_in(
|
||||||
|
expand_tooltip,
|
||||||
|
&ExpandMessageEditor,
|
||||||
|
&focus_handle,
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on_click(cx.listener(|_, _, window, cx| {
|
||||||
|
window.dispatch_action(Box::new(ExpandMessageEditor), cx);
|
||||||
|
})),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
h_flex()
|
||||||
|
.flex_none()
|
||||||
|
.justify_between()
|
||||||
|
.child(self.render_follow_toggle(cx))
|
||||||
|
.child(self.render_send_button(cx)),
|
||||||
|
)
|
||||||
.into_any()
|
.into_any()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2132,7 +2229,6 @@ impl Render for AcpThreadView {
|
||||||
.px(RESPONSE_PADDING_X)
|
.px(RESPONSE_PADDING_X)
|
||||||
.opacity(0.4)
|
.opacity(0.4)
|
||||||
.hover(|style| style.opacity(1.))
|
.hover(|style| style.opacity(1.))
|
||||||
.gap_1()
|
|
||||||
.flex_wrap()
|
.flex_wrap()
|
||||||
.justify_end()
|
.justify_end()
|
||||||
.child(open_as_markdown)
|
.child(open_as_markdown)
|
||||||
|
@ -2166,22 +2262,7 @@ impl Render for AcpThreadView {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.child(
|
.child(self.render_message_editor(window, cx))
|
||||||
v_flex()
|
|
||||||
.p_2()
|
|
||||||
.pt_3()
|
|
||||||
.gap_1()
|
|
||||||
.bg(cx.theme().colors().editor_background)
|
|
||||||
.border_t_1()
|
|
||||||
.border_color(cx.theme().colors().border)
|
|
||||||
.child(self.render_message_editor(cx))
|
|
||||||
.child(
|
|
||||||
h_flex()
|
|
||||||
.justify_between()
|
|
||||||
.child(self.render_follow_toggle(cx))
|
|
||||||
.child(self.render_send_button(cx)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::NewExternalAgentThread;
|
use crate::NewExternalAgentThread;
|
||||||
use crate::agent_diff::AgentDiffThread;
|
use crate::agent_diff::AgentDiffThread;
|
||||||
|
use crate::message_editor::{MAX_EDITOR_LINES, MIN_EDITOR_LINES};
|
||||||
use crate::{
|
use crate::{
|
||||||
AddContextServer, AgentDiffPane, ContinueThread, ContinueWithBurnMode,
|
AddContextServer, AgentDiffPane, ContinueThread, ContinueWithBurnMode,
|
||||||
DeleteRecentlyOpenThread, ExpandMessageEditor, Follow, InlineAssistant, NewTextThread,
|
DeleteRecentlyOpenThread, ExpandMessageEditor, Follow, InlineAssistant, NewTextThread,
|
||||||
|
@ -960,6 +961,8 @@ impl AgentPanel {
|
||||||
workspace.clone(),
|
workspace.clone(),
|
||||||
project,
|
project,
|
||||||
message_history,
|
message_history,
|
||||||
|
MIN_EDITOR_LINES,
|
||||||
|
Some(MAX_EDITOR_LINES),
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
|
|
@ -65,6 +65,9 @@ use agent::{
|
||||||
thread_store::{TextThreadStore, ThreadStore},
|
thread_store::{TextThreadStore, ThreadStore},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const MIN_EDITOR_LINES: usize = 4;
|
||||||
|
pub const MAX_EDITOR_LINES: usize = 8;
|
||||||
|
|
||||||
#[derive(RegisterComponent)]
|
#[derive(RegisterComponent)]
|
||||||
pub struct MessageEditor {
|
pub struct MessageEditor {
|
||||||
thread: Entity<Thread>,
|
thread: Entity<Thread>,
|
||||||
|
@ -88,9 +91,6 @@ pub struct MessageEditor {
|
||||||
_subscriptions: Vec<Subscription>,
|
_subscriptions: Vec<Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const MIN_EDITOR_LINES: usize = 4;
|
|
||||||
const MAX_EDITOR_LINES: usize = 8;
|
|
||||||
|
|
||||||
pub(crate) fn create_editor(
|
pub(crate) fn create_editor(
|
||||||
workspace: WeakEntity<Workspace>,
|
workspace: WeakEntity<Workspace>,
|
||||||
context_store: WeakEntity<ContextStore>,
|
context_store: WeakEntity<ContextStore>,
|
||||||
|
@ -711,11 +711,11 @@ impl MessageEditor {
|
||||||
cx.listener(|this, _: &RejectAll, window, cx| this.handle_reject_all(window, cx)),
|
cx.listener(|this, _: &RejectAll, window, cx| this.handle_reject_all(window, cx)),
|
||||||
)
|
)
|
||||||
.capture_action(cx.listener(Self::paste))
|
.capture_action(cx.listener(Self::paste))
|
||||||
.gap_2()
|
|
||||||
.p_2()
|
.p_2()
|
||||||
.bg(editor_bg_color)
|
.gap_2()
|
||||||
.border_t_1()
|
.border_t_1()
|
||||||
.border_color(cx.theme().colors().border)
|
.border_color(cx.theme().colors().border)
|
||||||
|
.bg(editor_bg_color)
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue