@@ -6,6 +6,7 @@ mod chip;
|
||||
mod content_group;
|
||||
mod context_menu;
|
||||
mod data_table;
|
||||
mod diff_stat;
|
||||
mod disclosure;
|
||||
mod divider;
|
||||
mod dropdown_menu;
|
||||
@@ -50,6 +51,7 @@ pub use chip::*;
|
||||
pub use content_group::*;
|
||||
pub use context_menu::*;
|
||||
pub use data_table::*;
|
||||
pub use diff_stat::*;
|
||||
pub use disclosure::*;
|
||||
pub use divider::*;
|
||||
pub use dropdown_menu::*;
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(IntoElement, RegisterComponent)]
|
||||
pub struct DiffStat {
|
||||
id: ElementId,
|
||||
added: usize,
|
||||
removed: usize,
|
||||
}
|
||||
|
||||
impl DiffStat {
|
||||
pub fn new(id: impl Into<ElementId>, added: usize, removed: usize) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
added,
|
||||
removed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for DiffStat {
|
||||
fn render(self, _: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||
h_flex()
|
||||
.id(self.id)
|
||||
.gap_1()
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_0p5()
|
||||
.child(
|
||||
Icon::new(IconName::Plus)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Success),
|
||||
)
|
||||
.child(
|
||||
Label::new(self.added.to_string())
|
||||
.color(Color::Success)
|
||||
.size(LabelSize::Small),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_0p5()
|
||||
.child(
|
||||
Icon::new(IconName::Dash)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Error),
|
||||
)
|
||||
.child(
|
||||
Label::new(self.removed.to_string())
|
||||
.color(Color::Error)
|
||||
.size(LabelSize::Small),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for DiffStat {
|
||||
fn scope() -> ComponentScope {
|
||||
ComponentScope::VersionControl
|
||||
}
|
||||
|
||||
fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
|
||||
let container = || {
|
||||
h_flex()
|
||||
.py_4()
|
||||
.w_72()
|
||||
.justify_center()
|
||||
.border_1()
|
||||
.border_color(cx.theme().colors().border_variant)
|
||||
.bg(cx.theme().colors().panel_background)
|
||||
};
|
||||
|
||||
let diff_stat_example = vec![single_example(
|
||||
"Default",
|
||||
container()
|
||||
.child(DiffStat::new("id", 1, 2))
|
||||
.into_any_element(),
|
||||
)];
|
||||
|
||||
Some(
|
||||
example_group(diff_stat_example)
|
||||
.vertical()
|
||||
.into_any_element(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{Chip, Indicator, SpinnerLabel, prelude::*};
|
||||
use crate::{Chip, DiffStat, Indicator, SpinnerLabel, prelude::*};
|
||||
use gpui::{ClickEvent, SharedString};
|
||||
|
||||
#[derive(IntoElement, RegisterComponent)]
|
||||
@@ -10,7 +10,8 @@ pub struct ThreadItem {
|
||||
running: bool,
|
||||
generation_done: bool,
|
||||
selected: bool,
|
||||
has_changes: bool,
|
||||
added: Option<usize>,
|
||||
removed: Option<usize>,
|
||||
worktree: Option<SharedString>,
|
||||
on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||
}
|
||||
@@ -25,7 +26,8 @@ impl ThreadItem {
|
||||
running: false,
|
||||
generation_done: false,
|
||||
selected: false,
|
||||
has_changes: false,
|
||||
added: None,
|
||||
removed: None,
|
||||
worktree: None,
|
||||
on_click: None,
|
||||
}
|
||||
@@ -56,8 +58,13 @@ impl ThreadItem {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn has_changes(mut self, has_changes: bool) -> Self {
|
||||
self.has_changes = has_changes;
|
||||
pub fn added(mut self, added: usize) -> Self {
|
||||
self.added = Some(added);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn removed(mut self, removed: usize) -> Self {
|
||||
self.removed = Some(removed);
|
||||
self
|
||||
}
|
||||
|
||||
@@ -90,8 +97,10 @@ impl RenderOnce for ThreadItem {
|
||||
)
|
||||
};
|
||||
|
||||
let has_no_changes = self.added.is_none() && self.removed.is_none();
|
||||
|
||||
v_flex()
|
||||
.id(self.id)
|
||||
.id(self.id.clone())
|
||||
.cursor_pointer()
|
||||
.p_2()
|
||||
.when(self.selected, |this| {
|
||||
@@ -123,12 +132,19 @@ impl RenderOnce for ThreadItem {
|
||||
.color(Color::Muted)
|
||||
.alpha(0.5),
|
||||
)
|
||||
.when(!self.has_changes, |this| {
|
||||
.when(has_no_changes, |this| {
|
||||
this.child(
|
||||
Label::new("No Changes")
|
||||
.size(LabelSize::Small)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
})
|
||||
.when(self.added.is_some() || self.removed.is_some(), |this| {
|
||||
this.child(DiffStat::new(
|
||||
self.id,
|
||||
self.added.unwrap_or(0),
|
||||
self.removed.unwrap_or(0),
|
||||
))
|
||||
}),
|
||||
)
|
||||
.when_some(self.on_click, |this, on_click| this.on_click(on_click))
|
||||
@@ -192,11 +208,23 @@ impl Component for ThreadItem {
|
||||
)
|
||||
.into_any_element(),
|
||||
),
|
||||
single_example(
|
||||
"With Changes",
|
||||
container()
|
||||
.child(
|
||||
ThreadItem::new("ti-5", "Managing user and project settings interactions")
|
||||
.icon(IconName::AiClaude)
|
||||
.timestamp("7:37 PM")
|
||||
.added(10)
|
||||
.removed(3),
|
||||
)
|
||||
.into_any_element(),
|
||||
),
|
||||
single_example(
|
||||
"Selected Item",
|
||||
container()
|
||||
.child(
|
||||
ThreadItem::new("ti-5", "Refine textarea interaction behavior")
|
||||
ThreadItem::new("ti-6", "Refine textarea interaction behavior")
|
||||
.icon(IconName::AiGemini)
|
||||
.timestamp("3:00 PM")
|
||||
.selected(true),
|
||||
|
||||
Reference in New Issue
Block a user