diff --git a/src/tui.zig b/src/tui.zig index c9edafd..72e59f1 100644 --- a/src/tui.zig +++ b/src/tui.zig @@ -1243,26 +1243,6 @@ pub const App = struct { return ctx.consumeAndRedraw(); } - // Escape: portfolio tab clears its account filter inline. - // Other tabs fall through to the global keymap (no global - // Esc binding) and then to the tab-local fallback dispatcher - // (e.g. history binds Esc to `compare_cancel`, projections - // binds Esc to `clear_as_of`). When portfolio migrates, its - // Esc handling moves into a tab-local action too. - if (key.codepoint == vaxis.Key.escape) { - if (self.active_tab == .portfolio and self.states.portfolio.account_filter != null) { - self.setAccountFilter(null); - self.states.portfolio.cursor = 0; - self.scroll_offset = 0; - tab_modules.portfolio.rebuildPortfolioRows(&self.states.portfolio, self); - self.setStatus("Filter cleared: showing all accounts"); - return ctx.consumeAndRedraw(); - } - // Fall through — no tab-specific handler. Esc isn't - // globally bound, so matchAction returns null and the - // tab-local fallback gets a chance. - } - const action = self.keymap.matchAction(key) orelse { // No global binding matched. Fall back to tab-local // dispatch — the active tab may bind this key in its @@ -1371,24 +1351,6 @@ pub const App = struct { self.reloadPortfolioFile(); return ctx.consumeAndRedraw(); }, - .sort_col_next => { - if (self.active_tab == .portfolio) { - tab_modules.portfolio.tab.handleAction(&self.states.portfolio, self, tab_modules.portfolio.Action.sort_col_next); - return ctx.consumeAndRedraw(); - } - }, - .sort_col_prev => { - if (self.active_tab == .portfolio) { - tab_modules.portfolio.tab.handleAction(&self.states.portfolio, self, tab_modules.portfolio.Action.sort_col_prev); - return ctx.consumeAndRedraw(); - } - }, - .account_filter => { - if (self.active_tab == .portfolio) { - tab_modules.portfolio.tab.handleAction(&self.states.portfolio, self, tab_modules.portfolio.Action.open_account_picker); - return ctx.consumeAndRedraw(); - } - }, } } diff --git a/src/tui/keybinds.zig b/src/tui/keybinds.zig index 8c5a6f3..ee0c8ec 100644 --- a/src/tui/keybinds.zig +++ b/src/tui/keybinds.zig @@ -27,9 +27,6 @@ pub const Action = enum { symbol_input, help, reload_portfolio, - sort_col_next, - sort_col_prev, - account_filter, }; pub const KeyCombo = struct { @@ -147,9 +144,6 @@ pub const global_default_bindings = [_]Binding{ .{ .action = .symbol_input, .key = .{ .codepoint = '/' } }, .{ .action = .help, .key = .{ .codepoint = '?' } }, .{ .action = .reload_portfolio, .key = .{ .codepoint = 'R' } }, - .{ .action = .sort_col_next, .key = .{ .codepoint = '>' } }, - .{ .action = .sort_col_prev, .key = .{ .codepoint = '<' } }, - .{ .action = .account_filter, .key = .{ .codepoint = 'a' } }, }; pub fn defaults() KeyMap { diff --git a/src/tui/portfolio_tab.zig b/src/tui/portfolio_tab.zig index 75d23b4..58b4768 100644 --- a/src/tui/portfolio_tab.zig +++ b/src/tui/portfolio_tab.zig @@ -48,6 +48,9 @@ pub const Action = enum { /// Open the account picker modal (mode = .account_picker). /// No-op if no portfolio is loaded. open_account_picker, + /// Clear the active account filter (return to "all accounts"). + /// No-op when no filter is active. Bound to Esc. + clear_account_filter, /// Select the cursor row's symbol as the currently-active /// symbol for the per-symbol tabs (quote/perf/options/etc.). select_symbol, @@ -127,14 +130,12 @@ pub const tab = struct { pub const label: []const u8 = "Portfolio"; pub const default_bindings: []const framework.TabBinding(Action) = &.{ - // These are dead until scoped keymaps land — the global - // keymap matches first. Declared per-tab so the help - // overlay and future scoped-dispatch can find them. .{ .action = .expand_collapse, .key = .{ .codepoint = vaxis.Key.enter } }, - .{ .action = .sort_col_next, .key = .{ .codepoint = 'S' } }, - .{ .action = .sort_col_prev, .key = .{ .codepoint = ';' } }, + .{ .action = .sort_col_next, .key = .{ .codepoint = '>' } }, + .{ .action = .sort_col_prev, .key = .{ .codepoint = '<' } }, .{ .action = .sort_reverse, .key = .{ .codepoint = 'o' } }, .{ .action = .open_account_picker, .key = .{ .codepoint = 'a' } }, + .{ .action = .clear_account_filter, .key = .{ .codepoint = vaxis.Key.escape } }, .{ .action = .select_symbol, .key = .{ .codepoint = 's' } }, .{ .action = .select_symbol, .key = .{ .codepoint = vaxis.Key.space } }, }; @@ -145,6 +146,7 @@ pub const tab = struct { .sort_col_prev = "Sort: previous column", .sort_reverse = "Sort: reverse direction", .open_account_picker = "Filter by account", + .clear_account_filter = "Clear account filter", .select_symbol = "Select symbol", }); @@ -222,6 +224,15 @@ pub const tab = struct { } } }, + .clear_account_filter => { + // No-op when no filter is active. + if (state.account_filter == null) return; + app.setAccountFilter(null); + state.cursor = 0; + app.scroll_offset = 0; + rebuildPortfolioRows(state, app); + app.setStatus("Filter cleared: showing all accounts"); + }, .select_symbol => { if (state.rows.items.len == 0) return; if (state.cursor >= state.rows.items.len) return;