1pub mod state;
2
3use self::state::{DiffState, RunningState};
4use crate::{
5 services::{config::Config, git::Diff, logger::Logs},
6 update::{keys::Key, message::Message},
7};
8use anyhow::Result;
9use crossterm::event::{self, Event, KeyEventKind};
10use ratatui::widgets::ListState;
11use std::{cell::RefCell, cmp, time::Duration};
12
13#[derive(Debug)]
14pub struct App {
15 running_state: RunningState,
16 config: Config,
18 diff: Diff,
19 diff_state: DiffState,
20 logs: Logs,
21 console_state: RefCell<ListState>,
22 tick_rate: Duration,
24}
25
26impl App {
27 pub fn new(logs: Logs) -> Self {
28 let mut new = Self {
29 running_state: Default::default(),
30 config: Config::new().expect("A config"),
32 diff: Default::default(),
33 diff_state: Default::default(),
34 logs,
35 console_state: Default::default(),
36 tick_rate: Duration::from_millis(250),
37 };
38
39 new.handle_console();
40
41 return new;
42 }
43
44 pub fn console_state(&self) -> &RefCell<ListState> {
45 &self.console_state
46 }
47
48 pub fn handle_console(&mut self) {
49 let console_length = self.console().len();
50 let console_state_index = cmp::max(1, console_length) - 1;
51
52 self.console_state
53 .borrow_mut()
54 .select(Some(console_state_index));
55 }
56
57 pub fn update(&mut self, msg: Message) -> Option<Message> {
58 log::info!("{}", msg);
59 self.handle_console();
60
61 match msg {
62 Message::PrevRow => {
63 self.previous_row();
64 }
65 Message::NextRow => {
66 self.next_row();
67 }
68 Message::LastRow => {
69 self.go_to_last_row();
70 }
71 Message::FirstRow => {
72 self.diff_state().reset_row_state();
73 }
74 Message::Quit => {
75 self.quit();
77 }
78 }
79
80 None
81 }
82
83 pub fn handle_event(&self) -> Result<Option<Message>> {
84 if event::poll(self.tick_rate)? {
85 if let Event::Key(key) = event::read()? {
86 if key.kind == KeyEventKind::Press {
87 return Ok(self.handle_key(key.into()));
89 }
90 }
91 }
92 Ok(None)
93 }
94
95 fn handle_key(&self, key: Key) -> Option<Message> {
96 let key_string = key.to_string();
97 let key = self.config.keymap().get(&key_string);
98 key.cloned()
99 }
100
101 pub fn console(&self) -> Vec<String> {
102 return self.logs.lock().unwrap().clone();
103 }
104
105 pub fn config(&self) -> &Config {
106 &self.config
107 }
108
109 pub fn diff_state(&self) -> &DiffState {
110 &self.diff_state
111 }
112
113 pub fn diff(&self) -> Option<&Diff> {
114 if self.diff.old_diff().len() != 0 && self.diff.current_diff().len() != 0 {
115 return Some(&self.diff);
116 }
117 None
118 }
119
120 pub fn set_diff(&mut self, diff_string: &str) {
121 self.diff = Diff::parse_diff(diff_string)
122 }
123
124 pub fn running_state(&self) -> &RunningState {
125 &self.running_state
126 }
127
128 fn quit(&mut self) {
129 self.running_state = RunningState::Done
130 }
131
132 fn go_to_last_row(&self) {
133 let last_row = self.diff.longest_diff_len();
134 self.diff_state
135 .old_diff()
136 .borrow_mut()
137 .select(Some(last_row));
138 self.diff_state
139 .current_diff()
140 .borrow_mut()
141 .select(Some(last_row));
142 }
143
144 fn next_row(&self) {
145 let old_diff_row_index = match self.diff_state.old_diff().borrow().selected() {
146 Some(i) => {
147 if i >= self.diff.old_diff().len() - 1 {
148 0
149 } else {
150 i + 1
151 }
152 }
153 None => 0,
154 };
155
156 let current_diff_row_index = match self.diff_state.current_diff().borrow().selected() {
157 Some(j) => {
158 if j >= self.diff.current_diff().len() - 1 {
159 0
160 } else {
161 j + 1
162 }
163 }
164 None => 0,
165 };
166
167 self.diff_state
168 .old_diff()
169 .borrow_mut()
170 .select(Some(old_diff_row_index));
171 self.diff_state
172 .current_diff()
173 .borrow_mut()
174 .select(Some(current_diff_row_index));
175 }
176
177 fn previous_row(&self) {
178 let old_diff_row_index = match self.diff_state.old_diff().borrow().selected() {
179 Some(i) => {
180 if i == 0 {
181 self.diff.old_diff().len() - 1
182 } else {
183 i - 1
184 }
185 }
186 None => 0,
187 };
188
189 let current_diff_row_index = match self.diff_state.current_diff().borrow().selected() {
190 Some(j) => {
191 if j == 0 {
192 self.diff.current_diff().len() - 1
193 } else {
194 j - 1
195 }
196 }
197 None => 0,
198 };
199
200 self.diff_state
201 .old_diff()
202 .borrow_mut()
203 .select(Some(old_diff_row_index));
204 self.diff_state
205 .current_diff()
206 .borrow_mut()
207 .select(Some(current_diff_row_index));
208 }
209}