commit bda0b4c56c6c0080b1829e86dc393c6556dffe49
parent 0f44c3f7574a751ab6dcda274c61816bdb7718b6
Author: William Casarin <jb55@jb55.com>
Date: Tue, 27 Jan 2026 08:07:05 -0800
dave: add status colors to classic view, show keybinds only with Ctrl
- Add colored status indicator bar to session list items (matching scene
view colors: gray=idle, green=working, yellow=needs input, red=error,
blue=done)
- Only show keybind numbers (1-9) when Ctrl is held, consistent with
scene view behavior
- Remove unused KeybindHint export
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat:
3 files changed, 43 insertions(+), 17 deletions(-)
diff --git a/crates/notedeck_dave/src/lib.rs b/crates/notedeck_dave/src/lib.rs
@@ -444,6 +444,7 @@ You are an AI agent for the nostr protocol called Dave, created by Damus. nostr
fn desktop_ui(&mut self, app_ctx: &mut AppContext, ui: &mut egui::Ui) -> DaveResponse {
let available = ui.available_rect_before_wrap();
let sidebar_width = 280.0;
+ let ctrl_held = ui.input(|i| i.modifiers.ctrl);
let sidebar_rect =
egui::Rect::from_min_size(available.min, egui::vec2(sidebar_width, available.height()));
@@ -464,7 +465,7 @@ You are an AI agent for the nostr protocol called Dave, created by Damus. nostr
self.show_scene = true;
}
ui.separator();
- SessionListUi::new(&self.session_manager).ui(ui)
+ SessionListUi::new(&self.session_manager, ctrl_held).ui(ui)
})
.inner
})
@@ -513,10 +514,13 @@ You are an AI agent for the nostr protocol called Dave, created by Damus. nostr
fn narrow_ui(&mut self, app_ctx: &mut AppContext, ui: &mut egui::Ui) -> DaveResponse {
if self.show_session_list {
// Show session list
+ let ctrl_held = ui.input(|i| i.modifiers.ctrl);
let session_action = egui::Frame::new()
.fill(ui.visuals().faint_bg_color)
.inner_margin(egui::Margin::symmetric(8, 12))
- .show(ui, |ui| SessionListUi::new(&self.session_manager).ui(ui))
+ .show(ui, |ui| {
+ SessionListUi::new(&self.session_manager, ctrl_held).ui(ui)
+ })
.inner;
if let Some(action) = session_action {
match action {
diff --git a/crates/notedeck_dave/src/ui/mod.rs b/crates/notedeck_dave/src/ui/mod.rs
@@ -7,7 +7,7 @@ pub mod session_list;
mod settings;
pub use dave::{DaveAction, DaveResponse, DaveUi};
-pub use keybind_hint::{keybind_hint, paint_keybind_hint, KeybindHint};
+pub use keybind_hint::{keybind_hint, paint_keybind_hint};
pub use keybindings::{check_keybindings, KeyAction};
pub use scene::{AgentScene, SceneAction, SceneResponse};
pub use session_list::{SessionListAction, SessionListUi};
diff --git a/crates/notedeck_dave/src/ui/session_list.rs b/crates/notedeck_dave/src/ui/session_list.rs
@@ -1,6 +1,7 @@
-use egui::{Align, Layout, Sense};
+use egui::{Align, Color32, Layout, Sense};
use notedeck_ui::app_images;
+use crate::agent_status::AgentStatus;
use crate::session::{SessionId, SessionManager};
/// Actions that can be triggered from the session list UI
@@ -14,11 +15,15 @@ pub enum SessionListAction {
/// UI component for displaying the session list sidebar
pub struct SessionListUi<'a> {
session_manager: &'a SessionManager,
+ ctrl_held: bool,
}
impl<'a> SessionListUi<'a> {
- pub fn new(session_manager: &'a SessionManager) -> Self {
- SessionListUi { session_manager }
+ pub fn new(session_manager: &'a SessionManager, ctrl_held: bool) -> Self {
+ SessionListUi {
+ session_manager,
+ ctrl_held,
+ }
}
pub fn ui(&self, ui: &mut egui::Ui) -> Option<SessionListAction> {
@@ -75,10 +80,20 @@ impl<'a> SessionListUi<'a> {
for (index, session) in self.session_manager.sessions_ordered().iter().enumerate() {
let is_active = Some(session.id) == active_id;
- // Show keyboard shortcut hint for first 9 sessions (1-9 keys)
- let shortcut_hint = if index < 9 { Some(index + 1) } else { None };
-
- let response = self.session_item_ui(ui, &session.title, is_active, shortcut_hint);
+ // Show keyboard shortcut hint for first 9 sessions (1-9 keys), only when Ctrl held
+ let shortcut_hint = if self.ctrl_held && index < 9 {
+ Some(index + 1)
+ } else {
+ None
+ };
+
+ let response = self.session_item_ui(
+ ui,
+ &session.title,
+ is_active,
+ shortcut_hint,
+ session.status(),
+ );
if response.clicked() {
action = Some(SessionListAction::SwitchTo(session.id));
@@ -102,12 +117,11 @@ impl<'a> SessionListUi<'a> {
title: &str,
is_active: bool,
shortcut_hint: Option<usize>,
+ status: AgentStatus,
) -> egui::Response {
let desired_size = egui::vec2(ui.available_width(), 36.0);
let (rect, response) = ui.allocate_exact_size(desired_size, Sense::click());
- let hover_text = shortcut_hint
- .map(|n| format!("Press {} to switch", n))
- .unwrap_or_default();
+ let hover_text = format!("Ctrl+{} to switch", shortcut_hint.unwrap_or(0));
let response = response
.on_hover_cursor(egui::CursorIcon::PointingHand)
.on_hover_text_at_pointer(hover_text);
@@ -118,16 +132,24 @@ impl<'a> SessionListUi<'a> {
} else if response.hovered() {
ui.visuals().widgets.hovered.weak_bg_fill
} else {
- egui::Color32::TRANSPARENT
+ Color32::TRANSPARENT
};
let corner_radius = 8.0;
ui.painter().rect_filled(rect, corner_radius, fill);
- // Draw shortcut hint on the left if available
+ // Status color indicator (left edge vertical bar)
+ let status_color = status.color();
+ let status_bar_rect = egui::Rect::from_min_size(
+ rect.left_top() + egui::vec2(2.0, 4.0),
+ egui::vec2(3.0, rect.height() - 8.0),
+ );
+ ui.painter().rect_filled(status_bar_rect, 1.5, status_color);
+
+ // Draw shortcut hint on the left if available (only when Ctrl held)
let text_start_x = if let Some(num) = shortcut_hint {
let hint_text = format!("{}", num);
- let hint_pos = rect.left_center() + egui::vec2(12.0, 0.0);
+ let hint_pos = rect.left_center() + egui::vec2(16.0, 0.0);
ui.painter().text(
hint_pos,
egui::Align2::LEFT_CENTER,
@@ -137,7 +159,7 @@ impl<'a> SessionListUi<'a> {
);
32.0
} else {
- 8.0
+ 12.0 // Leave room for status bar
};
// Draw title text