This removes around 900 unnecessary clones, ranging from cloning a few ints all the way to large data structures and images. A lot of these were fixed using `cargo clippy --fix --workspace --all-targets`, however it often breaks other lints and needs to be run again. This was then followed up with some manual fixing. I understand this is a large diff, but all the changes are pretty trivial. Rust is doing some heavy lifting here for us. Once I get it up to speed with main, I'd appreciate this getting merged rather sooner than later. Release Notes: - N/A
132 lines
4.5 KiB
Rust
132 lines
4.5 KiB
Rust
use gpui::{Animation, AnimationExt, AnyElement, App, IntoElement, pulsating_between};
|
|
use std::time::Duration;
|
|
use ui::{Tooltip, prelude::*};
|
|
|
|
/// A reusable header component for tool call cards.
|
|
#[derive(IntoElement)]
|
|
pub struct ToolCallCardHeader {
|
|
icon: IconName,
|
|
primary_text: SharedString,
|
|
secondary_text: Option<SharedString>,
|
|
code_path: Option<SharedString>,
|
|
disclosure_slot: Option<AnyElement>,
|
|
is_loading: bool,
|
|
error: Option<String>,
|
|
}
|
|
|
|
impl ToolCallCardHeader {
|
|
pub fn new(icon: IconName, primary_text: impl Into<SharedString>) -> Self {
|
|
Self {
|
|
icon,
|
|
primary_text: primary_text.into(),
|
|
secondary_text: None,
|
|
code_path: None,
|
|
disclosure_slot: None,
|
|
is_loading: false,
|
|
error: None,
|
|
}
|
|
}
|
|
|
|
pub fn with_secondary_text(mut self, text: impl Into<SharedString>) -> Self {
|
|
self.secondary_text = Some(text.into());
|
|
self
|
|
}
|
|
|
|
pub fn with_code_path(mut self, text: impl Into<SharedString>) -> Self {
|
|
self.code_path = Some(text.into());
|
|
self
|
|
}
|
|
|
|
pub fn disclosure_slot(mut self, element: impl IntoElement) -> Self {
|
|
self.disclosure_slot = Some(element.into_any_element());
|
|
self
|
|
}
|
|
|
|
pub fn loading(mut self) -> Self {
|
|
self.is_loading = true;
|
|
self
|
|
}
|
|
|
|
pub fn with_error(mut self, error: impl Into<String>) -> Self {
|
|
self.error = Some(error.into());
|
|
self
|
|
}
|
|
}
|
|
|
|
impl RenderOnce for ToolCallCardHeader {
|
|
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
|
let font_size = rems(0.8125);
|
|
let line_height = window.line_height();
|
|
|
|
let secondary_text = self.secondary_text;
|
|
let code_path = self.code_path;
|
|
|
|
let bullet_divider = || {
|
|
div()
|
|
.size(px(3.))
|
|
.rounded_full()
|
|
.bg(cx.theme().colors().text)
|
|
};
|
|
|
|
h_flex()
|
|
.id("tool-label-container")
|
|
.gap_2()
|
|
.max_w_full()
|
|
.overflow_x_scroll()
|
|
.opacity(0.8)
|
|
.child(
|
|
h_flex()
|
|
.h(line_height)
|
|
.gap_1p5()
|
|
.text_size(font_size)
|
|
.child(
|
|
h_flex().h(line_height).justify_center().child(
|
|
Icon::new(self.icon)
|
|
.size(IconSize::Small)
|
|
.color(Color::Muted),
|
|
),
|
|
)
|
|
.map(|this| {
|
|
if let Some(error) = &self.error {
|
|
this.child(format!("{} failed", self.primary_text)).child(
|
|
IconButton::new("error_info", IconName::Warning)
|
|
.shape(ui::IconButtonShape::Square)
|
|
.icon_size(IconSize::XSmall)
|
|
.icon_color(Color::Warning)
|
|
.tooltip(Tooltip::text(error.clone())),
|
|
)
|
|
} else {
|
|
this.child(self.primary_text.clone())
|
|
}
|
|
})
|
|
.when_some(secondary_text, |this, secondary_text| {
|
|
this.child(bullet_divider())
|
|
.child(div().text_size(font_size).child(secondary_text))
|
|
})
|
|
.when_some(code_path, |this, code_path| {
|
|
this.child(bullet_divider())
|
|
.child(Label::new(code_path).size(LabelSize::Small).inline_code(cx))
|
|
})
|
|
.with_animation(
|
|
"loading-label",
|
|
Animation::new(Duration::from_secs(2))
|
|
.repeat()
|
|
.with_easing(pulsating_between(0.6, 1.)),
|
|
move |this, delta| {
|
|
if self.is_loading {
|
|
this.opacity(delta)
|
|
} else {
|
|
this
|
|
}
|
|
},
|
|
),
|
|
)
|
|
.when_some(self.disclosure_slot, |container, disclosure_slot| {
|
|
container
|
|
.group("disclosure")
|
|
.justify_between()
|
|
.child(div().visible_on_hover("disclosure").child(disclosure_slot))
|
|
})
|
|
}
|
|
}
|