1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
pub(crate) mod command_runner;
pub(crate) mod commit;
pub mod editor;
pub mod project_search;
pub(crate) mod save_state;
pub(crate) mod extension_config;
pub mod file_selector;
pub(crate) mod git_branches;
pub(crate) mod git_history;
pub(crate) mod git_history_editor;
pub(crate) mod git_pull;
pub(crate) mod issue_view;
pub(crate) mod log_view;
// legacy SearchReplace view removed — editor now hosts expanded project search
pub(crate) mod task_archive;
pub mod terminal;
use ratatui::{Frame, layout::Rect};
use crate::input;
use crate::operation::{Event, Operation};
use crate::theme::Theme;
use crate::settings::Settings;
/// Whether a view is a primary working context or a temporary overlay.
///
/// - **Primary** views (Editor, Terminal, CommitWindow, GitHistory) represent the
/// user's main working context. When opening a modal the current primary is
/// stashed so it can be restored when the modal closes.
/// - **Modal** views (FileSelector, CommandRunner, LogView, SearchReplace,
/// ExtensionConfig) are overlays. Pressing `Esc` while in a modal view returns
/// to the stashed primary view.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ViewKind {
Primary,
Modal,
}
/// Every full-screen view implements this trait.
///
/// # Responsibilities
///
/// - `handle_key` — translate raw input into operations (no mutation)
/// - `handle_mouse` — translate mouse events into operations (default no-op)
/// - `handle_operation` — apply operations the view owns; emit an event on success
/// - `render` — draw the current state to the terminal frame
///
/// Views own their slice of state. Nobody mutates a view's internals except
/// the view itself, through `handle_operation`.
pub trait View {
/// The kind of this view: [`ViewKind::Primary`] or [`ViewKind::Modal`].
///
/// Used by the escape logic to decide whether to revert to the last primary
/// view or to ignore the key press.
const KIND: ViewKind;
/// Translate a key event into zero or more operations.
/// Must not mutate `self` — use `handle_operation` for that.
fn handle_key(&self, key: input::KeyEvent) -> Vec<Operation>;
/// Translate a mouse event into zero or more operations.
/// Default implementation is a no-op; views that support mouse override this.
fn handle_mouse(&self, _mouse: input::MouseEvent) -> Vec<Operation> {
vec![]
}
/// Apply a single operation if it is relevant to this view.
///
/// Returns `Some(event)` if the operation was applied (so the event loop
/// can broadcast the resulting event to subscribers), or `None` if this
/// view does not own the operation.
fn handle_operation(&mut self, op: &Operation, settings: &Settings) -> Option<Event>;
/// Save the current state of the view before it is closed.
fn save_state(&mut self, app_state: &mut crate::app_state::AppState);
/// Draw the view into the provided `area` of the current frame.
fn render(&self, frame: &mut Frame, area: Rect, theme: &Theme);
/// Populate the global status bar with view-specific content.
///
/// The default implementation is a no-op; views that want to surface
/// information in the status bar override this.
fn status_bar(&self, _state: &crate::app_state::AppState, _bar: &mut crate::widgets::status_bar::StatusBarBuilder) {}
}