pake-cli 3.4.0 โ†’ 3.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -23,7 +23,7 @@ import sharp from 'sharp';
23
23
  import * as psl from 'psl';
24
24
 
25
25
  var name = "pake-cli";
26
- var version = "3.4.0";
26
+ var version = "3.4.2";
27
27
  var description = "๐Ÿคฑ๐Ÿป Turn any webpage into a desktop app with one command. ๐Ÿคฑ๐Ÿป ไธ€้”ฎๆ‰“ๅŒ…็ฝ‘้กต็”Ÿๆˆ่ฝป้‡ๆกŒ้ขๅบ”็”จใ€‚";
28
28
  var engines = {
29
29
  node: ">=18.0.0"
@@ -201,11 +201,13 @@ const IS_MAC = platform$1 === 'darwin';
201
201
  const IS_WIN = platform$1 === 'win32';
202
202
  const IS_LINUX = platform$1 === 'linux';
203
203
 
204
- async function shellExec(command, timeout = 300000, env, showOutput = false) {
204
+ async function shellExec(command, timeout = 300000, env) {
205
205
  try {
206
206
  const { exitCode } = await execa(command, {
207
207
  cwd: npmDirectory,
208
- stdio: showOutput ? 'inherit' : ['inherit', 'pipe', 'inherit'],
208
+ // Use 'inherit' to show all output directly to user in real-time.
209
+ // This ensures linuxdeploy and other tool outputs are visible during builds.
210
+ stdio: 'inherit',
209
211
  shell: true,
210
212
  timeout,
211
213
  env: env ? { ...process.env, ...env } : process.env,
@@ -219,15 +221,35 @@ async function shellExec(command, timeout = 300000, env, showOutput = false) {
219
221
  throw new Error(`Command timed out after ${timeout}ms: "${command}". Try increasing timeout or check network connectivity.`);
220
222
  }
221
223
  let errorMsg = `Error occurred while executing command "${command}". Exit code: ${exitCode}. Details: ${errorMessage}`;
224
+ // Provide helpful guidance for common Linux AppImage build failures
225
+ // caused by strip tool incompatibility with modern glibc (2.38+)
226
+ const lowerError = errorMessage.toLowerCase();
222
227
  if (process.platform === 'linux' &&
223
- (errorMessage.includes('linuxdeploy') ||
224
- errorMessage.includes('appimage') ||
225
- errorMessage.includes('strip'))) {
228
+ (lowerError.includes('linuxdeploy') ||
229
+ lowerError.includes('appimage') ||
230
+ lowerError.includes('strip'))) {
226
231
  errorMsg +=
227
- '\n\nLinux AppImage build error. Try one of these solutions:\n' +
228
- ' 1. Run with: NO_STRIP=true pake <url> --targets appimage\n' +
229
- ' 2. Use DEB format instead: pake <url> --targets deb\n' +
230
- ' 3. See detailed solutions: https://github.com/tw93/Pake/blob/main/docs/faq.md';
232
+ '\n\nโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n' +
233
+ 'Linux AppImage Build Failed\n' +
234
+ 'โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n\n' +
235
+ 'Cause: Strip tool incompatibility with glibc 2.38+\n' +
236
+ ' (affects Debian Trixie, Arch Linux, and other modern distros)\n\n' +
237
+ 'Quick fix:\n' +
238
+ ' NO_STRIP=1 pake <url> --targets appimage --debug\n\n' +
239
+ 'Alternatives:\n' +
240
+ ' โ€ข Use DEB format: pake <url> --targets deb\n' +
241
+ ' โ€ข Update binutils: sudo apt install binutils (or pacman -S binutils)\n' +
242
+ ' โ€ข Detailed guide: https://github.com/tw93/Pake/blob/main/docs/faq.md\n' +
243
+ 'โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”';
244
+ if (lowerError.includes('fuse') ||
245
+ lowerError.includes('operation not permitted') ||
246
+ lowerError.includes('/dev/fuse')) {
247
+ errorMsg +=
248
+ '\n\nDocker / Container hint:\n' +
249
+ ' AppImage tooling needs access to /dev/fuse. When running inside Docker, add:\n' +
250
+ ' --privileged --device /dev/fuse --security-opt apparmor=unconfined\n' +
251
+ ' or run on the host directly.';
252
+ }
231
253
  }
232
254
  throw new Error(errorMsg);
233
255
  }
@@ -351,7 +373,7 @@ async function installRust() {
351
373
  const rustInstallScriptForWindows = 'winget install --id Rustlang.Rustup';
352
374
  const spinner = getSpinner('Downloading Rust...');
353
375
  try {
354
- await shellExec(IS_WIN ? rustInstallScriptForWindows : rustInstallScriptForMac, 300000, undefined, true);
376
+ await shellExec(IS_WIN ? rustInstallScriptForWindows : rustInstallScriptForMac, 300000, undefined);
355
377
  spinner.succeed(chalk.green('โœ” Rust installed successfully!'));
356
378
  ensureRustEnv();
357
379
  }
@@ -448,13 +470,14 @@ async function mergeConfig(url, options, tauriConf) {
448
470
  await fsExtra.copy(sourcePath, destPath);
449
471
  }
450
472
  }));
451
- const { width, height, fullscreen, hideTitleBar, alwaysOnTop, appVersion, darkMode, disabledWebShortcuts, activationShortcut, userAgent, showSystemTray, systemTrayIcon, useLocalFile, identifier, name, resizable = true, inject, proxyUrl, installerLanguage, hideOnClose, incognito, title, wasm, enableDragDrop, multiInstance, } = options;
473
+ const { width, height, fullscreen, maximize, hideTitleBar, alwaysOnTop, appVersion, darkMode, disabledWebShortcuts, activationShortcut, userAgent, showSystemTray, systemTrayIcon, useLocalFile, identifier, name, resizable = true, inject, proxyUrl, installerLanguage, hideOnClose, incognito, title, wasm, enableDragDrop, multiInstance, startToTray, } = options;
452
474
  const { platform } = process;
453
475
  const platformHideOnClose = hideOnClose ?? platform === 'darwin';
454
476
  const tauriConfWindowOptions = {
455
477
  width,
456
478
  height,
457
479
  fullscreen,
480
+ maximize,
458
481
  resizable,
459
482
  hide_title_bar: hideTitleBar,
460
483
  activation_shortcut: activationShortcut,
@@ -466,6 +489,7 @@ async function mergeConfig(url, options, tauriConf) {
466
489
  title: title || null,
467
490
  enable_wasm: wasm,
468
491
  enable_drag_drop: enableDragDrop,
492
+ start_to_tray: startToTray && showSystemTray,
469
493
  };
470
494
  Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions });
471
495
  tauriConf.productName = name;
@@ -774,10 +798,10 @@ class BaseBuilder {
774
798
  logger.info(`โœบ Located in China, using ${packageManager}/rsProxy CN mirror.`);
775
799
  const projectCnConf = path.join(tauriSrcPath, 'rust_proxy.toml');
776
800
  await fsExtra.copy(projectCnConf, projectConf);
777
- await shellExec(`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}`, timeout, buildEnv, this.options.debug);
801
+ await shellExec(`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}`, timeout, buildEnv);
778
802
  }
779
803
  else {
780
- await shellExec(`cd "${npmDirectory}" && ${packageManager} install${peerDepsOption}`, timeout, buildEnv, this.options.debug);
804
+ await shellExec(`cd "${npmDirectory}" && ${packageManager} install${peerDepsOption}`, timeout, buildEnv);
781
805
  }
782
806
  spinner.succeed(chalk.green('Package installed!'));
783
807
  if (!tauriTargetPathExists) {
@@ -802,11 +826,43 @@ class BaseBuilder {
802
826
  buildSpinner.stop();
803
827
  // Show static message to keep the status visible
804
828
  logger.warn('โœธ Building app...');
805
- const buildEnv = {
806
- ...this.getBuildEnvironment(),
807
- ...(process.env.NO_STRIP && { NO_STRIP: process.env.NO_STRIP }),
829
+ const baseEnv = this.getBuildEnvironment();
830
+ let buildEnv = {
831
+ ...(baseEnv ?? {}),
832
+ ...(process.env.NO_STRIP ? { NO_STRIP: process.env.NO_STRIP } : {}),
808
833
  };
809
- await shellExec(`cd "${npmDirectory}" && ${this.getBuildCommand(packageManager)}`, this.getBuildTimeout(), buildEnv, this.options.debug);
834
+ const resolveExecEnv = () => Object.keys(buildEnv).length > 0 ? buildEnv : undefined;
835
+ // Warn users about potential AppImage build failures on modern Linux systems.
836
+ // The linuxdeploy tool bundled in Tauri uses an older strip tool that doesn't
837
+ // recognize the .relr.dyn section introduced in glibc 2.38+.
838
+ if (process.platform === 'linux' && this.options.targets === 'appimage') {
839
+ if (!buildEnv.NO_STRIP) {
840
+ logger.warn('โš  Building AppImage on Linux may fail due to strip incompatibility with glibc 2.38+');
841
+ logger.warn('โš  If build fails, retry with: NO_STRIP=1 pake <url> --targets appimage');
842
+ }
843
+ }
844
+ const buildCommand = `cd "${npmDirectory}" && ${this.getBuildCommand(packageManager)}`;
845
+ const buildTimeout = this.getBuildTimeout();
846
+ try {
847
+ await shellExec(buildCommand, buildTimeout, resolveExecEnv());
848
+ }
849
+ catch (error) {
850
+ const shouldRetryWithoutStrip = process.platform === 'linux' &&
851
+ this.options.targets === 'appimage' &&
852
+ !buildEnv.NO_STRIP &&
853
+ this.isLinuxDeployStripError(error);
854
+ if (shouldRetryWithoutStrip) {
855
+ logger.warn('โš  AppImage build failed during linuxdeploy strip step, retrying with NO_STRIP=1 automatically.');
856
+ buildEnv = {
857
+ ...buildEnv,
858
+ NO_STRIP: '1',
859
+ };
860
+ await shellExec(buildCommand, buildTimeout, resolveExecEnv());
861
+ }
862
+ else {
863
+ throw error;
864
+ }
865
+ }
810
866
  // Copy app
811
867
  const fileName = this.getFileName();
812
868
  const fileType = this.getFileType(target);
@@ -829,6 +885,18 @@ class BaseBuilder {
829
885
  getFileType(target) {
830
886
  return target;
831
887
  }
888
+ isLinuxDeployStripError(error) {
889
+ if (!(error instanceof Error) || !error.message) {
890
+ return false;
891
+ }
892
+ const message = error.message.toLowerCase();
893
+ return (message.includes('linuxdeploy') ||
894
+ message.includes('failed to run linuxdeploy') ||
895
+ message.includes('strip:') ||
896
+ message.includes('unable to recognise the format of the input file') ||
897
+ message.includes('appimage tool failed') ||
898
+ message.includes('strip tool'));
899
+ }
832
900
  /**
833
901
  * ่งฃๆž็›ฎๆ ‡ๆžถๆž„
834
902
  */
@@ -865,6 +933,11 @@ class BaseBuilder {
865
933
  if (target) {
866
934
  fullCommand += ` --target ${target}`;
867
935
  }
936
+ // Enable verbose output in debug mode to help diagnose build issues.
937
+ // This provides detailed logs from Tauri CLI and bundler tools.
938
+ if (this.options.debug) {
939
+ fullCommand += ' --verbose';
940
+ }
868
941
  return fullCommand;
869
942
  }
870
943
  /**
@@ -1178,6 +1251,13 @@ class LinuxBuilder extends BaseBuilder {
1178
1251
  if (features.length > 0) {
1179
1252
  fullCommand += ` --features ${features.join(',')}`;
1180
1253
  }
1254
+ // Enable verbose output for AppImage builds when debugging or PAKE_VERBOSE is set.
1255
+ // AppImage builds often fail with minimal error messages from linuxdeploy,
1256
+ // so verbose mode helps diagnose issues like strip failures and missing dependencies.
1257
+ if (this.options.targets === 'appimage' &&
1258
+ (this.options.debug || process.env.PAKE_VERBOSE)) {
1259
+ fullCommand += ' --verbose';
1260
+ }
1181
1261
  return fullCommand;
1182
1262
  }
1183
1263
  getBasePath() {
@@ -1227,6 +1307,7 @@ const DEFAULT_PAKE_OPTIONS = {
1227
1307
  height: 780,
1228
1308
  width: 1200,
1229
1309
  fullscreen: false,
1310
+ maximize: false,
1230
1311
  hideTitleBar: false,
1231
1312
  alwaysOnTop: false,
1232
1313
  appVersion: '1.0.0',
@@ -1249,6 +1330,7 @@ const DEFAULT_PAKE_OPTIONS = {
1249
1330
  enableDragDrop: false,
1250
1331
  keepBinary: false,
1251
1332
  multiInstance: false,
1333
+ startToTray: false,
1252
1334
  };
1253
1335
 
1254
1336
  async function checkUpdateTips() {
@@ -1731,6 +1813,9 @@ program
1731
1813
  .addOption(new Option('--always-on-top', 'Always on the top level')
1732
1814
  .default(DEFAULT_PAKE_OPTIONS.alwaysOnTop)
1733
1815
  .hideHelp())
1816
+ .addOption(new Option('--maximize', 'Start window maximized')
1817
+ .default(DEFAULT_PAKE_OPTIONS.maximize)
1818
+ .hideHelp())
1734
1819
  .addOption(new Option('--dark-mode', 'Force Mac app to use dark mode')
1735
1820
  .default(DEFAULT_PAKE_OPTIONS.darkMode)
1736
1821
  .hideHelp())
@@ -1774,6 +1859,9 @@ program
1774
1859
  .addOption(new Option('--multi-instance', 'Allow multiple app instances')
1775
1860
  .default(DEFAULT_PAKE_OPTIONS.multiInstance)
1776
1861
  .hideHelp())
1862
+ .addOption(new Option('--start-to-tray', 'Start app minimized to tray')
1863
+ .default(DEFAULT_PAKE_OPTIONS.startToTray)
1864
+ .hideHelp())
1777
1865
  .addOption(new Option('--installer-language <string>', 'Installer language')
1778
1866
  .default(DEFAULT_PAKE_OPTIONS.installerLanguage)
1779
1867
  .hideHelp())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pake-cli",
3
- "version": "3.4.0",
3
+ "version": "3.4.2",
4
4
  "description": "๐Ÿคฑ๐Ÿป Turn any webpage into a desktop app with one command. ๐Ÿคฑ๐Ÿป ไธ€้”ฎๆ‰“ๅŒ…็ฝ‘้กต็”Ÿๆˆ่ฝป้‡ๆกŒ้ขๅบ”็”จใ€‚",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -16,6 +16,8 @@
16
16
  "incognito": false,
17
17
  "enable_wasm": false,
18
18
  "enable_drag_drop": false,
19
+ "maximize": false,
20
+ "start_to_tray": false,
19
21
  "title": null
20
22
  }
21
23
  ],
@@ -15,7 +15,9 @@
15
15
  "hide_on_close": true,
16
16
  "incognito": false,
17
17
  "enable_wasm": false,
18
- "enable_drag_drop": false
18
+ "enable_drag_drop": false,
19
+ "maximize": false,
20
+ "start_to_tray": false
19
21
  }
20
22
  ],
21
23
  "user_agent": {
@@ -5,6 +5,7 @@ pub struct WindowConfig {
5
5
  pub url: String,
6
6
  pub hide_title_bar: bool,
7
7
  pub fullscreen: bool,
8
+ pub maximize: bool,
8
9
  pub width: f64,
9
10
  pub height: f64,
10
11
  pub resizable: bool,
@@ -18,6 +19,7 @@ pub struct WindowConfig {
18
19
  pub title: Option<String>,
19
20
  pub enable_wasm: bool,
20
21
  pub enable_drag_drop: bool,
22
+ pub start_to_tray: bool,
21
23
  }
22
24
 
23
25
  #[derive(Debug, Serialize, Deserialize)]
@@ -3,13 +3,17 @@ use std::sync::{Arc, Mutex};
3
3
  use std::time::{Duration, Instant};
4
4
  use tauri::{
5
5
  menu::{MenuBuilder, MenuItemBuilder},
6
- tray::TrayIconBuilder,
6
+ tray::{TrayIconBuilder, TrayIconEvent},
7
7
  AppHandle, Manager,
8
8
  };
9
9
  use tauri_plugin_global_shortcut::{GlobalShortcutExt, Shortcut};
10
10
  use tauri_plugin_window_state::{AppHandleExt, StateFlags};
11
11
 
12
- pub fn set_system_tray(app: &AppHandle, show_system_tray: bool) -> tauri::Result<()> {
12
+ pub fn set_system_tray(
13
+ app: &AppHandle,
14
+ show_system_tray: bool,
15
+ tray_icon_path: &str,
16
+ ) -> tauri::Result<()> {
13
17
  if !show_system_tray {
14
18
  app.remove_tray_by_id("pake-tray");
15
19
  return Ok(());
@@ -44,7 +48,34 @@ pub fn set_system_tray(app: &AppHandle, show_system_tray: bool) -> tauri::Result
44
48
  }
45
49
  _ => (),
46
50
  })
47
- .icon(app.default_window_icon().unwrap().clone())
51
+ .on_tray_icon_event(|tray, event| match event {
52
+ TrayIconEvent::Click { button, .. } => {
53
+ if button == tauri::tray::MouseButton::Left {
54
+ if let Some(window) = tray.app_handle().get_webview_window("pake") {
55
+ let is_visible = window.is_visible().unwrap_or(false);
56
+ if is_visible {
57
+ window.hide().unwrap();
58
+ } else {
59
+ window.show().unwrap();
60
+ window.set_focus().unwrap();
61
+ }
62
+ }
63
+ }
64
+ }
65
+ _ => {}
66
+ })
67
+ .icon(if tray_icon_path.is_empty() {
68
+ app.default_window_icon()
69
+ .unwrap_or_else(|| panic!("Failed to get default window icon"))
70
+ .clone()
71
+ } else {
72
+ tauri::image::Image::from_path(tray_icon_path).unwrap_or_else(|_| {
73
+ // If custom tray icon fails to load, fallback to default
74
+ app.default_window_icon()
75
+ .unwrap_or_else(|| panic!("Failed to get default window icon"))
76
+ .clone()
77
+ })
78
+ })
48
79
  .build(app)?;
49
80
 
50
81
  tray.set_icon_as_template(false)?;
@@ -6,6 +6,22 @@ use tauri::{App, Config, Url, WebviewUrl, WebviewWindow, WebviewWindowBuilder};
6
6
  #[cfg(target_os = "macos")]
7
7
  use tauri::{Theme, TitleBarStyle};
8
8
 
9
+ #[cfg(target_os = "windows")]
10
+ fn build_proxy_browser_arg(url: &Url) -> Option<String> {
11
+ let host = url.host_str()?;
12
+ let scheme = url.scheme();
13
+ let port = url.port().or_else(|| match scheme {
14
+ "http" => Some(80),
15
+ "socks5" => Some(1080),
16
+ _ => None,
17
+ })?;
18
+
19
+ match scheme {
20
+ "http" | "socks5" => Some(format!("--proxy-server={scheme}://{host}:{port}")),
21
+ _ => None,
22
+ }
23
+ }
24
+
9
25
  pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) -> WebviewWindow {
10
26
  let package_name = tauri_config.clone().product_name.unwrap();
11
27
  let _data_dir = get_data_dir(app.handle(), package_name);
@@ -43,6 +59,7 @@ pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) ->
43
59
  .user_agent(user_agent)
44
60
  .resizable(window_config.resizable)
45
61
  .fullscreen(window_config.fullscreen)
62
+ .maximized(window_config.maximize)
46
63
  .inner_size(window_config.width, window_config.height)
47
64
  .always_on_top(window_config.always_on_top)
48
65
  .incognito(window_config.incognito);
@@ -59,20 +76,36 @@ pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) ->
59
76
  .initialization_script(include_str!("../inject/style.js"))
60
77
  .initialization_script(include_str!("../inject/custom.js"));
61
78
 
79
+ #[cfg(target_os = "windows")]
80
+ let mut windows_browser_args = String::from("--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection --disable-blink-features=AutomationControlled");
81
+
82
+ #[cfg(all(not(target_os = "windows"), not(target_os = "macos")))]
83
+ let mut linux_browser_args = String::from("--disable-blink-features=AutomationControlled");
84
+
62
85
  if window_config.enable_wasm {
63
- window_builder = window_builder
64
- .additional_browser_args("--enable-features=SharedArrayBuffer")
65
- .additional_browser_args("--enable-unsafe-webgpu");
66
- }
86
+ #[cfg(target_os = "windows")]
87
+ {
88
+ windows_browser_args.push_str(" --enable-features=SharedArrayBuffer");
89
+ windows_browser_args.push_str(" --enable-unsafe-webgpu");
90
+ }
67
91
 
68
- if !config.proxy_url.is_empty() {
69
- if let Ok(proxy_url) = Url::from_str(&config.proxy_url) {
70
- window_builder = window_builder.proxy_url(proxy_url);
71
- #[cfg(debug_assertions)]
72
- println!("Proxy configured: {}", config.proxy_url);
92
+ #[cfg(all(not(target_os = "windows"), not(target_os = "macos")))]
93
+ {
94
+ linux_browser_args.push_str(" --enable-features=SharedArrayBuffer");
95
+ linux_browser_args.push_str(" --enable-unsafe-webgpu");
96
+ }
97
+
98
+ #[cfg(target_os = "macos")]
99
+ {
100
+ window_builder = window_builder
101
+ .additional_browser_args("--enable-features=SharedArrayBuffer")
102
+ .additional_browser_args("--enable-unsafe-webgpu");
73
103
  }
74
104
  }
75
105
 
106
+ let mut parsed_proxy_url: Option<Url> = None;
107
+
108
+ // Platform-specific configuration must be set before proxy on Windows/Linux
76
109
  #[cfg(target_os = "macos")]
77
110
  {
78
111
  let title_bar_style = if window_config.hide_title_bar {
@@ -87,13 +120,46 @@ pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) ->
87
120
  }
88
121
  }
89
122
 
90
- // Windows and Linux share the same configuration
123
+ // Windows and Linux: set data_directory before proxy_url
91
124
  #[cfg(not(target_os = "macos"))]
92
125
  {
93
- window_builder = window_builder
94
- .data_directory(_data_dir)
95
- .additional_browser_args("--disable-blink-features=AutomationControlled")
96
- .theme(None);
126
+ window_builder = window_builder.data_directory(_data_dir).theme(None);
127
+
128
+ if !config.proxy_url.is_empty() {
129
+ if let Ok(proxy_url) = Url::from_str(&config.proxy_url) {
130
+ parsed_proxy_url = Some(proxy_url.clone());
131
+ #[cfg(target_os = "windows")]
132
+ {
133
+ if let Some(arg) = build_proxy_browser_arg(&proxy_url) {
134
+ windows_browser_args.push(' ');
135
+ windows_browser_args.push_str(&arg);
136
+ }
137
+ }
138
+ }
139
+ }
140
+
141
+ #[cfg(target_os = "windows")]
142
+ {
143
+ window_builder = window_builder.additional_browser_args(&windows_browser_args);
144
+ }
145
+
146
+ #[cfg(all(not(target_os = "windows"), not(target_os = "macos")))]
147
+ {
148
+ window_builder = window_builder.additional_browser_args(&linux_browser_args);
149
+ }
150
+ }
151
+
152
+ // Set proxy after platform-specific configs (required for Windows/Linux)
153
+ if parsed_proxy_url.is_none() && !config.proxy_url.is_empty() {
154
+ if let Ok(proxy_url) = Url::from_str(&config.proxy_url) {
155
+ parsed_proxy_url = Some(proxy_url);
156
+ }
157
+ }
158
+
159
+ if let Some(proxy_url) = parsed_proxy_url {
160
+ window_builder = window_builder.proxy_url(proxy_url);
161
+ #[cfg(debug_assertions)]
162
+ println!("Proxy configured: {}", config.proxy_url);
97
163
  }
98
164
 
99
165
  window_builder.build().expect("Failed to build window")
@@ -24,6 +24,7 @@ pub fn run_app() {
24
24
  let hide_on_close = pake_config.windows[0].hide_on_close;
25
25
  let activation_shortcut = pake_config.windows[0].activation_shortcut.clone();
26
26
  let init_fullscreen = pake_config.windows[0].fullscreen;
27
+ let start_to_tray = pake_config.windows[0].start_to_tray && show_system_tray; // Only valid when tray is enabled
27
28
  let multi_instance = pake_config.multi_instance;
28
29
 
29
30
  let window_state_plugin = WindowStatePlugin::default()
@@ -62,15 +63,23 @@ pub fn run_app() {
62
63
  ])
63
64
  .setup(move |app| {
64
65
  let window = set_window(app, &pake_config, &tauri_config);
65
- set_system_tray(app.app_handle(), show_system_tray).unwrap();
66
+ set_system_tray(
67
+ app.app_handle(),
68
+ show_system_tray,
69
+ &pake_config.system_tray_path,
70
+ )
71
+ .unwrap();
66
72
  set_global_shortcut(app.app_handle(), activation_shortcut).unwrap();
67
73
 
68
74
  // Show window after state restoration to prevent position flashing
69
- let window_clone = window.clone();
70
- tauri::async_runtime::spawn(async move {
71
- tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
72
- window_clone.show().unwrap();
73
- });
75
+ // Unless start_to_tray is enabled, then keep it hidden
76
+ if !start_to_tray {
77
+ let window_clone = window.clone();
78
+ tauri::async_runtime::spawn(async move {
79
+ tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
80
+ window_clone.show().unwrap();
81
+ });
82
+ }
74
83
 
75
84
  Ok(())
76
85
  })