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