Fix search stability and improve Escape key behavior
- Add bounds check in _mark_message_as_read to prevent IndexError - Clear metadata_by_id when search returns no results - Escape now focuses search input when in search mode instead of exiting - Add focus_input() method to SearchPanel
This commit is contained in:
@@ -273,6 +273,12 @@ class EmailViewerApp(App):
|
||||
|
||||
async def _mark_message_as_read(self, message_id: int, index: int) -> None:
|
||||
"""Mark a message as read and update the UI."""
|
||||
# Skip if message_id is invalid or index is out of bounds
|
||||
if message_id <= 0:
|
||||
return
|
||||
if index < 0 or index >= len(self.message_store.envelopes):
|
||||
return
|
||||
|
||||
# Check if already read
|
||||
envelope_data = self.message_store.envelopes[index]
|
||||
if envelope_data and envelope_data.get("type") != "header":
|
||||
@@ -885,32 +891,18 @@ class EmailViewerApp(App):
|
||||
self._update_list_view_subtitle()
|
||||
|
||||
def action_clear_selection(self) -> None:
|
||||
"""Clear all selected messages and exit search mode."""
|
||||
"""Clear all selected messages or focus search input if in search mode."""
|
||||
# If in search mode, focus the search input instead of exiting
|
||||
if self.search_mode:
|
||||
search_panel = self.query_one("#search_panel", SearchPanel)
|
||||
search_panel.focus_input()
|
||||
return
|
||||
|
||||
if self.selected_messages:
|
||||
self.selected_messages.clear()
|
||||
self.refresh_list_view_items() # Refresh all items to uncheck checkboxes
|
||||
self._update_list_view_subtitle()
|
||||
|
||||
# Exit search mode if active
|
||||
if self.search_mode:
|
||||
search_panel = self.query_one("#search_panel", SearchPanel)
|
||||
search_panel.hide()
|
||||
self.search_mode = False
|
||||
self.search_query = ""
|
||||
|
||||
# Restore cached envelopes
|
||||
if self._cached_envelopes:
|
||||
self.message_store.envelopes = self._cached_envelopes
|
||||
self._cached_envelopes = []
|
||||
self._populate_list_view()
|
||||
|
||||
# Restore envelope list title
|
||||
sort_indicator = "↑" if self.sort_order_ascending else "↓"
|
||||
self.query_one(
|
||||
"#envelopes_list"
|
||||
).border_title = f"1️⃣ Emails {sort_indicator}"
|
||||
self._update_list_view_subtitle()
|
||||
|
||||
def action_oldest(self) -> None:
|
||||
self.fetch_envelopes() if self.reload_needed else None
|
||||
self.show_message(self.message_store.get_oldest_id())
|
||||
@@ -1017,6 +1009,7 @@ class EmailViewerApp(App):
|
||||
content_container = self.query_one(ContentContainer)
|
||||
content_container.clear_content()
|
||||
self.message_store.envelopes = []
|
||||
self.message_store.metadata_by_id = {}
|
||||
self.total_messages = 0
|
||||
self.current_message_id = 0
|
||||
return
|
||||
|
||||
@@ -216,6 +216,11 @@ class SearchPanel(Widget):
|
||||
self._cancel_debounce()
|
||||
self.result_count = -1
|
||||
|
||||
def focus_input(self) -> None:
|
||||
"""Focus the search input field."""
|
||||
input_widget = self.query_one("#search-input", Input)
|
||||
input_widget.focus()
|
||||
|
||||
@property
|
||||
def is_visible(self) -> bool:
|
||||
"""Check if the panel is visible."""
|
||||
|
||||
Reference in New Issue
Block a user