feat(search): full-text event search from the top bar

A magnifier in each calendar screen's top bar opens a search overlay: type a
query and matching events (title, location or description) appear, nearest-to-
today first; tapping a result opens its detail.

- Data: query the Events table directly with a LIKE selection on title /
  description / location (wildcards escaped), so search is unbounded in time and
  filtered provider-side. New SearchProjection + toSearchResult mapper reuse the
  .ics export's DURATION handling for recurring masters. Hidden calendars are
  filtered out, mirroring instances().
- SearchViewModel debounces the query (250 ms), needs >= 2 chars, and orders
  results upcoming-ascending then past-descending.
- SearchScreen: autofocused inline field in the top bar, GroupedRow results
  reusing the agenda row style, idle/empty states. Hosted as a CalendarHost
  overlay below detail/edit so a tapped result's detail draws on top.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-23 10:42:37 +02:00
parent c0e27133b4
commit 82e93fda4c
15 changed files with 523 additions and 0 deletions

View File

@@ -232,6 +232,14 @@
<string name="agenda_empty_title">Nichts geplant</string>
<string name="agenda_empty_subtitle">Anstehende Termine erscheinen hier.</string>
<!-- Terminsuche -->
<string name="search_action">Suchen</string>
<string name="search_hint">Termine suchen</string>
<string name="search_back">Zurück</string>
<string name="search_clear">Löschen</string>
<string name="search_idle_hint">Durchsuche deine Termine nach Titel, Ort oder Notizen.</string>
<string name="search_empty">Keine Termine passen zu „%1$s“.</string>
<!-- Startbildschirm-Widgets -->
<string name="widget_agenda_title">Anstehend</string>
<string name="widget_agenda_label">Calendula Agenda</string>