@@ -245,6 +245,8 @@ impl RenderOnce for ThreadItem {
let removed_count = self.removed.unwrap_or(0);
let diff_stat_id = self.id.clone();
let has_worktree = self.worktree.is_some();
+ let has_timestamp = !self.timestamp.is_empty();
+ let timestamp = self.timestamp;
v_flex()
.id(self.id.clone())
@@ -253,13 +255,7 @@ impl RenderOnce for ThreadItem {
.overflow_hidden()
.cursor_pointer()
.w_full()
- .map(|this| {
- if has_worktree || has_diff_stats {
- this.p_2()
- } else {
- this.p_1()
- }
- })
+ .p_1()
.when(self.selected, |s| s.bg(color.element_active))
.border_1()
.border_color(gpui::transparent_black())
@@ -310,23 +306,47 @@ impl RenderOnce for ThreadItem {
.gap_1p5()
.child(icon_container()) // Icon Spacing
.child(worktree_label)
- .child(dot_separator())
+ .when(has_diff_stats || has_timestamp, |this| {
+ this.child(dot_separator())
+ })
.when(has_diff_stats, |this| {
this.child(DiffStat::new(
diff_stat_id.clone(),
added_count,
removed_count,
))
+ })
+ .when(has_diff_stats && has_timestamp, |this| {
+ this.child(dot_separator())
+ })
+ .when(has_timestamp, |this| {
+ this.child(
+ Label::new(timestamp.clone())
+ .size(LabelSize::Small)
+ .color(Color::Muted),
+ )
}),
)
})
- .when(!has_worktree && has_diff_stats, |this| {
+ .when(!has_worktree && (has_diff_stats || has_timestamp), |this| {
this.child(
h_flex()
.min_w_0()
.gap_1p5()
.child(icon_container()) // Icon Spacing
- .child(DiffStat::new(diff_stat_id, added_count, removed_count)),
+ .when(has_diff_stats, |this| {
+ this.child(DiffStat::new(diff_stat_id, added_count, removed_count))
+ })
+ .when(has_diff_stats && has_timestamp, |this| {
+ this.child(dot_separator())
+ })
+ .when(has_timestamp, |this| {
+ this.child(
+ Label::new(timestamp.clone())
+ .size(LabelSize::Small)
+ .color(Color::Muted),
+ )
+ }),
)
})
.when_some(self.on_click, |this, on_click| this.on_click(on_click))
@@ -349,21 +369,31 @@ impl Component for ThreadItem {
let thread_item_examples = vec![
single_example(
- "Default",
+ "Default (minutes)",
container()
.child(
ThreadItem::new("ti-1", "Linking to the Agent Panel Depending on Settings")
.icon(IconName::AiOpenAi)
- .timestamp("1:33 AM"),
+ .timestamp("15m"),
+ )
+ .into_any_element(),
+ ),
+ single_example(
+ "Timestamp Only (hours)",
+ container()
+ .child(
+ ThreadItem::new("ti-1b", "Thread with just a timestamp")
+ .icon(IconName::AiClaude)
+ .timestamp("3h"),
)
.into_any_element(),
),
single_example(
- "Notified",
+ "Notified (weeks)",
container()
.child(
ThreadItem::new("ti-2", "Refine thread view scrolling behavior")
- .timestamp("12:12 AM")
+ .timestamp("1w")
.notified(true),
)
.into_any_element(),
@@ -373,7 +403,7 @@ impl Component for ThreadItem {
container()
.child(
ThreadItem::new("ti-2b", "Execute shell command in terminal")
- .timestamp("12:15 AM")
+ .timestamp("2h")
.status(AgentThreadStatus::WaitingForConfirmation),
)
.into_any_element(),
@@ -383,7 +413,7 @@ impl Component for ThreadItem {
container()
.child(
ThreadItem::new("ti-2c", "Failed to connect to language server")
- .timestamp("12:20 AM")
+ .timestamp("5h")
.status(AgentThreadStatus::Error),
)
.into_any_element(),
@@ -394,7 +424,7 @@ impl Component for ThreadItem {
.child(
ThreadItem::new("ti-3", "Add line numbers option to FileEditBlock")
.icon(IconName::AiClaude)
- .timestamp("7:30 PM")
+ .timestamp("23h")
.status(AgentThreadStatus::Running),
)
.into_any_element(),
@@ -405,30 +435,43 @@ impl Component for ThreadItem {
.child(
ThreadItem::new("ti-4", "Add line numbers option to FileEditBlock")
.icon(IconName::AiClaude)
- .timestamp("7:37 PM")
+ .timestamp("2w")
.worktree("link-agent-panel"),
)
.into_any_element(),
),
single_example(
- "With Changes",
+ "With Changes (months)",
container()
.child(
ThreadItem::new("ti-5", "Managing user and project settings interactions")
.icon(IconName::AiClaude)
- .timestamp("7:37 PM")
+ .timestamp("1mo")
.added(10)
.removed(3),
)
.into_any_element(),
),
+ single_example(
+ "Worktree + Changes + Timestamp",
+ container()
+ .child(
+ ThreadItem::new("ti-5b", "Full metadata example")
+ .icon(IconName::AiClaude)
+ .worktree("my-project")
+ .added(42)
+ .removed(17)
+ .timestamp("3w"),
+ )
+ .into_any_element(),
+ ),
single_example(
"Selected Item",
container()
.child(
ThreadItem::new("ti-6", "Refine textarea interaction behavior")
.icon(IconName::AiGemini)
- .timestamp("3:00 PM")
+ .timestamp("45m")
.selected(true),
)
.into_any_element(),
@@ -439,23 +482,74 @@ impl Component for ThreadItem {
.child(
ThreadItem::new("ti-7", "Implement keyboard navigation")
.icon(IconName::AiClaude)
- .timestamp("4:00 PM")
+ .timestamp("12h")
.focused(true),
)
.into_any_element(),
),
+ single_example(
+ "Focused + Docked Right",
+ container()
+ .child(
+ ThreadItem::new("ti-7b", "Focused with right dock border")
+ .icon(IconName::AiClaude)
+ .timestamp("1w")
+ .focused(true)
+ .docked_right(true),
+ )
+ .into_any_element(),
+ ),
single_example(
"Selected + Focused",
container()
.child(
ThreadItem::new("ti-8", "Active and keyboard-focused thread")
.icon(IconName::AiGemini)
- .timestamp("5:00 PM")
+ .timestamp("2mo")
.selected(true)
.focused(true),
)
.into_any_element(),
),
+ single_example(
+ "Hovered with Action Slot",
+ container()
+ .child(
+ ThreadItem::new("ti-9", "Hover to see action button")
+ .icon(IconName::AiClaude)
+ .timestamp("6h")
+ .hovered(true)
+ .action_slot(
+ IconButton::new("delete", IconName::Trash)
+ .icon_size(IconSize::Small)
+ .icon_color(Color::Muted),
+ ),
+ )
+ .into_any_element(),
+ ),
+ single_example(
+ "Search Highlight",
+ container()
+ .child(
+ ThreadItem::new("ti-10", "Implement keyboard navigation")
+ .icon(IconName::AiClaude)
+ .timestamp("4w")
+ .highlight_positions(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
+ )
+ .into_any_element(),
+ ),
+ single_example(
+ "Worktree Search Highlight",
+ container()
+ .child(
+ ThreadItem::new("ti-11", "Search in worktree name")
+ .icon(IconName::AiClaude)
+ .timestamp("3mo")
+ .worktree("my-project-name")
+ .worktree_highlight_positions(vec![3, 4, 5, 6, 7, 8, 9, 10, 11]),
+ )
+ .into_any_element(),
+ ),
];
Some(