markdown: Move open_url
to the MarkdownElement
as on_url_click
(#28269)
Release Notes: - N/A --------- Co-authored-by: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
parent
d3abc61728
commit
0414908c4a
6 changed files with 201 additions and 194 deletions
|
@ -76,7 +76,6 @@ impl RenderedMessage {
|
|||
fn from_segments(
|
||||
segments: &[MessageSegment],
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
cx: &mut App,
|
||||
) -> Self {
|
||||
let mut this = Self {
|
||||
|
@ -84,12 +83,12 @@ impl RenderedMessage {
|
|||
segments: Vec::with_capacity(segments.len()),
|
||||
};
|
||||
for segment in segments {
|
||||
this.push_segment(segment, workspace.clone(), cx);
|
||||
this.push_segment(segment, cx);
|
||||
}
|
||||
this
|
||||
}
|
||||
|
||||
fn append_thinking(&mut self, text: &String, workspace: WeakEntity<Workspace>, cx: &mut App) {
|
||||
fn append_thinking(&mut self, text: &String, cx: &mut App) {
|
||||
if let Some(RenderedMessageSegment::Thinking {
|
||||
content,
|
||||
scroll_handle,
|
||||
|
@ -101,18 +100,13 @@ impl RenderedMessage {
|
|||
scroll_handle.scroll_to_bottom();
|
||||
} else {
|
||||
self.segments.push(RenderedMessageSegment::Thinking {
|
||||
content: render_markdown(
|
||||
text.into(),
|
||||
self.language_registry.clone(),
|
||||
workspace,
|
||||
cx,
|
||||
),
|
||||
content: render_markdown(text.into(), self.language_registry.clone(), cx),
|
||||
scroll_handle: ScrollHandle::default(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn append_text(&mut self, text: &String, workspace: WeakEntity<Workspace>, cx: &mut App) {
|
||||
fn append_text(&mut self, text: &String, cx: &mut App) {
|
||||
if let Some(RenderedMessageSegment::Text(markdown)) = self.segments.last_mut() {
|
||||
markdown.update(cx, |markdown, cx| markdown.append(text, cx));
|
||||
} else {
|
||||
|
@ -120,32 +114,20 @@ impl RenderedMessage {
|
|||
.push(RenderedMessageSegment::Text(render_markdown(
|
||||
SharedString::from(text),
|
||||
self.language_registry.clone(),
|
||||
workspace,
|
||||
cx,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
fn push_segment(
|
||||
&mut self,
|
||||
segment: &MessageSegment,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
cx: &mut App,
|
||||
) {
|
||||
fn push_segment(&mut self, segment: &MessageSegment, cx: &mut App) {
|
||||
let rendered_segment = match segment {
|
||||
MessageSegment::Thinking(text) => RenderedMessageSegment::Thinking {
|
||||
content: render_markdown(
|
||||
text.into(),
|
||||
self.language_registry.clone(),
|
||||
workspace,
|
||||
cx,
|
||||
),
|
||||
content: render_markdown(text.into(), self.language_registry.clone(), cx),
|
||||
scroll_handle: ScrollHandle::default(),
|
||||
},
|
||||
MessageSegment::Text(text) => RenderedMessageSegment::Text(render_markdown(
|
||||
text.into(),
|
||||
self.language_registry.clone(),
|
||||
workspace,
|
||||
cx,
|
||||
)),
|
||||
};
|
||||
|
@ -164,14 +146,9 @@ enum RenderedMessageSegment {
|
|||
fn render_markdown(
|
||||
text: SharedString,
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
cx: &mut App,
|
||||
) -> Entity<Markdown> {
|
||||
cx.new(|cx| {
|
||||
Markdown::new(text, Some(language_registry), None, cx).open_url(move |text, window, cx| {
|
||||
open_markdown_link(text, workspace.clone(), window, cx);
|
||||
})
|
||||
})
|
||||
cx.new(|cx| Markdown::new(text, Some(language_registry), None, cx))
|
||||
}
|
||||
|
||||
fn default_markdown_style(window: &Window, cx: &App) -> MarkdownStyle {
|
||||
|
@ -261,14 +238,9 @@ fn default_markdown_style(window: &Window, cx: &App) -> MarkdownStyle {
|
|||
fn render_tool_use_markdown(
|
||||
text: SharedString,
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
cx: &mut App,
|
||||
) -> Entity<Markdown> {
|
||||
cx.new(|cx| {
|
||||
Markdown::new(text, Some(language_registry), None, cx).open_url(move |text, window, cx| {
|
||||
open_markdown_link(text, workspace.clone(), window, cx);
|
||||
})
|
||||
})
|
||||
cx.new(|cx| Markdown::new(text, Some(language_registry), None, cx))
|
||||
}
|
||||
|
||||
fn tool_use_markdown_style(window: &Window, cx: &mut App) -> MarkdownStyle {
|
||||
|
@ -502,12 +474,8 @@ impl ActiveThread {
|
|||
self.messages.push(*id);
|
||||
self.list_state.splice(old_len..old_len, 1);
|
||||
|
||||
let rendered_message = RenderedMessage::from_segments(
|
||||
segments,
|
||||
self.language_registry.clone(),
|
||||
self.workspace.clone(),
|
||||
cx,
|
||||
);
|
||||
let rendered_message =
|
||||
RenderedMessage::from_segments(segments, self.language_registry.clone(), cx);
|
||||
self.rendered_messages_by_id.insert(*id, rendered_message);
|
||||
}
|
||||
|
||||
|
@ -522,12 +490,8 @@ impl ActiveThread {
|
|||
return;
|
||||
};
|
||||
self.list_state.splice(index..index + 1, 1);
|
||||
let rendered_message = RenderedMessage::from_segments(
|
||||
segments,
|
||||
self.language_registry.clone(),
|
||||
self.workspace.clone(),
|
||||
cx,
|
||||
);
|
||||
let rendered_message =
|
||||
RenderedMessage::from_segments(segments, self.language_registry.clone(), cx);
|
||||
self.rendered_messages_by_id.insert(*id, rendered_message);
|
||||
}
|
||||
|
||||
|
@ -549,12 +513,7 @@ impl ActiveThread {
|
|||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let rendered = RenderedToolUse {
|
||||
label: render_tool_use_markdown(
|
||||
tool_label.into(),
|
||||
self.language_registry.clone(),
|
||||
self.workspace.clone(),
|
||||
cx,
|
||||
),
|
||||
label: render_tool_use_markdown(tool_label.into(), self.language_registry.clone(), cx),
|
||||
input: render_tool_use_markdown(
|
||||
format!(
|
||||
"```json\n{}\n```",
|
||||
|
@ -562,15 +521,9 @@ impl ActiveThread {
|
|||
)
|
||||
.into(),
|
||||
self.language_registry.clone(),
|
||||
self.workspace.clone(),
|
||||
cx,
|
||||
),
|
||||
output: render_tool_use_markdown(
|
||||
tool_output,
|
||||
self.language_registry.clone(),
|
||||
self.workspace.clone(),
|
||||
cx,
|
||||
),
|
||||
output: render_tool_use_markdown(tool_output, self.language_registry.clone(), cx),
|
||||
};
|
||||
self.rendered_tool_uses
|
||||
.insert(tool_use_id.clone(), rendered);
|
||||
|
@ -613,12 +566,12 @@ impl ActiveThread {
|
|||
}
|
||||
ThreadEvent::StreamedAssistantText(message_id, text) => {
|
||||
if let Some(rendered_message) = self.rendered_messages_by_id.get_mut(&message_id) {
|
||||
rendered_message.append_text(text, self.workspace.clone(), cx);
|
||||
rendered_message.append_text(text, cx);
|
||||
}
|
||||
}
|
||||
ThreadEvent::StreamedAssistantThinking(message_id, text) => {
|
||||
if let Some(rendered_message) = self.rendered_messages_by_id.get_mut(&message_id) {
|
||||
rendered_message.append_thinking(text, self.workspace.clone(), cx);
|
||||
rendered_message.append_thinking(text, cx);
|
||||
}
|
||||
}
|
||||
ThreadEvent::MessageAdded(message_id) => {
|
||||
|
@ -1550,10 +1503,18 @@ impl ActiveThread {
|
|||
)
|
||||
.into_any_element(),
|
||||
RenderedMessageSegment::Text(markdown) => div()
|
||||
.child(MarkdownElement::new(
|
||||
markdown.clone(),
|
||||
default_markdown_style(window, cx),
|
||||
))
|
||||
.child(
|
||||
MarkdownElement::new(
|
||||
markdown.clone(),
|
||||
default_markdown_style(window, cx),
|
||||
)
|
||||
.on_url_click({
|
||||
let workspace = self.workspace.clone();
|
||||
move |text, window, cx| {
|
||||
open_markdown_link(text, workspace.clone(), window, cx);
|
||||
}
|
||||
}),
|
||||
)
|
||||
.into_any_element(),
|
||||
},
|
||||
),
|
||||
|
@ -1712,10 +1673,23 @@ impl ActiveThread {
|
|||
.h_20()
|
||||
.track_scroll(scroll_handle)
|
||||
.text_ui_sm(cx)
|
||||
.child(MarkdownElement::new(
|
||||
markdown.clone(),
|
||||
default_markdown_style(window, cx),
|
||||
))
|
||||
.child(
|
||||
MarkdownElement::new(
|
||||
markdown.clone(),
|
||||
default_markdown_style(window, cx),
|
||||
)
|
||||
.on_url_click({
|
||||
let workspace = self.workspace.clone();
|
||||
move |text, window, cx| {
|
||||
open_markdown_link(
|
||||
text,
|
||||
workspace.clone(),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}),
|
||||
)
|
||||
.overflow_hidden(),
|
||||
)
|
||||
.child(gradient_overlay),
|
||||
|
@ -1730,10 +1704,18 @@ impl ActiveThread {
|
|||
.rounded_b_lg()
|
||||
.bg(editor_bg)
|
||||
.text_ui_sm(cx)
|
||||
.child(MarkdownElement::new(
|
||||
markdown.clone(),
|
||||
default_markdown_style(window, cx),
|
||||
)),
|
||||
.child(
|
||||
MarkdownElement::new(
|
||||
markdown.clone(),
|
||||
default_markdown_style(window, cx),
|
||||
)
|
||||
.on_url_click({
|
||||
let workspace = self.workspace.clone();
|
||||
move |text, window, cx| {
|
||||
open_markdown_link(text, workspace.clone(), window, cx);
|
||||
}
|
||||
}),
|
||||
),
|
||||
)
|
||||
}),
|
||||
)
|
||||
|
@ -1789,13 +1771,41 @@ impl ActiveThread {
|
|||
let rendered_tool_use = self.rendered_tool_uses.get(&tool_use.id).cloned();
|
||||
let results_content_container = || v_flex().p_2().gap_0p5();
|
||||
|
||||
let results_content =
|
||||
v_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
let results_content = v_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
results_content_container()
|
||||
.child(
|
||||
Label::new("Input")
|
||||
.size(LabelSize::XSmall)
|
||||
.color(Color::Muted)
|
||||
.buffer_font(cx),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w_full()
|
||||
.text_ui_sm(cx)
|
||||
.children(rendered_tool_use.as_ref().map(|rendered| {
|
||||
MarkdownElement::new(
|
||||
rendered.input.clone(),
|
||||
tool_use_markdown_style(window, cx),
|
||||
)
|
||||
.on_url_click({
|
||||
let workspace = self.workspace.clone();
|
||||
move |text, window, cx| {
|
||||
open_markdown_link(text, workspace.clone(), window, cx);
|
||||
}
|
||||
})
|
||||
})),
|
||||
),
|
||||
)
|
||||
.map(|container| match tool_use.status {
|
||||
ToolUseStatus::Finished(_) => container.child(
|
||||
results_content_container()
|
||||
.border_t_1()
|
||||
.border_color(self.tool_card_border_color(cx))
|
||||
.child(
|
||||
Label::new("Input")
|
||||
Label::new("Result")
|
||||
.size(LabelSize::XSmall)
|
||||
.color(Color::Muted)
|
||||
.buffer_font(cx),
|
||||
|
@ -1803,95 +1813,87 @@ impl ActiveThread {
|
|||
.child(div().w_full().text_ui_sm(cx).children(
|
||||
rendered_tool_use.as_ref().map(|rendered| {
|
||||
MarkdownElement::new(
|
||||
rendered.input.clone(),
|
||||
rendered.output.clone(),
|
||||
tool_use_markdown_style(window, cx),
|
||||
)
|
||||
.on_url_click({
|
||||
let workspace = self.workspace.clone();
|
||||
move |text, window, cx| {
|
||||
open_markdown_link(text, workspace.clone(), window, cx);
|
||||
}
|
||||
})
|
||||
}),
|
||||
)),
|
||||
)
|
||||
.map(|container| match tool_use.status {
|
||||
ToolUseStatus::Finished(_) => container.child(
|
||||
results_content_container()
|
||||
),
|
||||
ToolUseStatus::Running => container.child(
|
||||
results_content_container().child(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.pb_1()
|
||||
.border_t_1()
|
||||
.border_color(self.tool_card_border_color(cx))
|
||||
.child(
|
||||
Label::new("Result")
|
||||
.size(LabelSize::XSmall)
|
||||
.color(Color::Muted)
|
||||
.buffer_font(cx),
|
||||
Icon::new(IconName::ArrowCircle)
|
||||
.size(IconSize::Small)
|
||||
.color(Color::Accent)
|
||||
.with_animation(
|
||||
"arrow-circle",
|
||||
Animation::new(Duration::from_secs(2)).repeat(),
|
||||
|icon, delta| {
|
||||
icon.transform(Transformation::rotate(percentage(
|
||||
delta,
|
||||
)))
|
||||
},
|
||||
),
|
||||
)
|
||||
.child(div().w_full().text_ui_sm(cx).children(
|
||||
rendered_tool_use.as_ref().map(|rendered| {
|
||||
MarkdownElement::new(
|
||||
rendered.output.clone(),
|
||||
tool_use_markdown_style(window, cx),
|
||||
)
|
||||
}),
|
||||
)),
|
||||
),
|
||||
ToolUseStatus::Running => container.child(
|
||||
results_content_container().child(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.pb_1()
|
||||
.border_t_1()
|
||||
.border_color(self.tool_card_border_color(cx))
|
||||
.child(
|
||||
Icon::new(IconName::ArrowCircle)
|
||||
.size(IconSize::Small)
|
||||
.color(Color::Accent)
|
||||
.with_animation(
|
||||
"arrow-circle",
|
||||
Animation::new(Duration::from_secs(2)).repeat(),
|
||||
|icon, delta| {
|
||||
icon.transform(Transformation::rotate(percentage(
|
||||
delta,
|
||||
)))
|
||||
},
|
||||
),
|
||||
)
|
||||
.child(
|
||||
Label::new("Running…")
|
||||
.size(LabelSize::XSmall)
|
||||
.color(Color::Muted)
|
||||
.buffer_font(cx),
|
||||
),
|
||||
),
|
||||
),
|
||||
ToolUseStatus::Error(_) => {
|
||||
container.child(
|
||||
results_content_container()
|
||||
.border_t_1()
|
||||
.border_color(self.tool_card_border_color(cx))
|
||||
.child(
|
||||
Label::new("Error")
|
||||
.size(LabelSize::XSmall)
|
||||
.color(Color::Muted)
|
||||
.buffer_font(cx),
|
||||
)
|
||||
.child(div().text_ui_sm(cx).children(
|
||||
rendered_tool_use.as_ref().map(|rendered| {
|
||||
MarkdownElement::new(
|
||||
rendered.output.clone(),
|
||||
tool_use_markdown_style(window, cx),
|
||||
)
|
||||
}),
|
||||
)),
|
||||
)
|
||||
}
|
||||
ToolUseStatus::Pending => container,
|
||||
ToolUseStatus::NeedsConfirmation => container.child(
|
||||
results_content_container()
|
||||
.border_t_1()
|
||||
.border_color(self.tool_card_border_color(cx))
|
||||
.child(
|
||||
Label::new("Asking Permission")
|
||||
.size(LabelSize::Small)
|
||||
Label::new("Running…")
|
||||
.size(LabelSize::XSmall)
|
||||
.color(Color::Muted)
|
||||
.buffer_font(cx),
|
||||
),
|
||||
),
|
||||
});
|
||||
),
|
||||
ToolUseStatus::Error(_) => container.child(
|
||||
results_content_container()
|
||||
.border_t_1()
|
||||
.border_color(self.tool_card_border_color(cx))
|
||||
.child(
|
||||
Label::new("Error")
|
||||
.size(LabelSize::XSmall)
|
||||
.color(Color::Muted)
|
||||
.buffer_font(cx),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_ui_sm(cx)
|
||||
.children(rendered_tool_use.as_ref().map(|rendered| {
|
||||
MarkdownElement::new(
|
||||
rendered.output.clone(),
|
||||
tool_use_markdown_style(window, cx),
|
||||
)
|
||||
.on_url_click({
|
||||
let workspace = self.workspace.clone();
|
||||
move |text, window, cx| {
|
||||
open_markdown_link(text, workspace.clone(), window, cx);
|
||||
}
|
||||
})
|
||||
})),
|
||||
),
|
||||
),
|
||||
ToolUseStatus::Pending => container,
|
||||
ToolUseStatus::NeedsConfirmation => container.child(
|
||||
results_content_container()
|
||||
.border_t_1()
|
||||
.border_color(self.tool_card_border_color(cx))
|
||||
.child(
|
||||
Label::new("Asking Permission")
|
||||
.size(LabelSize::Small)
|
||||
.color(Color::Muted)
|
||||
.buffer_font(cx),
|
||||
),
|
||||
),
|
||||
});
|
||||
|
||||
let gradient_overlay = |color: Hsla| {
|
||||
div()
|
||||
|
@ -1939,7 +1941,9 @@ impl ActiveThread {
|
|||
)
|
||||
.child(
|
||||
h_flex().pr_8().text_ui_sm(cx).children(
|
||||
rendered_tool_use.map(|rendered| MarkdownElement::new(rendered.label, tool_use_markdown_style(window, cx)))
|
||||
rendered_tool_use.map(|rendered| MarkdownElement::new(rendered.label, tool_use_markdown_style(window, cx)).on_url_click({let workspace = self.workspace.clone(); move |text, window, cx| {
|
||||
open_markdown_link(text, workspace.clone(), window, cx);
|
||||
}}))
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -2027,7 +2031,9 @@ impl ActiveThread {
|
|||
)
|
||||
.child(
|
||||
h_flex().pr_8().text_ui_sm(cx).children(
|
||||
rendered_tool_use.map(|rendered| MarkdownElement::new(rendered.label, tool_use_markdown_style(window, cx)))
|
||||
rendered_tool_use.map(|rendered| MarkdownElement::new(rendered.label, tool_use_markdown_style(window, cx)).on_url_click({let workspace = self.workspace.clone(); move |text, window, cx| {
|
||||
open_markdown_link(text, workspace.clone(), window, cx);
|
||||
}}))
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -792,15 +792,11 @@ impl editor::Addon for AgentDiffAddon {
|
|||
|
||||
pub struct AgentDiffToolbar {
|
||||
agent_diff: Option<WeakEntity<AgentDiff>>,
|
||||
_workspace: WeakEntity<Workspace>,
|
||||
}
|
||||
|
||||
impl AgentDiffToolbar {
|
||||
pub fn new(workspace: &Workspace, _: &mut Context<Self>) -> Self {
|
||||
Self {
|
||||
agent_diff: None,
|
||||
_workspace: workspace.weak_handle(),
|
||||
}
|
||||
pub fn new() -> Self {
|
||||
Self { agent_diff: None }
|
||||
}
|
||||
|
||||
fn agent_diff(&self, _: &App) -> Option<Entity<AgentDiff>> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue