diff --git a/tui/folder_inbox.go b/tui/folder_inbox.go index 9b3a7e7d339150b358d8b52bb1c24bc86c9ef0c5..7e0aa99c69fb46b1a565715ac3c5b9542499a5ad 100644 --- a/tui/folder_inbox.go +++ b/tui/folder_inbox.go @@ -172,6 +172,12 @@ func (m *FolderInbox) Update(msg tea.Msg) (tea.Model, tea.Cmd) { break } + // Don't intercept keys while the inbox search overlay is active. + // Otherwise folder-level bindings like "m" (move) would shadow text input. + if m.inbox.searchOverlay != nil { + break + } + kb := config.Keybinds // Route input to preview pane when focused diff --git a/tui/folder_inbox_test.go b/tui/folder_inbox_test.go index dc17a7fb6216b9ae818dc665326b8acf4c56feb3..25e88ae32a1a38c5ed3c2a0802f29ca19bbf4509 100644 --- a/tui/folder_inbox_test.go +++ b/tui/folder_inbox_test.go @@ -86,3 +86,39 @@ func TestFolderInboxSplitPreviewPrefersAllEmails(t *testing.T) { t.Fatalf("expected the live allEmails entry, got %+v", got) } } + +// TestSearchOverlayKeysNotIntercepted covers issue #1199: pressing keys that +// match folder-level bindings (e.g. "m" for move) while the search overlay is +// active used to trigger the move flow instead of entering text into the +// search input. FolderInbox.Update now passes through to the inner inbox +// while m.inbox.searchOverlay != nil so the overlay receives raw keystrokes. +func TestSearchOverlayKeysNotIntercepted(t *testing.T) { + accounts := []config.Account{ + {ID: "account-1", Email: "host.example.com", FetchEmail: "first@example.com"}, + } + fi := NewFolderInbox([]string{"INBOX", "Archive"}, accounts) + model, _ := fi.Update(tea.WindowSizeMsg{Width: 200, Height: 60}) + fi = model.(*FolderInbox) + + // Selection must exist so the bug's "m" -> Move handler would actually fire. + fi.SetEmails([]fetcher.Email{ + {UID: 1, AccountID: "account-1", Subject: "first"}, + }, accounts) + + // Open the search overlay (the same state pressing "/" produces in inbox.go). + fi.inbox.searchOverlay = NewSearchOverlay(fi.width, fi.height) + + // Press "m" -- with the bug this would set movingEmail = true. + model, _ = fi.Update(tea.KeyPressMsg{Code: 'm', Text: "m"}) + fi = model.(*FolderInbox) + + if fi.movingEmail { + t.Fatal("pressing 'm' while search overlay is active must not start the move flow") + } + if fi.inbox.searchOverlay == nil { + t.Fatal("search overlay must remain open after typing into it") + } + if got := fi.inbox.searchOverlay.input.Value(); got != "m" { + t.Fatalf("search input should contain typed character, got %q", got) + } +}