Add search autocomplete and fix search state restoration

- Add SuggestFromList with Himalaya keywords for search input autocomplete
- Cache and restore metadata_by_id when cancelling search (fixes navigation)
- Set search_mode=True when opening panel for consistent Escape behavior
- Fix SearchPanel CSS vertical alignment with explicit heights
This commit is contained in:
Bendt
2025-12-19 15:33:42 -05:00
parent 5deebbbf98
commit 9a2f8ee211
2 changed files with 38 additions and 3 deletions

View File

@@ -77,6 +77,7 @@ class EmailViewerApp(App):
search_query: Reactive[str] = reactive("") # Current search filter
search_mode: Reactive[bool] = reactive(False) # True when showing search results
_cached_envelopes: List[Dict[str, Any]] = [] # Cached envelopes before search
_cached_metadata: Dict[int, Dict[str, Any]] = {} # Cached metadata before search
def get_system_commands(self, screen: Screen) -> Iterable[SystemCommand]:
yield from super().get_system_commands(screen)
@@ -917,6 +918,8 @@ class EmailViewerApp(App):
if not search_panel.is_visible:
# Cache current envelopes before searching
self._cached_envelopes = list(self.message_store.envelopes)
self._cached_metadata = dict(self.message_store.metadata_by_id)
self.search_mode = True
search_panel.show(self.search_query)
def on_search_panel_search_requested(
@@ -938,11 +941,14 @@ class EmailViewerApp(App):
self.search_mode = False
self.search_query = ""
# Restore cached envelopes
# Restore cached envelopes and metadata
if self._cached_envelopes:
self.message_store.envelopes = self._cached_envelopes
self._cached_envelopes = []
self._populate_list_view()
if self._cached_metadata:
self.message_store.metadata_by_id = self._cached_metadata
self._cached_metadata = {}
self._populate_list_view()
# Restore envelope list title
sort_indicator = "" if self.sort_order_ascending else ""

View File

@@ -17,6 +17,32 @@ from textual.screen import ModalScreen
from textual.timer import Timer
from textual.widget import Widget
from textual.widgets import Button, Input, Label, Static
from textual.suggester import SuggestFromList
# Himalaya search keywords for autocomplete
HIMALAYA_KEYWORDS = [
"from ",
"to ",
"subject ",
"body ",
"date ",
"before ",
"after ",
"flag ",
"not ",
"and ",
"or ",
"order by ",
"order by date ",
"order by date asc",
"order by date desc",
"order by from ",
"order by to ",
"order by subject ",
"flag seen",
"flag flagged",
"not flag seen",
]
HIMALAYA_SEARCH_HELP = """
## Himalaya Search Query Syntax
@@ -125,7 +151,7 @@ class SearchPanel(Widget):
}
SearchPanel > Horizontal {
height: auto;
height: 3;
width: 100%;
align: left middle;
}
@@ -134,6 +160,7 @@ class SearchPanel(Widget):
width: auto;
padding: 0 1;
color: $primary;
height: 1;
}
SearchPanel Input {
@@ -151,6 +178,7 @@ class SearchPanel(Widget):
width: auto;
padding: 0 1;
color: $text-muted;
height: 1;
}
"""
@@ -197,6 +225,7 @@ class SearchPanel(Widget):
yield Input(
placeholder="from <name> or subject <text> or body <text>...",
id="search-input",
suggester=SuggestFromList(HIMALAYA_KEYWORDS, case_sensitive=False),
)
yield Label("", classes="search-status", id="search-status")
yield Button("?", variant="default", id="help-btn")