diff --git a/.gitignore b/.gitignore index ce9645a0..cfe2afda 100644 --- a/.gitignore +++ b/.gitignore @@ -90,4 +90,4 @@ apps/ .claude/codemap_* # Maintainer-internal design notes (trade-secret material, never published) -.private/ +.private/ \ No newline at end of file diff --git a/crates/tui/src/localization.rs b/crates/tui/src/localization.rs index b76d6a4b..3f78e844 100644 --- a/crates/tui/src/localization.rs +++ b/crates/tui/src/localization.rs @@ -332,6 +332,7 @@ pub enum MessageId { KbScrollTranscript, KbNavigateHistory, KbScrollTranscriptAlt, + KbBrowseHistory, KbScrollPage, KbJumpTopBottom, KbJumpTopBottomEmpty, @@ -566,6 +567,7 @@ pub const ALL_MESSAGE_IDS: &[MessageId] = &[ MessageId::KbScrollTranscript, MessageId::KbNavigateHistory, MessageId::KbScrollTranscriptAlt, + MessageId::KbBrowseHistory, MessageId::KbScrollPage, MessageId::KbJumpTopBottom, MessageId::KbJumpTopBottomEmpty, @@ -1039,6 +1041,7 @@ fn english(id: MessageId) -> &'static str { "Scroll transcript, navigate input history, or select composer attachments" } MessageId::KbNavigateHistory => "Navigate input history", + MessageId::KbBrowseHistory => "Browse conversation history", MessageId::KbScrollTranscriptAlt => "Scroll transcript", MessageId::KbScrollPage => "Scroll transcript by page", MessageId::KbJumpTopBottom => "Jump to top / bottom of transcript", @@ -1416,6 +1419,7 @@ fn japanese(id: MessageId) -> Option<&'static str> { "会話履歴をスクロール、入力履歴を移動、または添付ファイルを選択" } MessageId::KbNavigateHistory => "入力履歴を移動", + MessageId::KbBrowseHistory => "会話履歴を閲覧", MessageId::KbScrollTranscriptAlt => "会話履歴をスクロール", MessageId::KbScrollPage => "ページ単位で会話履歴をスクロール", MessageId::KbJumpTopBottom => "会話履歴の先頭/末尾へジャンプ", @@ -1742,6 +1746,7 @@ fn chinese_simplified(id: MessageId) -> Option<&'static str> { } MessageId::KbScrollTranscript => "滚动对话记录、浏览输入历史或选择附件", MessageId::KbNavigateHistory => "浏览输入历史", + MessageId::KbBrowseHistory => "浏览对话历史", MessageId::KbScrollTranscriptAlt => "滚动对话记录", MessageId::KbScrollPage => "按页滚动对话记录", MessageId::KbJumpTopBottom => "跳转到对话顶部/底部", @@ -2088,6 +2093,7 @@ fn portuguese_brazil(id: MessageId) -> Option<&'static str> { "Rolar transcrição, navegar histórico de entrada ou selecionar anexos do compositor" } MessageId::KbNavigateHistory => "Navegar histórico de entrada", + MessageId::KbBrowseHistory => "Navegar histórico da conversa", MessageId::KbScrollTranscriptAlt => "Rolar transcrição", MessageId::KbScrollPage => "Rolar transcrição por página", MessageId::KbJumpTopBottom => "Pular para topo / fim da transcrição", @@ -2366,4 +2372,4 @@ mod tests { } out } -} +} \ No newline at end of file diff --git a/crates/tui/src/tui/keybindings.rs b/crates/tui/src/tui/keybindings.rs index c58437fb..1e489edc 100644 --- a/crates/tui/src/tui/keybindings.rs +++ b/crates/tui/src/tui/keybindings.rs @@ -93,6 +93,11 @@ pub const KEYBINDINGS: &[KeybindingEntry] = &[ description_id: crate::localization::MessageId::KbScrollTranscriptAlt, section: KeybindingSection::Navigation, }, + KeybindingEntry { + chord: "Shift+↑ / Shift+↓", + description_id: crate::localization::MessageId::KbBrowseHistory, + section: KeybindingSection::Navigation, + }, KeybindingEntry { chord: "PgUp / PgDn", description_id: crate::localization::MessageId::KbScrollPage, @@ -368,4 +373,4 @@ mod tests { ranks.dedup(); assert_eq!(ranks.len(), sections.len(), "ranks must be unique"); } -} +} \ No newline at end of file diff --git a/crates/tui/src/tui/ui.rs b/crates/tui/src/tui/ui.rs index 467ee43c..2ea5cc21 100644 --- a/crates/tui/src/tui/ui.rs +++ b/crates/tui/src/tui/ui.rs @@ -2721,6 +2721,9 @@ async fn run_event_loop( KeyCode::Up if key.modifiers.contains(KeyModifiers::ALT) => { app.scroll_up(3); } + KeyCode::Up if key.modifiers.contains(KeyModifiers::SHIFT) => { + app.scroll_up(3); + } KeyCode::Up if key.modifiers.is_empty() && mention_menu_open @@ -2767,6 +2770,9 @@ async fn run_event_loop( KeyCode::Down if key.modifiers.contains(KeyModifiers::ALT) => { app.scroll_down(3); } + KeyCode::Down if key.modifiers.contains(KeyModifiers::SHIFT) => { + app.scroll_down(3); + } KeyCode::Down if key.modifiers.is_empty() && mention_menu_open => { app.mention_menu_selected = (app.mention_menu_selected + 1) .min(mention_menu_entries.len().saturating_sub(1)); @@ -9800,4 +9806,4 @@ fn extract_reasoning_header(text: &str) -> Option { } #[cfg(test)] -mod tests; +mod tests; \ No newline at end of file