keymap_ui: Ensure keybind with empty arguments can be saved (#36393)

Follow up to #36278 to ensure this bug is actually fixed. Also fixes
this on two layers and adds a test for the lower layer, as we cannot
properly test it in the UI.

Furthermore, this improves the error message to show some more context
and ensures the status toast is actually only shown when the keybind was
successfully updated: Before, we would show the success toast whilst
also showing an error in the editor.

Lastly, this also fixes some issues with the status toast (and
animations) where no status toast or no animation would show in certain
scenarios.

Release Notes:

- N/A
This commit is contained in:
Finn Evers 2025-08-18 13:01:32 +02:00 committed by GitHub
parent d83f341d27
commit 843336970a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 93 additions and 74 deletions

View file

@ -2177,11 +2177,11 @@ impl KeybindingEditorModal {
let action_arguments = self
.action_arguments_editor
.as_ref()
.map(|editor| editor.read(cx).editor.read(cx).text(cx));
.map(|arguments_editor| arguments_editor.read(cx).editor.read(cx).text(cx))
.filter(|args| !args.is_empty());
let value = action_arguments
.as_ref()
.filter(|args| !args.is_empty())
.map(|args| {
serde_json::from_str(args).context("Failed to parse action arguments as JSON")
})
@ -2289,29 +2289,11 @@ impl KeybindingEditorModal {
let create = self.creating;
let status_toast = StatusToast::new(
format!(
"Saved edits to the {} action.",
&self.editing_keybind.action().humanized_name
),
cx,
move |this, _cx| {
this.icon(ToastIcon::new(IconName::Check).color(Color::Success))
.dismiss_button(true)
// .action("Undo", f) todo: wire the undo functionality
},
);
self.workspace
.update(cx, |workspace, cx| {
workspace.toggle_status_toast(status_toast, cx);
})
.log_err();
cx.spawn(async move |this, cx| {
let action_name = existing_keybind.action().name;
let humanized_action_name = existing_keybind.action().humanized_name.clone();
if let Err(err) = save_keybinding_update(
match save_keybinding_update(
create,
existing_keybind,
&action_mapping,
@ -2321,25 +2303,43 @@ impl KeybindingEditorModal {
)
.await
{
this.update(cx, |this, cx| {
this.set_error(InputError::error(err), cx);
})
.log_err();
} else {
this.update(cx, |this, cx| {
this.keymap_editor.update(cx, |keymap, cx| {
keymap.previous_edit = Some(PreviousEdit::Keybinding {
action_mapping,
action_name,
fallback: keymap
.table_interaction_state
.read(cx)
.get_scrollbar_offset(Axis::Vertical),
})
});
cx.emit(DismissEvent);
})
.ok();
Ok(_) => {
this.update(cx, |this, cx| {
this.keymap_editor.update(cx, |keymap, cx| {
keymap.previous_edit = Some(PreviousEdit::Keybinding {
action_mapping,
action_name,
fallback: keymap
.table_interaction_state
.read(cx)
.get_scrollbar_offset(Axis::Vertical),
});
let status_toast = StatusToast::new(
format!("Saved edits to the {} action.", humanized_action_name),
cx,
move |this, _cx| {
this.icon(ToastIcon::new(IconName::Check).color(Color::Success))
.dismiss_button(true)
// .action("Undo", f) todo: wire the undo functionality
},
);
this.workspace
.update(cx, |workspace, cx| {
workspace.toggle_status_toast(status_toast, cx);
})
.log_err();
});
cx.emit(DismissEvent);
})
.ok();
}
Err(err) => {
this.update(cx, |this, cx| {
this.set_error(InputError::error(err), cx);
})
.log_err();
}
}
})
.detach();
@ -3011,7 +3011,7 @@ async fn save_keybinding_update(
let updated_keymap_contents =
settings::KeymapFile::update_keybinding(operation, keymap_contents, tab_size)
.context("Failed to update keybinding")?;
.map_err(|err| anyhow::anyhow!("Could not save updated keybinding: {}", err))?;
fs.write(
paths::keymap_file().as_path(),
updated_keymap_contents.as_bytes(),