feat: more native menus with expected reactions
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
use muda::accelerator::{Accelerator, CMD_OR_CTRL, Code, Modifiers};
|
||||
use muda::{Menu, MenuEvent, MenuItem, PredefinedMenuItem, Submenu};
|
||||
use muda::{CheckMenuItem, Menu, MenuEvent, MenuItem, PredefinedMenuItem, Submenu};
|
||||
|
||||
use crate::native_edit::EditCommand;
|
||||
|
||||
const PREFERENCES: &str = "preferences";
|
||||
const MODEL_MANAGER: &str = "model-manager";
|
||||
const NEW_CHAT: &str = "new-chat";
|
||||
const EXPORT_CHAT: &str = "export-chat";
|
||||
const TOGGLE_SIDEBAR: &str = "toggle-sidebar";
|
||||
const HELP: &str = "help";
|
||||
const UNDO: &str = "undo";
|
||||
const REDO: &str = "redo";
|
||||
const CUT: &str = "cut";
|
||||
@@ -14,20 +18,36 @@ const SELECT_ALL: &str = "select-all";
|
||||
|
||||
pub(crate) struct NativeMenu {
|
||||
_menu: Menu,
|
||||
new_chat: MenuItem,
|
||||
export_chat: MenuItem,
|
||||
sidebar: CheckMenuItem,
|
||||
undo: MenuItem,
|
||||
redo: MenuItem,
|
||||
cut: MenuItem,
|
||||
copy: MenuItem,
|
||||
paste: MenuItem,
|
||||
select_all: MenuItem,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub(crate) enum NativeMenuEvent {
|
||||
Preferences,
|
||||
ModelManager,
|
||||
NewChat,
|
||||
ExportChat,
|
||||
ToggleSidebar,
|
||||
Help,
|
||||
Edit(EditCommand),
|
||||
}
|
||||
|
||||
pub(crate) fn install() -> Result<NativeMenu, String> {
|
||||
let menu = Menu::new();
|
||||
let application = Submenu::new("DS4Server", true);
|
||||
let file = Submenu::new("File", true);
|
||||
let edit = Submenu::new("Edit", true);
|
||||
let view = Submenu::new("View", true);
|
||||
let window = Submenu::new("Window", true);
|
||||
let help = Submenu::new("Help", true);
|
||||
let preferences = MenuItem::with_id(
|
||||
PREFERENCES,
|
||||
"Preferences…",
|
||||
@@ -43,6 +63,37 @@ pub(crate) fn install() -> Result<NativeMenu, String> {
|
||||
Code::KeyM,
|
||||
)),
|
||||
);
|
||||
let new_chat = MenuItem::with_id(
|
||||
NEW_CHAT,
|
||||
"New Chat",
|
||||
false,
|
||||
Some(Accelerator::new(Some(Modifiers::SUPER), Code::KeyN)),
|
||||
);
|
||||
let export_chat = MenuItem::with_id(
|
||||
EXPORT_CHAT,
|
||||
"Export Chat as Markdown…",
|
||||
false,
|
||||
Some(Accelerator::new(
|
||||
Some(Modifiers::SUPER | Modifiers::SHIFT),
|
||||
Code::KeyS,
|
||||
)),
|
||||
);
|
||||
let sidebar = CheckMenuItem::with_id(
|
||||
TOGGLE_SIDEBAR,
|
||||
"Show Sidebar",
|
||||
true,
|
||||
true,
|
||||
Some(Accelerator::new(Some(Modifiers::SUPER), Code::KeyB)),
|
||||
);
|
||||
let open_help = MenuItem::with_id(
|
||||
HELP,
|
||||
"DS4Server Help",
|
||||
true,
|
||||
Some(Accelerator::new(
|
||||
Some(Modifiers::SUPER | Modifiers::SHIFT),
|
||||
Code::Slash,
|
||||
)),
|
||||
);
|
||||
let undo = edit_item(UNDO, "Undo", Code::KeyZ, None);
|
||||
let redo = edit_item(REDO, "Redo", Code::KeyZ, Some(Modifiers::SHIFT));
|
||||
let cut = edit_item(CUT, "Cut", Code::KeyX, None);
|
||||
@@ -65,6 +116,13 @@ pub(crate) fn install() -> Result<NativeMenu, String> {
|
||||
&PredefinedMenuItem::quit(None),
|
||||
])
|
||||
.map_err(|error| error.to_string())?;
|
||||
file.append_items(&[
|
||||
&new_chat,
|
||||
&export_chat,
|
||||
&PredefinedMenuItem::separator(),
|
||||
&PredefinedMenuItem::close_window(None),
|
||||
])
|
||||
.map_err(|error| error.to_string())?;
|
||||
edit.append_items(&[
|
||||
&undo,
|
||||
&redo,
|
||||
@@ -75,21 +133,53 @@ pub(crate) fn install() -> Result<NativeMenu, String> {
|
||||
&select_all,
|
||||
])
|
||||
.map_err(|error| error.to_string())?;
|
||||
view.append_items(&[&sidebar, &PredefinedMenuItem::separator(), &model_manager])
|
||||
.map_err(|error| error.to_string())?;
|
||||
window
|
||||
.append_items(&[
|
||||
&model_manager,
|
||||
&PredefinedMenuItem::separator(),
|
||||
&PredefinedMenuItem::minimize(None),
|
||||
&PredefinedMenuItem::maximize(None),
|
||||
&PredefinedMenuItem::close_window(None),
|
||||
&PredefinedMenuItem::bring_all_to_front(None),
|
||||
])
|
||||
.map_err(|error| error.to_string())?;
|
||||
menu.append_items(&[&application, &edit, &window])
|
||||
help.append(&open_help).map_err(|error| error.to_string())?;
|
||||
menu.append_items(&[&application, &file, &edit, &view, &window, &help])
|
||||
.map_err(|error| error.to_string())?;
|
||||
menu.init_for_nsapp();
|
||||
window.set_as_windows_menu_for_nsapp();
|
||||
Ok(NativeMenu { _menu: menu })
|
||||
Ok(NativeMenu {
|
||||
_menu: menu,
|
||||
new_chat,
|
||||
export_chat,
|
||||
sidebar,
|
||||
undo,
|
||||
redo,
|
||||
cut,
|
||||
copy,
|
||||
paste,
|
||||
select_all,
|
||||
})
|
||||
}
|
||||
|
||||
impl NativeMenu {
|
||||
pub(crate) fn update(
|
||||
&self,
|
||||
project_active: bool,
|
||||
chat_active: bool,
|
||||
sidebar_visible: bool,
|
||||
edit: crate::native_edit::EditAvailability,
|
||||
) {
|
||||
self.new_chat.set_enabled(project_active);
|
||||
self.export_chat.set_enabled(chat_active);
|
||||
self.sidebar.set_checked(sidebar_visible);
|
||||
self.undo.set_enabled(edit.undo);
|
||||
self.redo.set_enabled(edit.redo);
|
||||
self.cut.set_enabled(edit.cut);
|
||||
self.copy.set_enabled(edit.copy);
|
||||
self.paste.set_enabled(edit.paste);
|
||||
self.select_all.set_enabled(edit.select_all);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn next_event() -> Option<NativeMenuEvent> {
|
||||
@@ -97,6 +187,10 @@ pub(crate) fn next_event() -> Option<NativeMenuEvent> {
|
||||
let event = match event.id.0.as_str() {
|
||||
PREFERENCES => NativeMenuEvent::Preferences,
|
||||
MODEL_MANAGER => NativeMenuEvent::ModelManager,
|
||||
NEW_CHAT => NativeMenuEvent::NewChat,
|
||||
EXPORT_CHAT => NativeMenuEvent::ExportChat,
|
||||
TOGGLE_SIDEBAR => NativeMenuEvent::ToggleSidebar,
|
||||
HELP => NativeMenuEvent::Help,
|
||||
UNDO => NativeMenuEvent::Edit(EditCommand::Undo),
|
||||
REDO => NativeMenuEvent::Edit(EditCommand::Redo),
|
||||
CUT => NativeMenuEvent::Edit(EditCommand::Cut),
|
||||
|
||||
Reference in New Issue
Block a user