kimun_notes/components/overlay.rs
1//! The `Overlay` trait and its supporting types — the contract every editor
2//! overlay (note browser, Saved Searches modal, or dialog) implements so the
3//! `OverlayHost` can route input / app-messages / render to it uniformly.
4
5use std::sync::Arc;
6
7use kimun_core::NoteVault;
8use ratatui::Frame;
9use ratatui::layout::Rect;
10
11use crate::components::event_state::EventState;
12use crate::components::events::{AppTx, InputEvent, OverlayData};
13use crate::components::sortable::SortableList;
14use crate::settings::themes::Theme;
15
16/// Identifies which overlay is active — used for toggle, focus label, and hints.
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum OverlayKind {
19 NoteBrowser,
20 SavedSearches,
21 CommandPalette,
22 Dialog,
23}
24
25impl OverlayKind {
26 /// Footer label for this overlay kind.
27 pub fn label(&self) -> &'static str {
28 match self {
29 OverlayKind::NoteBrowser => "NOTE BROWSER",
30 OverlayKind::SavedSearches => "SAVED SEARCHES",
31 OverlayKind::CommandPalette => "COMMANDS",
32 OverlayKind::Dialog => "DIALOG",
33 }
34 }
35}
36
37/// Outcome of routing an `AppEvent` to the active overlay. Overlays never
38/// request their own dismissal here: dialogs close by emitting the
39/// `AppEvent::CloseOverlay` event, which the editor handles separately.
40#[derive(Debug)]
41pub enum OverlayMsg {
42 /// The overlay did not recognise the message.
43 NotConsumed,
44 /// The overlay handled the message and stays open.
45 Consumed,
46}
47
48// `Send` because a screen holds `Box<dyn Overlay>` and screens are `Send` (see
49// `AppScreen` in `app_screen/mod.rs`). Every overlay already satisfied it.
50pub trait Overlay: Send {
51 fn kind(&self) -> OverlayKind;
52 fn handle_input(&mut self, event: &InputEvent, tx: &AppTx) -> EventState;
53 /// Receive an **Overlay data** result addressed to this overlay (see
54 /// CONTEXT.md). `NotConsumed` means the data was not for this overlay
55 /// (or is stale) — the host drops it; nothing else ever sees it.
56 fn handle_data(
57 &mut self,
58 _data: &OverlayData,
59 _vault: &Arc<NoteVault>,
60 _tx: &AppTx,
61 ) -> OverlayMsg {
62 OverlayMsg::NotConsumed
63 }
64 fn render(&mut self, f: &mut Frame, area: Rect, theme: &Theme);
65 fn hint_shortcuts(&self) -> Vec<(String, String)> {
66 vec![]
67 }
68 /// The query string this overlay holds, if it is query-backed (the note
69 /// browser). Used by the editor's save-current-query action to source the
70 /// query from the active overlay. Defaults to `None` for non-query overlays.
71 fn query(&self) -> Option<&str> {
72 None
73 }
74 /// The saved-search name this overlay's query came from (its breadcrumb
75 /// provenance), if any. Used to pre-fill the save-search dialog's name.
76 /// Defaults to `None` for overlays without a breadcrumb.
77 fn saved_search_provenance(&self) -> Option<&str> {
78 None
79 }
80 /// This overlay as a list the sort dialog can sort, if it is one (the
81 /// Ctrl+K search browser or the Ctrl+O file finder). Drives Ctrl+R over an open overlay. Defaults
82 /// to `None`.
83 fn as_sortable(&self) -> Option<&dyn SortableList> {
84 None
85 }
86 /// Whether this overlay's input takes the query syntax (the Ctrl+K
87 /// search browser) — F1 and its `[F1]` chip then open the syntax
88 /// reference over it. Defaults to `false`.
89 fn takes_query_syntax(&self) -> bool {
90 false
91 }
92 /// Mutable twin of [`Self::as_sortable`], for applying a sort to the
93 /// overlay parked under the sort dialog.
94 fn as_sortable_mut(&mut self) -> Option<&mut dyn SortableList> {
95 None
96 }
97}