notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

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:
Mcrates/notedeck_dave/src/lib.rs | 8++++++--
Mcrates/notedeck_dave/src/ui/mod.rs | 2+-
Mcrates/notedeck_dave/src/ui/session_list.rs | 50++++++++++++++++++++++++++++++++++++--------------
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