fresh/app/
keybinding_editor_actions.rs1use super::keybinding_editor::KeybindingEditor;
6use super::Editor;
7use crate::input::handler::InputResult;
8use crate::view::keybinding_editor::{handle_keybinding_editor_input, KeybindingEditorAction};
9use crate::view::ui::point_in_rect;
10use crossterm::event::{KeyEvent, MouseButton, MouseEvent, MouseEventKind};
11
12impl Editor {
13 pub fn open_keybinding_editor(&mut self) {
15 let config_path = self.dir_context.config_path().display().to_string();
16 self.keybinding_editor = Some(KeybindingEditor::new(
17 &self.config,
18 &self.keybindings,
19 config_path,
20 ));
21 }
22
23 pub fn handle_keybinding_editor_input(&mut self, event: &KeyEvent) -> InputResult {
25 let mut editor = match self.keybinding_editor.take() {
26 Some(e) => e,
27 None => return InputResult::Ignored,
28 };
29
30 let action = handle_keybinding_editor_input(&mut editor, event);
31
32 match action {
33 KeybindingEditorAction::Consumed => {
34 self.keybinding_editor = Some(editor);
35 InputResult::Consumed
36 }
37 KeybindingEditorAction::Close => {
38 self.set_status_message("Keybinding editor closed".to_string());
40 InputResult::Consumed
41 }
42 KeybindingEditorAction::SaveAndClose => {
43 self.save_keybinding_editor_changes(&editor);
45 InputResult::Consumed
46 }
47 KeybindingEditorAction::StatusMessage(msg) => {
48 self.set_status_message(msg);
49 self.keybinding_editor = Some(editor);
50 InputResult::Consumed
51 }
52 }
53 }
54
55 fn save_keybinding_editor_changes(&mut self, editor: &KeybindingEditor) {
57 if !editor.has_changes {
58 return;
59 }
60
61 for remove in editor.get_pending_removes() {
63 self.config.keybindings.retain(|kb| {
64 !(kb.action == remove.action
65 && kb.key == remove.key
66 && kb.modifiers == remove.modifiers
67 && kb.when == remove.when)
68 });
69 }
70
71 let new_bindings = editor.get_custom_bindings();
73 for binding in new_bindings {
74 self.config.keybindings.push(binding);
75 }
76
77 self.keybindings = crate::input::keybindings::KeybindingResolver::new(&self.config);
79
80 let config_value = match serde_json::to_value(&self.config.keybindings) {
82 Ok(v) => v,
83 Err(e) => {
84 self.set_status_message(format!("Failed to serialize keybindings: {}", e));
85 return;
86 }
87 };
88
89 let mut changes = std::collections::HashMap::new();
90 changes.insert("/keybindings".to_string(), config_value);
91
92 let resolver = crate::config_io::ConfigResolver::new(
93 self.dir_context.clone(),
94 self.working_dir.clone(),
95 );
96
97 match resolver.save_changes_to_layer(
98 &changes,
99 &std::collections::HashSet::new(),
100 crate::config_io::ConfigLayer::User,
101 ) {
102 Ok(()) => {
103 self.set_status_message("Keybinding changes saved".to_string());
104 }
105 Err(e) => {
106 self.set_status_message(format!("Failed to save keybindings: {}", e));
107 }
108 }
109 }
110
111 pub fn is_keybinding_editor_active(&self) -> bool {
113 self.keybinding_editor.is_some()
114 }
115
116 pub fn handle_keybinding_editor_mouse(
119 &mut self,
120 mouse_event: MouseEvent,
121 ) -> anyhow::Result<bool> {
122 let mut editor = match self.keybinding_editor.take() {
123 Some(e) => e,
124 None => return Ok(false),
125 };
126
127 let col = mouse_event.column;
128 let row = mouse_event.row;
129 let layout = &editor.layout;
130
131 if !point_in_rect(layout.modal_area, col, row) {
134 self.keybinding_editor = Some(editor);
135 return Ok(false);
136 }
137
138 match mouse_event.kind {
139 MouseEventKind::ScrollUp => {
140 if editor.edit_dialog.is_none() && !editor.showing_confirm_dialog {
142 editor.select_prev();
143 }
144 }
145 MouseEventKind::ScrollDown => {
146 if editor.edit_dialog.is_none() && !editor.showing_confirm_dialog {
147 editor.select_next();
148 }
149 }
150 MouseEventKind::Down(MouseButton::Left) => {
151 if editor.showing_confirm_dialog {
153 if let Some((save_r, discard_r, cancel_r)) = layout.confirm_buttons {
154 if point_in_rect(save_r, col, row) {
155 self.save_keybinding_editor_changes(&editor);
156 return Ok(true);
157 } else if point_in_rect(discard_r, col, row) {
158 self.set_status_message("Keybinding editor closed".to_string());
159 return Ok(true);
160 } else if point_in_rect(cancel_r, col, row) {
161 editor.showing_confirm_dialog = false;
162 }
163 }
164 self.keybinding_editor = Some(editor);
165 return Ok(true);
166 }
167
168 if editor.edit_dialog.is_some() {
170 if let Some((save_r, cancel_r)) = layout.dialog_buttons {
172 if point_in_rect(save_r, col, row) {
173 if let Some(err) = editor.apply_edit_dialog() {
175 self.set_status_message(err);
176 }
177 self.keybinding_editor = Some(editor);
178 return Ok(true);
179 } else if point_in_rect(cancel_r, col, row) {
180 editor.edit_dialog = None;
182 self.keybinding_editor = Some(editor);
183 return Ok(true);
184 }
185 }
186 if let Some(r) = layout.dialog_key_field {
188 if point_in_rect(r, col, row) {
189 if let Some(ref mut dialog) = editor.edit_dialog {
190 dialog.focus_area = 0;
191 dialog.mode = crate::app::keybinding_editor::EditMode::RecordingKey;
192 }
193 }
194 }
195 if let Some(r) = layout.dialog_action_field {
196 if point_in_rect(r, col, row) {
197 if let Some(ref mut dialog) = editor.edit_dialog {
198 dialog.focus_area = 1;
199 dialog.mode =
200 crate::app::keybinding_editor::EditMode::EditingAction;
201 }
202 }
203 }
204 if let Some(r) = layout.dialog_context_field {
205 if point_in_rect(r, col, row) {
206 if let Some(ref mut dialog) = editor.edit_dialog {
207 dialog.focus_area = 2;
208 dialog.mode =
209 crate::app::keybinding_editor::EditMode::EditingContext;
210 }
211 }
212 }
213 self.keybinding_editor = Some(editor);
214 return Ok(true);
215 }
216
217 if let Some(search_r) = layout.search_bar {
219 if point_in_rect(search_r, col, row) {
220 editor.start_search();
221 self.keybinding_editor = Some(editor);
222 return Ok(true);
223 }
224 }
225
226 let table_area = layout.table_area;
228 let first_row_y = layout.table_first_row_y;
229 if point_in_rect(table_area, col, row) && row >= first_row_y {
230 let clicked_row = (row - first_row_y) as usize;
231 let new_selected = editor.scroll.offset as usize + clicked_row;
232 if new_selected < editor.filtered_indices.len() {
233 editor.selected = new_selected;
234 }
235 }
236 }
237 _ => {}
238 }
239
240 self.keybinding_editor = Some(editor);
241 Ok(true)
242 }
243}