diff --git a/src/app.rs b/src/app.rs index fa31056..b3d1788 100644 --- a/src/app.rs +++ b/src/app.rs @@ -133,6 +133,10 @@ pub(crate) enum Message { WindowOpened(window::Id), WindowClosed(window::Id), DismissPanel, + /// Tab and shift-tab: iced leaves the key to the application, so the fields + /// of a form are only linked once we move the focus ourselves. + FocusNext, + FocusPrevious, PreferenceModelChanged(ModelChoice), PreferenceDsparkChanged(bool), PreferenceTimeoutChanged(String), @@ -447,6 +451,8 @@ impl App { self.error = None; } } + Message::FocusNext => return iced::widget::focus_next(), + Message::FocusPrevious => return iced::widget::focus_previous(), Message::ShowChat => self.detail_tab = DetailTab::Chat, Message::ShowStats => { self.detail_tab = DetailTab::Stats; @@ -1200,6 +1206,11 @@ fn shortcut(key: keyboard::Key, modifiers: keyboard::Modifiers) -> Option Some(Message::DismissPanel), + keyboard::Key::Named(keyboard::key::Named::Tab) => Some(if modifiers.shift() { + Message::FocusPrevious + } else { + Message::FocusNext + }), _ => None, } } @@ -1318,6 +1329,15 @@ mod tests { keyboard::Modifiers::COMMAND | keyboard::Modifiers::SHIFT, ); assert!(matches!(message, Some(Message::OpenModelManager))); + let tab = keyboard::Key::Named(keyboard::key::Named::Tab); + assert!(matches!( + shortcut(tab.clone(), keyboard::Modifiers::empty()), + Some(Message::FocusNext) + )); + assert!(matches!( + shortcut(tab, keyboard::Modifiers::SHIFT), + Some(Message::FocusPrevious) + )); assert!(ModelChoice::DeepSeekV4Flash.supports_dspark()); assert!(!ModelChoice::DeepSeekV4Pro.supports_dspark()); assert!(!ModelChoice::Glm52.supports_dspark());