1use ratatui::crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum Action {
8 Continue,
10 Quit,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum Pane {
17 Ready,
19 List,
21 Claims,
23 Agenda,
25 Search,
27}
28
29impl Pane {
30 pub const ALL: [Pane; 5] = [
32 Pane::Ready,
33 Pane::List,
34 Pane::Claims,
35 Pane::Agenda,
36 Pane::Search,
37 ];
38
39 pub fn title(self) -> &'static str {
41 match self {
42 Self::Ready => "Ready",
43 Self::List => "List",
44 Self::Claims => "Claims",
45 Self::Agenda => "Agenda",
46 Self::Search => "Search",
47 }
48 }
49
50 pub fn index(self) -> usize {
52 Self::ALL.iter().position(|p| *p == self).unwrap_or(0)
53 }
54
55 pub fn from_index(i: usize) -> Self {
57 Self::ALL[i % Self::ALL.len()]
58 }
59
60 pub fn next(self) -> Self {
62 Self::from_index(self.index() + 1)
63 }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum DetailTab {
69 Show,
71 Excerpt,
73 Tree,
75 Related,
77}
78
79impl DetailTab {
80 pub const ALL: [DetailTab; 4] = [
82 DetailTab::Show,
83 DetailTab::Excerpt,
84 DetailTab::Tree,
85 DetailTab::Related,
86 ];
87
88 pub fn title(self) -> &'static str {
90 match self {
91 Self::Show => "show",
92 Self::Excerpt => "excerpt",
93 Self::Tree => "tree",
94 Self::Related => "related",
95 }
96 }
97
98 pub fn next(self) -> Self {
100 let i = Self::ALL.iter().position(|t| *t == self).unwrap_or(0);
101 Self::ALL[(i + 1) % Self::ALL.len()]
102 }
103}
104
105#[derive(Debug, Clone, Copy, PartialEq, Eq)]
107pub enum Focus {
108 Rows,
110 Detail,
112}
113
114#[derive(Debug, Clone, Copy, PartialEq, Eq)]
116pub enum PromptKind {
117 Search,
119 Note,
121 Project,
123}
124
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
127pub enum ConfirmKind {
128 Done,
130 Cancelled,
132}
133
134impl ConfirmKind {
135 pub fn state(self) -> &'static str {
137 match self {
138 Self::Done => "DONE",
139 Self::Cancelled => "CANCELLED",
140 }
141 }
142}
143
144pub fn is_press(key: KeyEvent) -> bool {
146 key.kind == KeyEventKind::Press || key.kind == KeyEventKind::Repeat
147}
148
149pub fn char_of(key: KeyEvent) -> Option<char> {
151 match key.code {
152 KeyCode::Char(c) if key.modifiers.is_empty() || key.modifiers == KeyModifiers::SHIFT => {
153 Some(c)
154 }
155 _ => None,
156 }
157}
158
159pub const HELP: &str = "\
161vissue tui
162
163j/k, arrows move
164Tab, 1-5 pane (Ready List Claims Agenda Search)
165Enter focus detail / cycle detail tab
166p project filter
167/ search
168c claim
169n note
170s cycle TODO / STARTED / BLOCKED
171D DONE (confirm)
172X CANCELLED (confirm)
173o open (shared selection)
174y copy id
175R reload
176? this help
177q / Esc quit / back
178
179Body edits stay in the file.
180body lives in file; open the range above
181";