From b575094f4b6e6a466d2beb4ee73d10a77ad69eb0 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Wed, 1 Mar 2023 12:37:53 +0800 Subject: [PATCH] feat: basic app menu (#1207) --- apps/desktop/src-tauri/Cargo.lock | 36 +++++++++ apps/desktop/src-tauri/Cargo.toml | 2 +- apps/desktop/src-tauri/src/main.rs | 3 + apps/desktop/src-tauri/src/menu.rs | 108 +++++++++++++++++++++++++ apps/desktop/src-tauri/tauri.conf.json | 5 ++ apps/desktop/src/preload/index.ts | 8 -- apps/desktop/src/preload/type.ts | 1 + 7 files changed, 154 insertions(+), 9 deletions(-) create mode 100644 apps/desktop/src-tauri/src/menu.rs diff --git a/apps/desktop/src-tauri/Cargo.lock b/apps/desktop/src-tauri/Cargo.lock index c2b4d052f2..c6b321ce2d 100644 --- a/apps/desktop/src-tauri/Cargo.lock +++ b/apps/desktop/src-tauri/Cargo.lock @@ -2115,6 +2115,30 @@ dependencies = [ "thiserror", ] +[[package]] +name = "libappindicator" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2d3cb96d092b4824cb306c9e544c856a4cb6210c1081945187f7f1924b47e8" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b3b6681973cea8cc3bce7391e6d7d5502720b80a581c9a95c9cbaf592826aa" +dependencies = [ + "gtk-sys", + "libloading", + "once_cell", +] + [[package]] name = "libc" version = "0.2.138" @@ -2130,6 +2154,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + [[package]] name = "libsqlite3-sys" version = "0.24.2" @@ -4430,6 +4464,7 @@ dependencies = [ "core-foundation", "core-graphics", "crossbeam-channel", + "dirs-next", "dispatch", "gdk", "gdk-pixbuf", @@ -4443,6 +4478,7 @@ dependencies = [ "instant", "jni", "lazy_static", + "libappindicator", "libc", "log", "ndk", diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index 0811174f47..0da68ed2b5 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -35,7 +35,7 @@ schemars = "0.8.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" dotenvy = "0.15.6" -tauri = { version = "1.2", features = ["api-all", "devtools"] } +tauri = { version = "1.2", features = ["api-all", "devtools", "system-tray"] } tokio = { version = "1.23.0", features = ["rt", "macros"] } lib0 = "0.12.0" moka = { version = "0.9.6", features = ["future"] } diff --git a/apps/desktop/src-tauri/src/main.rs b/apps/desktop/src-tauri/src/main.rs index 2d60864bf2..d5342abaf9 100644 --- a/apps/desktop/src-tauri/src/main.rs +++ b/apps/desktop/src-tauri/src/main.rs @@ -5,6 +5,7 @@ mod commands; mod state; +mod menu; use dotenvy::dotenv; use state::AppState; use std::env; @@ -47,6 +48,8 @@ async fn main() { Ok(()) }) .invoke_handler(commands::invoke_handler()) + .menu(menu::init()) + .on_menu_event(menu::menu_handler) .run(tauri::generate_context!()) .expect("error while running tauri application"); } diff --git a/apps/desktop/src-tauri/src/menu.rs b/apps/desktop/src-tauri/src/menu.rs new file mode 100644 index 0000000000..cbcc105500 --- /dev/null +++ b/apps/desktop/src-tauri/src/menu.rs @@ -0,0 +1,108 @@ +use tauri::{CustomMenuItem, Manager, Menu, MenuItem, Submenu, WindowMenuEvent}; + +#[cfg(target_os = "macos")] +use tauri::AboutMetadata; + +// --- Menu +pub fn init() -> Menu { + let name = "AFFiNE"; + let app_menu = Submenu::new( + name, + Menu::with_items([ + #[cfg(target_os = "macos")] + MenuItem::About(name.into(), AboutMetadata::default()).into(), + MenuItem::Services.into(), + MenuItem::Hide.into(), + MenuItem::HideOthers.into(), + MenuItem::ShowAll.into(), + MenuItem::Separator.into(), + MenuItem::Quit.into(), + ]), + ); + + let edit_menu = Submenu::new( + "Edit", + Menu::new() + .add_native_item(MenuItem::Undo) + .add_native_item(MenuItem::Redo) + .add_native_item(MenuItem::Separator) + .add_native_item(MenuItem::Cut) + .add_native_item(MenuItem::Copy) + .add_native_item(MenuItem::Paste) + .add_native_item(MenuItem::SelectAll), + ); + + let view_menu = Submenu::new( + "View", + Menu::new() + .add_item(CustomMenuItem::new("go_back".to_string(), "Go Back").accelerator("CmdOrCtrl+[")) + .add_item( + CustomMenuItem::new("go_forward".to_string(), "Go Forward").accelerator("CmdOrCtrl+]"), + ) + .add_native_item(MenuItem::Separator) + .add_item( + CustomMenuItem::new("zoom_0".to_string(), "Zoom to Actual Size").accelerator("CmdOrCtrl+0"), + ) + .add_item(CustomMenuItem::new("zoom_out".to_string(), "Zoom Out").accelerator("CmdOrCtrl+-")) + .add_item(CustomMenuItem::new("zoom_in".to_string(), "Zoom In").accelerator("CmdOrCtrl+Plus")) + .add_native_item(MenuItem::Separator) + .add_item( + CustomMenuItem::new("reload".to_string(), "Refresh the Screen").accelerator("CmdOrCtrl+R"), + ), + ); + + let window_menu = Submenu::new( + "Window", + Menu::new() + .add_item(CustomMenuItem::new( + "official_website".to_string(), + "About AFFiNE", + )) + .add_native_item(MenuItem::Separator) + .add_native_item(MenuItem::Minimize) + .add_native_item(MenuItem::Zoom), + ); + + let help_menu = Submenu::new( + "Help", + Menu::new() + .add_item(CustomMenuItem::new("update_log".to_string(), "Update Log")) + .add_item(CustomMenuItem::new("report_bug".to_string(), "Report Bug")) + .add_item( + CustomMenuItem::new("dev_tools".to_string(), "Toggle Developer Tools") + .accelerator("CmdOrCtrl+Shift+I"), + ), + ); + + Menu::new() + .add_submenu(app_menu) + .add_submenu(window_menu) + .add_submenu(edit_menu) + .add_submenu(view_menu) + .add_submenu(help_menu) +} + +// --- Menu Event +pub fn menu_handler(event: WindowMenuEvent) { + let win = Some(event.window()).unwrap(); + let app = win.app_handle(); + let menu_id = event.menu_item_id(); + + match menu_id { + // App + "restart" => tauri::api::process::restart(&app.env()), + // Window + // View + "zoom_0" => win.eval("window.__zoom0 && window.__zoom0()").unwrap(), + "zoom_out" => win.eval("window.__zoomOut && window.__zoomOut()").unwrap(), + "zoom_in" => win.eval("window.__zoomIn && window.__zoomIn()").unwrap(), + "reload" => win.eval("window.location.reload()").unwrap(), + "go_back" => win.eval("window.history.go(-1)").unwrap(), + "go_forward" => win.eval("window.history.go(1)").unwrap(), + "dev_tools" => { + win.open_devtools(); + win.close_devtools(); + } + _ => {} + } +} diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 5f91121a81..7826b99c7d 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -18,6 +18,11 @@ "scope": ["$RESOURCE", "$RESOURCE/*", "$APP/*"] } }, + "systemTray": { + "iconPath": "icons/128x128@2x.png", + "iconAsTemplate": true, + "menuOnLeftClick": false + }, "bundle": { "active": true, "category": "DeveloperTool", diff --git a/apps/desktop/src/preload/index.ts b/apps/desktop/src/preload/index.ts index 6ac4908c4a..866504b859 100644 --- a/apps/desktop/src/preload/index.ts +++ b/apps/desktop/src/preload/index.ts @@ -1,9 +1,3 @@ -declare global { - interface Window { - __TAURI_ISOLATION_HOOK_: (payload: any) => any; - } -} - // tauri preload script can't have `export {}` // @ts-ignore 'index.ts' cannot be compiled under '--isolatedModules' because it is considered a global script file. Add an import, export, or an empty 'export {}' statement to make it a module.ts(1208) window.__TAURI_ISOLATION_HOOK__ = payload => { @@ -20,5 +14,3 @@ function setEnvironmentVariables() { } setEnvironmentVariables(); - -export {}; diff --git a/apps/desktop/src/preload/type.ts b/apps/desktop/src/preload/type.ts index fc17ded153..68ceb265f1 100644 --- a/apps/desktop/src/preload/type.ts +++ b/apps/desktop/src/preload/type.ts @@ -4,6 +4,7 @@ declare global { interface Window { CLIENT_APP?: boolean; + __TAURI_ISOLATION_HOOK_: (payload: any) => any; } }