Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ab07c2343 | ||
|
|
342e732ef0 |
@@ -197,10 +197,6 @@ impl App {
|
|||||||
};
|
};
|
||||||
let key = self.clicks.promote(key, std::time::Instant::now());
|
let key = self.clicks.promote(key, std::time::Instant::now());
|
||||||
|
|
||||||
if self.handle_sidebar_mouse(&key) {
|
|
||||||
return Ok(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overlay intercept first.
|
// Overlay intercept first.
|
||||||
let (decision, effects) = self.handle_overlay_input(&key);
|
let (decision, effects) = self.handle_overlay_input(&key);
|
||||||
self.perform(effects).await;
|
self.perform(effects).await;
|
||||||
@@ -208,6 +204,10 @@ impl App {
|
|||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.handle_sidebar_mouse(&key) {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
|
||||||
let known = self.cfg.keymap.known_bindings(self.state.mode);
|
let known = self.cfg.keymap.known_bindings(self.state.mode);
|
||||||
match self.chord.feed(&key, &known) {
|
match self.chord.feed(&key, &known) {
|
||||||
ChordResult::Pending => Ok(false),
|
ChordResult::Pending => Ok(false),
|
||||||
@@ -250,6 +250,7 @@ impl App {
|
|||||||
let Some(item) = self.region.sidebar_item_at(*row) else {
|
let Some(item) = self.region.sidebar_item_at(*row) else {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
self.state.focus = Focus::Sidebar;
|
||||||
match item {
|
match item {
|
||||||
SidebarItem::Group(key) => {
|
SidebarItem::Group(key) => {
|
||||||
self.state.sidebar_highlight = Some(SidebarItem::Group(key.clone()));
|
self.state.sidebar_highlight = Some(SidebarItem::Group(key.clone()));
|
||||||
@@ -257,7 +258,6 @@ impl App {
|
|||||||
}
|
}
|
||||||
SidebarItem::Session(id) => {
|
SidebarItem::Session(id) => {
|
||||||
self.state.sidebar_highlight = Some(SidebarItem::Session(id));
|
self.state.sidebar_highlight = Some(SidebarItem::Session(id));
|
||||||
self.state.focus = Focus::Sidebar;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
@@ -1296,6 +1296,7 @@ mod tests {
|
|||||||
.state
|
.state
|
||||||
.collapsed_sidebar_groups
|
.collapsed_sidebar_groups
|
||||||
.contains(&PathBuf::from("/")));
|
.contains(&PathBuf::from("/")));
|
||||||
|
assert_eq!(app.state.focus, Focus::Sidebar);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1319,6 +1320,35 @@ mod tests {
|
|||||||
.state
|
.state
|
||||||
.collapsed_sidebar_groups
|
.collapsed_sidebar_groups
|
||||||
.contains(&PathBuf::from("/")));
|
.contains(&PathBuf::from("/")));
|
||||||
|
assert_eq!(app.state.focus, Focus::Sidebar);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn sidebar_click_dismisses_a_toast_before_handling_the_click() {
|
||||||
|
use crossterm::event::{MouseButton, MouseEvent, MouseEventKind};
|
||||||
|
|
||||||
|
let sid = Uuid::from_u128(17);
|
||||||
|
let mut app = app_with_highlighted_session(sid);
|
||||||
|
app.state.toast("notice");
|
||||||
|
app.region.sidebar = Some(ratatui::layout::Rect::new(0, 0, 28, 10));
|
||||||
|
app.region.sidebar_items = vec![SidebarItem::Group(PathBuf::from("/"))];
|
||||||
|
|
||||||
|
let quit = app
|
||||||
|
.handle_event(CtEvent::Mouse(MouseEvent {
|
||||||
|
kind: MouseEventKind::Down(MouseButton::Left),
|
||||||
|
column: 3,
|
||||||
|
row: 2,
|
||||||
|
modifiers: crossterm::event::KeyModifiers::NONE,
|
||||||
|
}))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert!(!quit);
|
||||||
|
assert!(app.state.overlay().is_none());
|
||||||
|
assert!(app
|
||||||
|
.state
|
||||||
|
.collapsed_sidebar_groups
|
||||||
|
.contains(&PathBuf::from("/")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -180,21 +180,27 @@ impl Sidebar {
|
|||||||
let path = abbreviate_dir(&group.key, home);
|
let path = abbreviate_dir(&group.key, home);
|
||||||
let name = abbreviate_folder_name(&path);
|
let name = abbreviate_folder_name(&path);
|
||||||
let count = format!(" ({})", group.sessions.len());
|
let count = format!(" ({})", group.sessions.len());
|
||||||
let mut spans = vec![Span::styled(
|
let prefix = Span::styled(
|
||||||
prefix,
|
prefix,
|
||||||
if edge {
|
if edge {
|
||||||
base.fg(palette.focus_accent)
|
base.fg(palette.focus_accent)
|
||||||
} else {
|
} else {
|
||||||
base
|
base
|
||||||
},
|
},
|
||||||
)];
|
);
|
||||||
spans.push(Span::styled(chevron, base));
|
let chevron = Span::styled(chevron, base);
|
||||||
|
let count = Span::styled(count, surface.muted_style());
|
||||||
|
let label_budget = width.saturating_sub(prefix.width() + chevron.width() + count.width());
|
||||||
|
let mut label = Vec::new();
|
||||||
if let Some(stem) = name.stem {
|
if let Some(stem) = name.stem {
|
||||||
spans.push(Span::styled(format!("{stem}/"), surface.dim_style()));
|
label.push(Span::styled(format!("{stem}/"), surface.dim_style()));
|
||||||
}
|
}
|
||||||
spans.push(Span::styled(name.last, base));
|
label.push(Span::styled(name.last, base));
|
||||||
spans.push(Span::styled(count, surface.muted_style()));
|
|
||||||
pad_to_width(fit_to_width(spans, width), width, base)
|
let mut spans = vec![prefix, chevron];
|
||||||
|
spans.extend(fit_to_width(label, label_budget));
|
||||||
|
spans.push(count);
|
||||||
|
pad_to_width(spans, width, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name_row(&self, s: &Session, width: usize, focused: bool) -> Vec<Span<'static>> {
|
fn name_row(&self, s: &Session, width: usize, focused: bool) -> Vec<Span<'static>> {
|
||||||
@@ -541,6 +547,26 @@ mod tests {
|
|||||||
assert!(!rendered.contains("claude"));
|
assert!(!rendered.contains("claude"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn long_group_labels_yield_to_the_always_visible_count() {
|
||||||
|
let mut session = session_named(1, "claude");
|
||||||
|
session.cwd = "/very/long/project/path/extraordinarily-long-project-name".into();
|
||||||
|
let sidebar = Sidebar {
|
||||||
|
sessions: vec![session],
|
||||||
|
highlight: None,
|
||||||
|
attached: Default::default(),
|
||||||
|
};
|
||||||
|
let key = PathBuf::from("/very/long/project/path/extraordinarily-long-project-name");
|
||||||
|
let collapsed = HashSet::from([key]);
|
||||||
|
let rendered = render_to_string(&draw_collapsed(&sidebar, 28, 6, &collapsed));
|
||||||
|
|
||||||
|
assert!(rendered.contains('…'));
|
||||||
|
assert!(
|
||||||
|
rendered.contains("(1)"),
|
||||||
|
"group count was truncated: {rendered:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn shared_display_helpers_abbreviate_group_labels() {
|
fn shared_display_helpers_abbreviate_group_labels() {
|
||||||
let path = maestro_protocol::display::abbreviate_dir(
|
let path = maestro_protocol::display::abbreviate_dir(
|
||||||
|
|||||||
Reference in New Issue
Block a user