diff --git a/README.md b/README.md index 13804cd..4757133 100644 --- a/README.md +++ b/README.md @@ -146,11 +146,13 @@ | + r | Ctrl + r | Refresh Page | | + w | Ctrl + w | Hide window, not quit | | + - | Ctrl + - | Zoom out the page | -| + + | Ctrl + + | Zoom in the page | | + = | Ctrl + = | Zoom in the Page | | + 0 | Ctrl + 0 | Reset the page zoom | +| + L | Ctrl + L | Copy Current Page URL | +| + + H | Ctrl + Shift + H | Go to Home Page | +| + + I | Ctrl + Shift + I | Toggle Developer Tools (Debug Only) | -In addition, double-click the title bar to switch to full-screen mode. For Mac users, you can also use the gesture to go to the previous or next page and drag the title bar to move the window. +In addition, double-click the title bar to switch to full-screen mode. For Mac users, you can also use the gesture to go to the previous or next page and drag the title bar to move the window. The new menu also offers options for navigation, zoom, and window controls. diff --git a/README_CN.md b/README_CN.md index 7b4b39a..5f9245c 100644 --- a/README_CN.md +++ b/README_CN.md @@ -147,11 +147,13 @@ | + r | Ctrl + r | 刷新页面 | | + w | Ctrl + w | 隐藏窗口,非退出 | | + - | Ctrl + - | 缩小页面 | -| + + | Ctrl + + | 放大页面 | | + = | Ctrl + = | 放大页面 | | + 0 | Ctrl + 0 | 重置页面缩放 | +| + L | Ctrl + L | 复制当前页面网址 | +| + + H | Ctrl + Shift + H | 回到首页 | +| + + I | Ctrl + Shift + I | 开启调试 (仅开发版) | -此外还支持双击头部全屏切换,拖拽头部移动窗口,Mac 用户支持手势返回和前进,有其他需求欢迎提出。 +此外还支持双击头部全屏切换,拖拽头部移动窗口,Mac 用户支持手势返回和前进,新菜单也提供了导航、缩放和窗口控制等选项。 diff --git a/README_JP.md b/README_JP.md index 26f91a9..de1f525 100644 --- a/README_JP.md +++ b/README_JP.md @@ -145,11 +145,13 @@ | + r | Ctrl + r | ページをリフレッシュ | | + w | Ctrl + w | ウィンドウを隠す、終了しない | | + - | Ctrl + - | ページを縮小 | -| + + | Ctrl + + | ページを拡大 | | + = | Ctrl + = | ページを拡大 | | + 0 | Ctrl + 0 | ページのズームをリセット | +| + L | Ctrl + L | 現在のURLをコピー | +| + + H | Ctrl + Shift + H | ホームページに戻る | +| + + I | Ctrl + Shift + I | 開発者ツール (デバッグのみ) | -さらに、タイトルバーをダブルクリックして全画面モードに切り替えることができます。Mac ユーザーは、ジェスチャーを使用して前のページまたは次のページに移動することもできます。ウィンドウを移動するには、タイトルバーをドラッグします。 +さらに、タイトルバーをダブルクリックして全画面モードに切り替えることができます。Mac ユーザーは、ジェスチャーを使用して前のページまたは次のページに移動することもできます。新しいメニューには、ナビゲーション、ズーム、ウィンドウ制御などのオプションも用意されています。 diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index b796bb4..7c0c8df 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2588,7 +2588,7 @@ dependencies = [ [[package]] name = "pake" -version = "3.1.2" +version = "3.5.4" dependencies = [ "serde", "serde_json", @@ -2598,6 +2598,7 @@ dependencies = [ "tauri-plugin-http", "tauri-plugin-notification", "tauri-plugin-oauth", + "tauri-plugin-opener", "tauri-plugin-shell", "tauri-plugin-single-instance", "tauri-plugin-window-state", @@ -4022,9 +4023,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.9.0" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f07c6590706b2fc0ab287b041cf5ce9c435b3850bdae5571e19d9d27584e89d" +checksum = "15524fc7959bfcaa051ba6d0b3fb1ef18e978de2176c7c6acb977f7fd14d35c7" dependencies = [ "anyhow", "bytes", @@ -4066,7 +4067,6 @@ dependencies = [ "tokio", "tray-icon", "url", - "urlpattern", "webkit2gtk", "webview2-com", "window-vibrancy", @@ -4075,9 +4075,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.5.0" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71be1f494b683ac439e6d61c16ab5c472c6f9c6ee78995b29556d9067c021a1" +checksum = "17fcb8819fd16463512a12f531d44826ce566f486d7ccd211c9c8cebdaec4e08" dependencies = [ "anyhow", "cargo_toml", @@ -4097,9 +4097,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c1fe64c74cc40f90848281a90058a6db931eb400b60205840e09801ee30f190" +checksum = "9fa9844cefcf99554a16e0a278156ae73b0d8680bbc0e2ad1e4287aadd8489cf" dependencies = [ "base64 0.22.1", "brotli", @@ -4124,9 +4124,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "260c5d2eb036b76206b9fca20b7be3614cfd21046c5396f7959e0e64a4b07f2f" +checksum = "3764a12f886d8245e66b7ee9b43ccc47883399be2019a61d80cf0f4117446fde" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -4155,9 +4155,9 @@ dependencies = [ [[package]] name = "tauri-plugin-fs" -version = "2.4.2" +version = "2.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "315784ec4be45e90a987687bae7235e6be3d6e9e350d2b75c16b8a4bf22c1db7" +checksum = "47df422695255ecbe7bac7012440eddaeefd026656171eac9559f5243d3230d9" dependencies = [ "anyhow", "dunce", @@ -4177,9 +4177,9 @@ dependencies = [ [[package]] name = "tauri-plugin-global-shortcut" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6df9f0f7bf2fe768b85fee4951c2505a35b72c44df1f6403e74e110bc13c5f58" +checksum = "424af23c7e88d05e4a1a6fc2c7be077912f8c76bd7900fd50aa2b7cbf5a2c405" dependencies = [ "global-hotkey", "log", @@ -4192,9 +4192,9 @@ dependencies = [ [[package]] name = "tauri-plugin-http" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938a3d7051c9a82b431e3a0f3468f85715b3442b3c3a3913095e9fa509e2652c" +checksum = "c00685aceab12643cf024f712ab0448ba8fcadf86f2391d49d2e5aa732aacc70" dependencies = [ "bytes", "cookie_store", @@ -4216,9 +4216,9 @@ dependencies = [ [[package]] name = "tauri-plugin-notification" -version = "2.3.1" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fbc86b929b5376ab84b25c060f966d146b2fbd59b6af8264027b343c82c219" +checksum = "01fc2c5ff41105bd1f7242d8201fdf3efd70749b82fa013a17f2126357d194cc" dependencies = [ "log", "notify-rust", @@ -4249,10 +4249,32 @@ dependencies = [ ] [[package]] -name = "tauri-plugin-shell" -version = "2.3.1" +name = "tauri-plugin-opener" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54777d0c0d8add34eea3ced84378619ef5b97996bd967d3038c668feefd21071" +checksum = "c26b72571d25dee25667940027114e60f569fc3974f8cefbe50c2cbc5fd65e3b" +dependencies = [ + "dunce", + "glob", + "objc2-app-kit", + "objc2-foundation 0.3.2", + "open", + "schemars 0.8.22", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.17", + "url", + "windows", + "zbus", +] + +[[package]] +name = "tauri-plugin-shell" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c374b6db45f2a8a304f0273a15080d98c70cde86178855fc24653ba657a1144c" dependencies = [ "encoding_rs", "log", @@ -4271,9 +4293,9 @@ dependencies = [ [[package]] name = "tauri-plugin-single-instance" -version = "2.3.4" +version = "2.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb9cac815bf11c4a80fb498666bcdad66d65b89e3ae24669e47806febb76389c" +checksum = "dd707f8c86b4e3004e2c141fa24351f1909ba40ce1b8437e30d5ed5277dd3710" dependencies = [ "serde", "serde_json", @@ -4286,9 +4308,9 @@ dependencies = [ [[package]] name = "tauri-plugin-window-state" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5f6fe3291bfa609c7e0b0ee3bedac294d94c7018934086ce782c1d0f2a468e" +checksum = "73736611e14142408d15353e21e3cca2f12a3cfb523ad0ce85999b6d2ef1a704" dependencies = [ "bitflags 2.10.0", "log", @@ -4301,9 +4323,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.9.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3367f0b47df90e9195cd9f04a56b0055a2cba45aa11923c6c253d748778176fc" +checksum = "87f766fe9f3d1efc4b59b17e7a891ad5ed195fa8d23582abb02e6c9a01137892" dependencies = [ "cookie", "dpi", @@ -4326,9 +4348,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.9.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d91d29ca680c545364cf75ba2f2e3c7ea2ab6376bfa3be26b56fa2463a5b5e" +checksum = "7950f3bde6bcca6655bc5e76d3d6ec587ceb81032851ab4ddbe1f508bdea2729" dependencies = [ "gtk", "http", @@ -4353,9 +4375,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b8bbe426abdbf52d050e52ed693130dbd68375b9ad82a3fb17efb4c8d85673" +checksum = "76a423c51176eb3616ee9b516a9fa67fed5f0e78baaba680e44eb5dd2cc37490" dependencies = [ "anyhow", "brotli", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 3971803..fbe88cf 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pake" -version = "3.1.2" +version = "3.5.4" description = "🤱🏻 Turn any webpage into a desktop app with Rust." authors = ["Tw93"] license = "MIT" @@ -15,20 +15,21 @@ crate-type = ["staticlib", "cdylib", "lib"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] -tauri-build = { version = "2.5.0", features = [] } +tauri-build = { version = "2.5.3", features = [] } [dependencies] serde_json = "1.0.145" serde = { version = "1.0.228", features = ["derive"] } tokio = { version = "1.48.0", features = ["full"] } -tauri = { version = "2.9.0", features = ["tray-icon", "image-ico", "image-png", "macos-proxy"] } -tauri-plugin-window-state = "2.4.0" +tauri = { version = "2.9.4", features = ["tray-icon", "image-ico", "image-png", "macos-proxy"] } +tauri-plugin-window-state = "2.4.1" tauri-plugin-oauth = "2.0.0" -tauri-plugin-http = "2.5.2" -tauri-plugin-global-shortcut = { version = "2.3.0" } -tauri-plugin-shell = "2.3.1" -tauri-plugin-single-instance = "2.3.4" -tauri-plugin-notification = "2.3.1" +tauri-plugin-http = "2.5.4" +tauri-plugin-global-shortcut = { version = "2.3.1" } +tauri-plugin-shell = { version = "2.3.3" } +tauri-plugin-opener = { version = "2.5.2" } +tauri-plugin-single-instance = "2.3.6" +tauri-plugin-notification = "2.3.3" [features] # this feature is used for development builds from development cli diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 1eb1a78..0e5dd53 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -9,6 +9,9 @@ use tauri_plugin_window_state::StateFlags; #[cfg(target_os = "macos")] use std::time::Duration; +use tauri::menu::{AboutMetadata, Menu, MenuItem, PredefinedMenuItem, Submenu}; +use tauri_plugin_opener::OpenerExt; // Add this + use app::{ invoke::{download_file, download_file_by_binary, send_notification, update_theme_mode}, setup::{set_global_shortcut, set_system_tray}, @@ -42,7 +45,8 @@ pub fn run_app() { .plugin(tauri_plugin_oauth::init()) .plugin(tauri_plugin_http::init()) .plugin(tauri_plugin_shell::init()) - .plugin(tauri_plugin_notification::init()); + .plugin(tauri_plugin_notification::init()) + .plugin(tauri_plugin_opener::init()); // Add this // Only add single instance plugin if multiple instances are not allowed if !multi_instance { @@ -63,6 +67,227 @@ pub fn run_app() { update_theme_mode, ]) .setup(move |app| { + // --- Menu Construction Start --- + let pake_version = env!("CARGO_PKG_VERSION"); + let pake_menu_item_title = format!("Built with Pake V{}", pake_version); + + // App Menu (macOS specific, e.g., "Pake") + let app_menu = Submenu::new(app, "Pake", true)?; + let about_metadata = AboutMetadata::default(); + app_menu.append(&PredefinedMenuItem::about( + app, + Some("Pake"), + Some(about_metadata), + )?)?; + app_menu.append(&PredefinedMenuItem::separator(app)?)?; + app_menu.append(&PredefinedMenuItem::services(app, None)?)?; + app_menu.append(&PredefinedMenuItem::separator(app)?)?; + app_menu.append(&PredefinedMenuItem::hide(app, None)?)?; + app_menu.append(&PredefinedMenuItem::hide_others(app, None)?)?; + app_menu.append(&PredefinedMenuItem::show_all(app, None)?)?; + app_menu.append(&PredefinedMenuItem::separator(app)?)?; + app_menu.append(&PredefinedMenuItem::quit(app, None)?)?; + + // File Menu + let file_menu = Submenu::new(app, "File", true)?; + file_menu.append(&PredefinedMenuItem::close_window(app, None)?)?; + + // Edit Menu + let edit_menu = Submenu::new(app, "Edit", true)?; + edit_menu.append(&PredefinedMenuItem::undo(app, None)?)?; + edit_menu.append(&PredefinedMenuItem::redo(app, None)?)?; + edit_menu.append(&PredefinedMenuItem::separator(app)?)?; + edit_menu.append(&PredefinedMenuItem::cut(app, None)?)?; + edit_menu.append(&PredefinedMenuItem::copy(app, None)?)?; + edit_menu.append(&PredefinedMenuItem::paste(app, None)?)?; + edit_menu.append(&PredefinedMenuItem::select_all(app, None)?)?; + edit_menu.append(&PredefinedMenuItem::separator(app)?)?; + edit_menu.append(&MenuItem::with_id( + app, + "copy_url", + "Copy URL", + true, + Some("CmdOrCtrl+L"), + )?)?; + + // View Menu + let view_menu = Submenu::new(app, "View", true)?; + view_menu.append(&MenuItem::with_id( + app, + "reload", + "Reload", + true, + Some("CmdOrCtrl+R"), + )?)?; + view_menu.append(&PredefinedMenuItem::separator(app)?)?; + view_menu.append(&MenuItem::with_id( + app, + "zoom_in", + "Zoom In", + true, + Some("CmdOrCtrl+="), + )?)?; + view_menu.append(&MenuItem::with_id( + app, + "zoom_out", + "Zoom Out", + true, + Some("CmdOrCtrl+-"), + )?)?; + view_menu.append(&MenuItem::with_id( + app, + "zoom_reset", + "Actual Size", + true, + Some("CmdOrCtrl+0"), + )?)?; + view_menu.append(&PredefinedMenuItem::separator(app)?)?; + view_menu.append(&PredefinedMenuItem::fullscreen(app, None)?)?; + view_menu.append(&PredefinedMenuItem::separator(app)?)?; + view_menu.append(&MenuItem::with_id( + app, + "toggle_devtools", + "Toggle Developer Tools", + cfg!(debug_assertions), + Some("CmdOrCtrl+Option+I"), + )?)?; + + // Navigation Menu + let navigation_menu = Submenu::new(app, "Navigation", true)?; + navigation_menu.append(&MenuItem::with_id( + app, + "go_back", + "Back", + true, + Some("CmdOrCtrl+["), + )?)?; + navigation_menu.append(&MenuItem::with_id( + app, + "go_forward", + "Forward", + true, + Some("CmdOrCtrl+]"), + )?)?; + navigation_menu.append(&MenuItem::with_id( + app, + "go_home", + "Go Home", + true, + Some("CmdOrCtrl+Shift+H"), + )?)?; + + // Window Menu + let window_menu = Submenu::new(app, "Window", true)?; + window_menu.append(&PredefinedMenuItem::minimize(app, None)?)?; + window_menu.append(&PredefinedMenuItem::maximize(app, None)?)?; + window_menu.append(&PredefinedMenuItem::separator(app)?)?; + window_menu.append(&MenuItem::with_id( + app, + "always_on_top", + "Toggle Always on Top", + true, + None::<&str>, + )?)?; + window_menu.append(&PredefinedMenuItem::separator(app)?)?; + window_menu.append(&PredefinedMenuItem::close_window(app, None)?)?; + + // Help Menu (Custom) + let help_menu = Submenu::new(app, "Help", true)?; + let github_item = MenuItem::with_id( + app, + "pake_github_link", + &pake_menu_item_title, + true, + None::<&str>, + )?; + help_menu.append(&github_item)?; + + // Construct the Menu Bar + let menu = Menu::with_items( + app, + &[ + &app_menu, + &file_menu, + &edit_menu, + &view_menu, + &navigation_menu, + &window_menu, + &help_menu, + ], + )?; + + app.set_menu(menu)?; + + // Event Handling for Custom Menu Item + app.on_menu_event(move |app_handle, event| { + match event.id().as_ref() { + "pake_github_link" => { + let _ = app_handle + .opener() + .open_url("https://github.com/tw93/Pake", None::<&str>); + } + "reload" => { + if let Some(window) = app_handle.get_webview_window("pake") { + let _ = window.eval("window.location.reload()"); + } + } + "toggle_devtools" => { + #[cfg(debug_assertions)] // Only allow in debug builds + if let Some(window) = app_handle.get_webview_window("pake") { + if window.is_devtools_open() { + window.close_devtools(); + } else { + window.open_devtools(); + } + } + } + "zoom_in" => { + if let Some(window) = app_handle.get_webview_window("pake") { + let _ = window.eval("zoomIn()"); + } + } + "zoom_out" => { + if let Some(window) = app_handle.get_webview_window("pake") { + let _ = window.eval("zoomOut()"); + } + } + "zoom_reset" => { + if let Some(window) = app_handle.get_webview_window("pake") { + let _ = window.eval("setZoom('100%')"); + } + } + "go_back" => { + if let Some(window) = app_handle.get_webview_window("pake") { + let _ = window.eval("window.history.back()"); + } + } + "go_forward" => { + if let Some(window) = app_handle.get_webview_window("pake") { + let _ = window.eval("window.history.forward()"); + } + } + "go_home" => { + if let Some(window) = app_handle.get_webview_window("pake") { + let _ = window.eval("window.location.href = window.pakeConfig.url"); + } + } + "copy_url" => { + if let Some(window) = app_handle.get_webview_window("pake") { + let _ = + window.eval("navigator.clipboard.writeText(window.location.href)"); + } + } + "always_on_top" => { + if let Some(window) = app_handle.get_webview_window("pake") { + let is_on_top = window.is_always_on_top().unwrap_or(false); + let _ = window.set_always_on_top(!is_on_top); + } + } + _ => {} + } + }); + // --- Menu Construction End --- + let window = set_window(app, &pake_config, &tauri_config); set_system_tray( app.app_handle(),