From fabebdbd994d1129a78324396eaf99cbdc8d6b40 Mon Sep 17 00:00:00 2001 From: Tw93 Date: Fri, 17 Oct 2025 18:00:28 +0800 Subject: [PATCH] add --maximize and --start-to-tray options --- CLAUDE.md | 2 ++ bin/cli.ts | 10 ++++++++++ bin/defaults.ts | 2 ++ bin/helpers/merge.ts | 4 ++++ bin/types.ts | 6 ++++++ docs/cli-usage.md | 22 ++++++++++++++++++++++ docs/cli-usage_CN.md | 21 +++++++++++++++++++++ package.json | 2 +- src-tauri/pake.json | 4 +++- src-tauri/src/app/config.rs | 2 ++ src-tauri/src/app/setup.rs | 29 ++++++++++++++++++++++++++--- src-tauri/src/lib.rs | 16 ++++++++++------ 12 files changed, 109 insertions(+), 11 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d5575c6..999fdc0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -57,12 +57,14 @@ pnpm run dev # Development with hot reload - **CLI Tool** (`bin/`): Main entry point, builders, options processing - **Tauri App** (`src-tauri/`): Rust application, window/tray management, injection logic - **Config Files**: `pake.json`, `tauri.conf.json`, platform-specific configs +- **Injection System** (`src-tauri/src/inject/event.js`): Custom event handlers, shortcuts, downloads, notifications ## Documentation Guidelines - **Main README**: Common parameters only - **CLI Documentation** (`docs/cli-usage.md`): ALL parameters with examples - **Rare parameters**: Full docs in CLI usage, minimal in main README +- **NO technical documentation files**: Do not create separate technical docs, design docs, or implementation notes - keep technical details in memory/conversation only ## Platform Specifics diff --git a/bin/cli.ts b/bin/cli.ts index 3581570..2a74625 100644 --- a/bin/cli.ts +++ b/bin/cli.ts @@ -99,6 +99,11 @@ program .default(DEFAULT.alwaysOnTop) .hideHelp(), ) + .addOption( + new Option('--maximize', 'Start window maximized') + .default(DEFAULT.maximize) + .hideHelp(), + ) .addOption( new Option('--dark-mode', 'Force Mac app to use dark mode') .default(DEFAULT.darkMode) @@ -164,6 +169,11 @@ program .default(DEFAULT.multiInstance) .hideHelp(), ) + .addOption( + new Option('--start-to-tray', 'Start app minimized to tray') + .default(DEFAULT.startToTray) + .hideHelp(), + ) .addOption( new Option('--installer-language ', 'Installer language') .default(DEFAULT.installerLanguage) diff --git a/bin/defaults.ts b/bin/defaults.ts index a4e9dd0..a78501b 100644 --- a/bin/defaults.ts +++ b/bin/defaults.ts @@ -5,6 +5,7 @@ export const DEFAULT_PAKE_OPTIONS: PakeCliOptions = { height: 780, width: 1200, fullscreen: false, + maximize: false, resizable: true, hideTitleBar: false, alwaysOnTop: false, @@ -28,6 +29,7 @@ export const DEFAULT_PAKE_OPTIONS: PakeCliOptions = { enableDragDrop: false, keepBinary: false, multiInstance: false, + startToTray: false, }; // Just for cli development diff --git a/bin/helpers/merge.ts b/bin/helpers/merge.ts index e9fb65a..311fd92 100644 --- a/bin/helpers/merge.ts +++ b/bin/helpers/merge.ts @@ -49,6 +49,7 @@ export async function mergeConfig( width, height, fullscreen, + maximize, hideTitleBar, alwaysOnTop, appVersion, @@ -71,6 +72,7 @@ export async function mergeConfig( wasm, enableDragDrop, multiInstance, + startToTray, } = options; const { platform } = process; @@ -81,6 +83,7 @@ export async function mergeConfig( width, height, fullscreen, + maximize, resizable, hide_title_bar: hideTitleBar, activation_shortcut: activationShortcut, @@ -92,6 +95,7 @@ export async function mergeConfig( title: title || null, enable_wasm: wasm, enable_drag_drop: enableDragDrop, + start_to_tray: startToTray && showSystemTray, }; Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions }); diff --git a/bin/types.ts b/bin/types.ts index 7ed61f7..4559207 100644 --- a/bin/types.ts +++ b/bin/types.ts @@ -24,6 +24,9 @@ export interface PakeCliOptions { // Whether the window can be fullscreen, default false fullscreen: boolean; + // Start window maximized, default false + maximize: boolean; + // Enable immersive header, default false. hideTitleBar: boolean; @@ -90,6 +93,9 @@ export interface PakeCliOptions { // Allow multiple instances, default false (single instance) multiInstance: boolean; + + // Start app minimized to tray, default false + startToTray: boolean; } export interface PakeAppOptions extends PakeCliOptions { diff --git a/docs/cli-usage.md b/docs/cli-usage.md index da90e25..9e6efc8 100644 --- a/docs/cli-usage.md +++ b/docs/cli-usage.md @@ -160,6 +160,15 @@ screen. --fullscreen ``` +#### [maximize] + +Determine whether the application launches with a maximized window. Default is `false`. Use the following command to enable +maximize. + +```shell +--maximize +``` + #### [activation-shortcut] Set the activation shortcut for the application. Default is empty, so it does not take effect. You can customize the activation shortcut with the following commands, e.g. `CmdOrControl+Shift+P`. Usage can refer to [available-modifiers](https://www.electronjs.org/docs/latest/api/accelerator#available-modifiers). @@ -293,6 +302,19 @@ Hide window instead of closing the application when clicking close button. Platf --hide-on-close false ``` +#### [start-to-tray] + +Start the application minimized to system tray instead of showing the window. Must be used with `--show-system-tray`. Default is `false`. + +```shell +--start-to-tray + +# Example: Start hidden to tray (must use with --show-system-tray) +pake https://github.com --name GitHub --show-system-tray --start-to-tray +``` + +**Note**: Double-click the tray icon to show/hide the window. If used without `--show-system-tray`, this option is ignored. + #### [title] Set the window title bar text. macOS shows no title if not specified; Windows/Linux fallback to app name. diff --git a/docs/cli-usage_CN.md b/docs/cli-usage_CN.md index a3f7fe0..82ada93 100644 --- a/docs/cli-usage_CN.md +++ b/docs/cli-usage_CN.md @@ -159,6 +159,14 @@ pake https://github.com --name GitHub --fullscreen ``` +#### [maximize] + +设置应用程序是否在启动时最大化窗口,默认为 `false`。使用以下命令可以设置应用程序启动时窗口最大化。 + +```shell +--maximize +``` + #### [activation-shortcut] 设置应用程序的激活快捷键。默认为空,不生效,可以使用以下命令自定义激活快捷键,例如 `CmdOrControl+Shift+P`,使用可参考 [available-modifiers](https://www.electronjs.org/docs/latest/api/accelerator#available-modifiers)。 @@ -292,6 +300,19 @@ pake https://github.com --name GitHub --hide-on-close false ``` +#### [start-to-tray] + +启动时将应用程序最小化到系统托盘而不是显示窗口。必须与 `--show-system-tray` 一起使用。默认为 `false`。 + +```shell +--start-to-tray + +# 示例:启动时隐藏到托盘(必须与 --show-system-tray 一起使用) +pake https://github.com --name GitHub --show-system-tray --start-to-tray +``` + +**注意**:双击托盘图标可以显示/隐藏窗口。如果不与 `--show-system-tray` 一起使用,此选项将被忽略。 + #### [title] 设置窗口标题栏文本,macOS 未指定时不显示标题,Windows/Linux 回退使用应用名称。 diff --git a/package.json b/package.json index aac5378..db709ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pake-cli", - "version": "3.4.0", + "version": "3.4.1", "description": "🤱🏻 Turn any webpage into a desktop app with one command. 🤱🏻 一键打包网页生成轻量桌面应用。", "engines": { "node": ">=18.0.0" diff --git a/src-tauri/pake.json b/src-tauri/pake.json index f76f783..97ad31a 100644 --- a/src-tauri/pake.json +++ b/src-tauri/pake.json @@ -15,7 +15,9 @@ "hide_on_close": true, "incognito": false, "enable_wasm": false, - "enable_drag_drop": false + "enable_drag_drop": false, + "maximize": false, + "start_to_tray": false } ], "user_agent": { diff --git a/src-tauri/src/app/config.rs b/src-tauri/src/app/config.rs index 591b9f5..9246b7b 100644 --- a/src-tauri/src/app/config.rs +++ b/src-tauri/src/app/config.rs @@ -5,6 +5,7 @@ pub struct WindowConfig { pub url: String, pub hide_title_bar: bool, pub fullscreen: bool, + pub maximize: bool, pub width: f64, pub height: f64, pub resizable: bool, @@ -18,6 +19,7 @@ pub struct WindowConfig { pub title: Option, pub enable_wasm: bool, pub enable_drag_drop: bool, + pub start_to_tray: bool, } #[derive(Debug, Serialize, Deserialize)] diff --git a/src-tauri/src/app/setup.rs b/src-tauri/src/app/setup.rs index a66a427..7a01a76 100644 --- a/src-tauri/src/app/setup.rs +++ b/src-tauri/src/app/setup.rs @@ -3,13 +3,13 @@ use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; use tauri::{ menu::{MenuBuilder, MenuItemBuilder}, - tray::TrayIconBuilder, + tray::{TrayIconBuilder, TrayIconEvent}, AppHandle, Manager, }; use tauri_plugin_global_shortcut::{GlobalShortcutExt, Shortcut}; use tauri_plugin_window_state::{AppHandleExt, StateFlags}; -pub fn set_system_tray(app: &AppHandle, show_system_tray: bool) -> tauri::Result<()> { +pub fn set_system_tray(app: &AppHandle, show_system_tray: bool, tray_icon_path: &str) -> tauri::Result<()> { if !show_system_tray { app.remove_tray_by_id("pake-tray"); return Ok(()); @@ -44,7 +44,30 @@ pub fn set_system_tray(app: &AppHandle, show_system_tray: bool) -> tauri::Result } _ => (), }) - .icon(app.default_window_icon().unwrap().clone()) + .on_tray_icon_event(|tray, event| match event { + TrayIconEvent::Click { button, .. } => { + if button == tauri::tray::MouseButton::Left { + if let Some(window) = tray.app_handle().get_webview_window("pake") { + let is_visible = window.is_visible().unwrap_or(false); + if is_visible { + window.hide().unwrap(); + } else { + window.show().unwrap(); + window.set_focus().unwrap(); + } + } + } + } + _ => {} + }) + .icon(if tray_icon_path.is_empty() { + app.default_window_icon().unwrap_or_else(|| panic!("Failed to get default window icon")).clone() + } else { + tauri::image::Image::from_path(tray_icon_path).unwrap_or_else(|_| { + // If custom tray icon fails to load, fallback to default + app.default_window_icon().unwrap_or_else(|| panic!("Failed to get default window icon")).clone() + }) + }) .build(app)?; tray.set_icon_as_template(false)?; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 4b43c9a..6e7b6fc 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -24,6 +24,7 @@ pub fn run_app() { let hide_on_close = pake_config.windows[0].hide_on_close; let activation_shortcut = pake_config.windows[0].activation_shortcut.clone(); let init_fullscreen = pake_config.windows[0].fullscreen; + let start_to_tray = pake_config.windows[0].start_to_tray && show_system_tray; // Only valid when tray is enabled let multi_instance = pake_config.multi_instance; let window_state_plugin = WindowStatePlugin::default() @@ -62,15 +63,18 @@ pub fn run_app() { ]) .setup(move |app| { let window = set_window(app, &pake_config, &tauri_config); - set_system_tray(app.app_handle(), show_system_tray).unwrap(); + set_system_tray(app.app_handle(), show_system_tray, &pake_config.system_tray_path).unwrap(); set_global_shortcut(app.app_handle(), activation_shortcut).unwrap(); // Show window after state restoration to prevent position flashing - let window_clone = window.clone(); - tauri::async_runtime::spawn(async move { - tokio::time::sleep(tokio::time::Duration::from_millis(50)).await; - window_clone.show().unwrap(); - }); + // Unless start_to_tray is enabled, then keep it hidden + if !start_to_tray { + let window_clone = window.clone(); + tauri::async_runtime::spawn(async move { + tokio::time::sleep(tokio::time::Duration::from_millis(50)).await; + window_clone.show().unwrap(); + }); + } Ok(()) })