Complete desktop parity and security audit (#42)

This commit is contained in:
2026-08-10 20:38:28 +02:00
parent 4a54bf7b6a
commit 40b15a9713
5 changed files with 340 additions and 36 deletions

View File

@@ -2,6 +2,32 @@
use iced::keyboard::{self, key::Named};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DesktopPlatform {
MacOs,
Linux,
Windows,
}
impl DesktopPlatform {
pub const fn current() -> Self {
if cfg!(target_os = "macos") {
Self::MacOs
} else if cfg!(target_os = "windows") {
Self::Windows
} else {
Self::Linux
}
}
const fn primary_modifier(self) -> keyboard::Modifiers {
match self {
Self::MacOs => keyboard::Modifiers::LOGO,
Self::Linux | Self::Windows => keyboard::Modifiers::CTRL,
}
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum UiAction {
About,
@@ -314,8 +340,12 @@ pub fn actions_in(group: MenuGroup) -> impl Iterator<Item = &'static ActionSpec>
}
pub fn shortcut_label(action: UiAction) -> Option<String> {
shortcut_label_for(action, DesktopPlatform::current())
}
pub fn shortcut_label_for(action: UiAction, platform: DesktopPlatform) -> Option<String> {
let shortcut = spec_for(action).shortcut?;
if cfg!(target_os = "macos") {
if platform == DesktopPlatform::MacOs {
Some(shortcut.to_owned())
} else {
Some(shortcut.replace('⇧', "Shift+").replace('⌘', "Ctrl+"))
@@ -685,13 +715,21 @@ pub const fn aliases(action: UiAction) -> &'static [&'static str] {
}
pub fn shortcut_action(key: &keyboard::Key, modifiers: keyboard::Modifiers) -> Option<UiAction> {
shortcut_action_for(DesktopPlatform::current(), key, modifiers)
}
pub fn shortcut_action_for(
platform: DesktopPlatform,
key: &keyboard::Key,
modifiers: keyboard::Modifiers,
) -> Option<UiAction> {
if key.as_ref() == keyboard::Key::Named(Named::Tab) && modifiers.is_empty() {
return Some(UiAction::TogglePaneFocus);
}
if key.as_ref() == keyboard::Key::Named(Named::F1) {
return Some(UiAction::Help);
}
if !modifiers.command() {
if !modifiers.contains(platform.primary_modifier()) {
return None;
}
match key.as_ref() {
@@ -940,36 +978,62 @@ mod tests {
}
#[test]
fn conventional_shortcuts_resolve_to_the_registered_actions() {
let primary = keyboard::Modifiers::COMMAND;
for (key, expected) in [
("o", UiAction::OpenFolder),
("s", UiAction::Save),
("f", UiAction::Find),
("k", UiAction::CommandPalette),
("n", UiAction::NewEntry),
("w", UiAction::CloseWindow),
("q", UiAction::Quit),
("x", UiAction::Cut),
("c", UiAction::CopyField),
("v", UiAction::Paste),
(",", UiAction::Settings),
fn conventional_shortcuts_resolve_on_every_supported_platform() {
for (platform, primary, label) in [
(DesktopPlatform::MacOs, keyboard::Modifiers::LOGO, "⌘S"),
(DesktopPlatform::Linux, keyboard::Modifiers::CTRL, "Ctrl+S"),
(
DesktopPlatform::Windows,
keyboard::Modifiers::CTRL,
"Ctrl+S",
),
] {
assert_eq!(
shortcut_action(&keyboard::Key::Character(key.into()), primary),
Some(expected)
shortcut_label_for(UiAction::Save, platform).as_deref(),
Some(label)
);
for (key, expected) in [
("o", UiAction::OpenFolder),
("s", UiAction::Save),
("f", UiAction::Find),
("k", UiAction::CommandPalette),
("n", UiAction::NewEntry),
("w", UiAction::CloseWindow),
("q", UiAction::Quit),
("x", UiAction::Cut),
("c", UiAction::CopyField),
("v", UiAction::Paste),
(",", UiAction::Settings),
] {
assert_eq!(
shortcut_action_for(platform, &keyboard::Key::Character(key.into()), primary,),
Some(expected)
);
}
assert_eq!(
shortcut_action_for(
platform,
&keyboard::Key::Character("f".into()),
primary | keyboard::Modifiers::SHIFT,
),
Some(UiAction::SearchContents)
);
assert_eq!(
shortcut_action_for(
platform,
&keyboard::Key::Named(Named::F1),
keyboard::Modifiers::NONE,
),
Some(UiAction::Help)
);
}
assert_eq!(
shortcut_action(
&keyboard::Key::Character("f".into()),
primary | keyboard::Modifiers::SHIFT,
shortcut_action_for(
DesktopPlatform::MacOs,
&keyboard::Key::Character("s".into()),
keyboard::Modifiers::CTRL,
),
Some(UiAction::SearchContents)
);
assert_eq!(
shortcut_action(&keyboard::Key::Named(Named::F1), keyboard::Modifiers::NONE),
Some(UiAction::Help)
None
);
assert_eq!(shortcut_label(UiAction::Help).as_deref(), Some("F1"));
}