pake-cli 3.9.1 โ†’ 3.10.0

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
@@ -22,7 +22,7 @@ import * as psl from 'psl';
22
22
  import { InvalidArgumentError, program as program$1, Option } from 'commander';
23
23
 
24
24
  var name = "pake-cli";
25
- var version = "3.9.1";
25
+ var version = "3.10.0";
26
26
  var description = "๐Ÿคฑ๐Ÿป Turn any webpage into a desktop app with one command. ๐Ÿคฑ๐Ÿป ไธ€้”ฎๆ‰“ๅŒ…็ฝ‘้กต็”Ÿๆˆ่ฝป้‡ๆกŒ้ขๅบ”็”จใ€‚";
27
27
  var engines = {
28
28
  node: ">=18.0.0"
@@ -94,7 +94,7 @@ var devDependencies = {
94
94
  "@rollup/plugin-replace": "^6.0.3",
95
95
  "@rollup/plugin-terser": "^0.4.4",
96
96
  "@types/fs-extra": "^11.0.4",
97
- "@types/node": "^25.3.0",
97
+ "@types/node": "^25.3.2",
98
98
  "@types/page-icon": "^0.3.6",
99
99
  "@types/prompts": "^2.4.9",
100
100
  "@types/tmp": "^0.2.6",
@@ -102,7 +102,7 @@ var devDependencies = {
102
102
  "app-root-path": "^3.1.0",
103
103
  "cross-env": "^10.1.0",
104
104
  prettier: "^3.8.1",
105
- rollup: "^4.58.0",
105
+ rollup: "^4.59.0",
106
106
  "rollup-plugin-typescript2": "^0.36.0",
107
107
  tslib: "^2.8.1",
108
108
  typescript: "^5.9.3",
@@ -484,7 +484,7 @@ async function mergeConfig(url, options, tauriConf) {
484
484
  await fsExtra.copy(sourcePath, destPath);
485
485
  }
486
486
  }));
487
- const { width, height, fullscreen, maximize, hideTitleBar, alwaysOnTop, appVersion, darkMode, disabledWebShortcuts, activationShortcut, userAgent, showSystemTray, systemTrayIcon, useLocalFile, identifier, name = 'pake-app', resizable = true, inject, proxyUrl, installerLanguage, hideOnClose, incognito, title, wasm, enableDragDrop, multiInstance, startToTray, forceInternalNavigation, zoom, minWidth, minHeight, ignoreCertificateErrors, newWindow, } = options;
487
+ const { width, height, fullscreen, maximize, hideTitleBar, alwaysOnTop, appVersion, darkMode, disabledWebShortcuts, activationShortcut, userAgent, showSystemTray, systemTrayIcon, useLocalFile, identifier, name = 'pake-app', resizable = true, inject, proxyUrl, installerLanguage, hideOnClose, incognito, title, wasm, enableDragDrop, multiInstance, multiWindow, startToTray, forceInternalNavigation, internalUrlRegex, zoom, minWidth, minHeight, ignoreCertificateErrors, newWindow, } = options;
488
488
  const { platform } = process;
489
489
  const platformHideOnClose = hideOnClose ?? platform === 'darwin';
490
490
  const tauriConfWindowOptions = {
@@ -505,6 +505,7 @@ async function mergeConfig(url, options, tauriConf) {
505
505
  enable_drag_drop: enableDragDrop,
506
506
  start_to_tray: startToTray && showSystemTray,
507
507
  force_internal_navigation: forceInternalNavigation,
508
+ internal_url_regex: internalUrlRegex,
508
509
  zoom,
509
510
  min_width: minWidth,
510
511
  min_height: minHeight,
@@ -728,6 +729,7 @@ Terminal=false
728
729
  }
729
730
  tauriConf.pake.proxy_url = proxyUrl || '';
730
731
  tauriConf.pake.multi_instance = multiInstance;
732
+ tauriConf.pake.multi_window = multiWindow;
731
733
  // Configure WASM support with required HTTP headers
732
734
  if (wasm) {
733
735
  tauriConf.app.security = {
@@ -1397,6 +1399,108 @@ class BuilderProvider {
1397
1399
  }
1398
1400
  }
1399
1401
 
1402
+ const ICO_HEADER_SIZE = 6;
1403
+ const ICO_DIR_ENTRY_SIZE = 16;
1404
+ const ICO_TYPE_ICON = 1;
1405
+ function decodeDimension(value) {
1406
+ return value === 0 ? 256 : value;
1407
+ }
1408
+ function compareByPreferredSize(preferredSize) {
1409
+ return (a, b) => {
1410
+ const aSize = Math.max(a.width, a.height);
1411
+ const bSize = Math.max(b.width, b.height);
1412
+ const aExact = aSize === preferredSize ? 0 : 1;
1413
+ const bExact = bSize === preferredSize ? 0 : 1;
1414
+ if (aExact !== bExact)
1415
+ return aExact - bExact;
1416
+ const aDistance = Math.abs(aSize - preferredSize);
1417
+ const bDistance = Math.abs(bSize - preferredSize);
1418
+ if (aDistance !== bDistance)
1419
+ return aDistance - bDistance;
1420
+ const aSmaller = aSize < preferredSize ? 1 : 0;
1421
+ const bSmaller = bSize < preferredSize ? 1 : 0;
1422
+ if (aSmaller !== bSmaller)
1423
+ return aSmaller - bSmaller;
1424
+ if (a.bitCount !== b.bitCount)
1425
+ return b.bitCount - a.bitCount;
1426
+ if (aSize !== bSize)
1427
+ return bSize - aSize;
1428
+ return a.index - b.index;
1429
+ };
1430
+ }
1431
+ function parseIcoBuffer(buffer) {
1432
+ if (buffer.length < ICO_HEADER_SIZE) {
1433
+ throw new Error('Invalid ICO: header too short.');
1434
+ }
1435
+ const reserved = buffer.readUInt16LE(0);
1436
+ const type = buffer.readUInt16LE(2);
1437
+ const count = buffer.readUInt16LE(4);
1438
+ if (reserved !== 0 || type !== ICO_TYPE_ICON || count < 1) {
1439
+ throw new Error('Invalid ICO: invalid header.');
1440
+ }
1441
+ const tableSize = ICO_HEADER_SIZE + count * ICO_DIR_ENTRY_SIZE;
1442
+ if (buffer.length < tableSize) {
1443
+ throw new Error('Invalid ICO: directory table too short.');
1444
+ }
1445
+ const entries = [];
1446
+ for (let i = 0; i < count; i++) {
1447
+ const offset = ICO_HEADER_SIZE + i * ICO_DIR_ENTRY_SIZE;
1448
+ const widthByte = buffer.readUInt8(offset);
1449
+ const heightByte = buffer.readUInt8(offset + 1);
1450
+ const bitCount = buffer.readUInt16LE(offset + 6);
1451
+ const bytesInRes = buffer.readUInt32LE(offset + 8);
1452
+ const imageOffset = buffer.readUInt32LE(offset + 12);
1453
+ if (bytesInRes < 1 || imageOffset + bytesInRes > buffer.length) {
1454
+ throw new Error('Invalid ICO: frame out of bounds.');
1455
+ }
1456
+ entries.push({
1457
+ index: i,
1458
+ width: decodeDimension(widthByte),
1459
+ height: decodeDimension(heightByte),
1460
+ bitCount,
1461
+ bytesInRes,
1462
+ imageOffset,
1463
+ directory: buffer.subarray(offset, offset + ICO_DIR_ENTRY_SIZE),
1464
+ data: buffer.subarray(imageOffset, imageOffset + bytesInRes),
1465
+ });
1466
+ }
1467
+ return entries;
1468
+ }
1469
+ function buildReorderedIcoBuffer(buffer, preferredSize) {
1470
+ const entries = parseIcoBuffer(buffer);
1471
+ const ordered = [...entries].sort(compareByPreferredSize(preferredSize));
1472
+ const count = ordered.length;
1473
+ const tableSize = ICO_HEADER_SIZE + count * ICO_DIR_ENTRY_SIZE;
1474
+ const payloadSize = ordered.reduce((acc, entry) => acc + entry.data.length, 0);
1475
+ const output = Buffer.alloc(tableSize + payloadSize);
1476
+ output.writeUInt16LE(0, 0);
1477
+ output.writeUInt16LE(ICO_TYPE_ICON, 2);
1478
+ output.writeUInt16LE(count, 4);
1479
+ let currentOffset = tableSize;
1480
+ for (let i = 0; i < count; i++) {
1481
+ const entry = ordered[i];
1482
+ const entryOffset = ICO_HEADER_SIZE + i * ICO_DIR_ENTRY_SIZE;
1483
+ entry.directory.copy(output, entryOffset, 0, 8);
1484
+ output.writeUInt32LE(entry.data.length, entryOffset + 8);
1485
+ output.writeUInt32LE(currentOffset, entryOffset + 12);
1486
+ entry.data.copy(output, currentOffset);
1487
+ currentOffset += entry.data.length;
1488
+ }
1489
+ return output;
1490
+ }
1491
+ async function writeIcoWithPreferredSize(sourcePath, outputPath, preferredSize) {
1492
+ try {
1493
+ const sourceBuffer = await fsExtra.readFile(sourcePath);
1494
+ const reordered = buildReorderedIcoBuffer(sourceBuffer, preferredSize);
1495
+ await fsExtra.ensureDir(path.dirname(outputPath));
1496
+ await fsExtra.outputFile(outputPath, reordered);
1497
+ return true;
1498
+ }
1499
+ catch {
1500
+ return false;
1501
+ }
1502
+ }
1503
+
1400
1504
  const ICON_CONFIG = {
1401
1505
  minFileSize: 100,
1402
1506
  supportedFormats: ['png', 'ico', 'jpeg', 'jpg', 'webp', 'icns'],
@@ -1440,7 +1544,11 @@ async function copyWindowsIconIfNeeded(convertedPath, appName) {
1440
1544
  try {
1441
1545
  const finalIconPath = generateIconPath(appName);
1442
1546
  await fsExtra.ensureDir(path.dirname(finalIconPath));
1443
- await fsExtra.copy(convertedPath, finalIconPath);
1547
+ // Reorder ICO to prioritize 256px icons for better Windows display
1548
+ const reordered = await writeIcoWithPreferredSize(convertedPath, finalIconPath, 256);
1549
+ if (!reordered) {
1550
+ await fsExtra.copy(convertedPath, finalIconPath);
1551
+ }
1444
1552
  return finalIconPath;
1445
1553
  }
1446
1554
  catch (error) {
@@ -1933,8 +2041,10 @@ const DEFAULT_PAKE_OPTIONS = {
1933
2041
  enableDragDrop: false,
1934
2042
  keepBinary: false,
1935
2043
  multiInstance: false,
2044
+ multiWindow: false,
1936
2045
  startToTray: false,
1937
2046
  forceInternalNavigation: false,
2047
+ internalUrlRegex: '',
1938
2048
  iterativeBuild: false,
1939
2049
  zoom: 100,
1940
2050
  minWidth: 0,
@@ -2058,12 +2168,18 @@ ${green('|_| \\__,_|_|\\_\\___| can turn any webpage into a desktop app with
2058
2168
  .addOption(new Option('--multi-instance', 'Allow multiple app instances')
2059
2169
  .default(DEFAULT_PAKE_OPTIONS.multiInstance)
2060
2170
  .hideHelp())
2171
+ .addOption(new Option('--multi-window', 'Allow opening multiple windows within one app instance')
2172
+ .default(DEFAULT_PAKE_OPTIONS.multiWindow)
2173
+ .hideHelp())
2061
2174
  .addOption(new Option('--start-to-tray', 'Start app minimized to tray')
2062
2175
  .default(DEFAULT_PAKE_OPTIONS.startToTray)
2063
2176
  .hideHelp())
2064
2177
  .addOption(new Option('--force-internal-navigation', 'Keep every link inside the Pake window instead of opening external handlers')
2065
2178
  .default(DEFAULT_PAKE_OPTIONS.forceInternalNavigation)
2066
2179
  .hideHelp())
2180
+ .addOption(new Option('--internal-url-regex <string>', 'Regex pattern to match URLs that should be considered internal')
2181
+ .default(DEFAULT_PAKE_OPTIONS.internalUrlRegex)
2182
+ .hideHelp())
2067
2183
  .addOption(new Option('--installer-language <string>', 'Installer language')
2068
2184
  .default(DEFAULT_PAKE_OPTIONS.installerLanguage)
2069
2185
  .hideHelp())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pake-cli",
3
- "version": "3.9.1",
3
+ "version": "3.10.0",
4
4
  "description": "๐Ÿคฑ๐Ÿป Turn any webpage into a desktop app with one command. ๐Ÿคฑ๐Ÿป ไธ€้”ฎๆ‰“ๅŒ…็ฝ‘้กต็”Ÿๆˆ่ฝป้‡ๆกŒ้ขๅบ”็”จใ€‚",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -72,7 +72,7 @@
72
72
  "@rollup/plugin-replace": "^6.0.3",
73
73
  "@rollup/plugin-terser": "^0.4.4",
74
74
  "@types/fs-extra": "^11.0.4",
75
- "@types/node": "^25.3.0",
75
+ "@types/node": "^25.3.2",
76
76
  "@types/page-icon": "^0.3.6",
77
77
  "@types/prompts": "^2.4.9",
78
78
  "@types/tmp": "^0.2.6",
@@ -80,7 +80,7 @@
80
80
  "app-root-path": "^3.1.0",
81
81
  "cross-env": "^10.1.0",
82
82
  "prettier": "^3.8.1",
83
- "rollup": "^4.58.0",
83
+ "rollup": "^4.59.0",
84
84
  "rollup-plugin-typescript2": "^0.36.0",
85
85
  "tslib": "^2.8.1",
86
86
  "typescript": "^5.9.3",
@@ -443,9 +443,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
443
443
 
444
444
  [[package]]
445
445
  name = "chrono"
446
- version = "0.4.43"
446
+ version = "0.4.44"
447
447
  source = "registry+https://github.com/rust-lang/crates.io-index"
448
- checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118"
448
+ checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
449
449
  dependencies = [
450
450
  "iana-time-zone",
451
451
  "num-traits",
@@ -698,9 +698,9 @@ checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376"
698
698
 
699
699
  [[package]]
700
700
  name = "deranged"
701
- version = "0.5.7"
701
+ version = "0.5.8"
702
702
  source = "registry+https://github.com/rust-lang/crates.io-index"
703
- checksum = "2163a0e204a148662b6b6816d4b5d5668a5f2f8df498ccbd5cd0e864e78fecba"
703
+ checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
704
704
  dependencies = [
705
705
  "powerfmt",
706
706
  "serde_core",
@@ -758,9 +758,9 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
758
758
 
759
759
  [[package]]
760
760
  name = "dispatch2"
761
- version = "0.3.0"
761
+ version = "0.3.1"
762
762
  source = "registry+https://github.com/rust-lang/crates.io-index"
763
- checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
763
+ checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
764
764
  dependencies = [
765
765
  "bitflags 2.11.0",
766
766
  "objc2",
@@ -1937,9 +1937,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
1937
1937
 
1938
1938
  [[package]]
1939
1939
  name = "js-sys"
1940
- version = "0.3.87"
1940
+ version = "0.3.91"
1941
1941
  source = "registry+https://github.com/rust-lang/crates.io-index"
1942
- checksum = "93f0862381daaec758576dcc22eb7bbf4d7efd67328553f3b45a412a51a3fb21"
1942
+ checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c"
1943
1943
  dependencies = [
1944
1944
  "once_cell",
1945
1945
  "wasm-bindgen",
@@ -2054,9 +2054,9 @@ dependencies = [
2054
2054
 
2055
2055
  [[package]]
2056
2056
  name = "linux-raw-sys"
2057
- version = "0.11.0"
2057
+ version = "0.12.1"
2058
2058
  source = "registry+https://github.com/rust-lang/crates.io-index"
2059
- checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
2059
+ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
2060
2060
 
2061
2061
  [[package]]
2062
2062
  name = "litemap"
@@ -2308,9 +2308,9 @@ dependencies = [
2308
2308
 
2309
2309
  [[package]]
2310
2310
  name = "objc2"
2311
- version = "0.6.3"
2311
+ version = "0.6.4"
2312
2312
  source = "registry+https://github.com/rust-lang/crates.io-index"
2313
- checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
2313
+ checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
2314
2314
  dependencies = [
2315
2315
  "objc2-encode",
2316
2316
  "objc2-exception-helper",
@@ -2564,7 +2564,7 @@ dependencies = [
2564
2564
 
2565
2565
  [[package]]
2566
2566
  name = "pake"
2567
- version = "3.9.1"
2567
+ version = "3.10.0"
2568
2568
  dependencies = [
2569
2569
  "serde",
2570
2570
  "serde_json",
@@ -2783,9 +2783,9 @@ dependencies = [
2783
2783
 
2784
2784
  [[package]]
2785
2785
  name = "pin-project-lite"
2786
- version = "0.2.16"
2786
+ version = "0.2.17"
2787
2787
  source = "registry+https://github.com/rust-lang/crates.io-index"
2788
- checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
2788
+ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
2789
2789
 
2790
2790
  [[package]]
2791
2791
  name = "pin-utils"
@@ -2795,9 +2795,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
2795
2795
 
2796
2796
  [[package]]
2797
2797
  name = "piper"
2798
- version = "0.2.4"
2798
+ version = "0.2.5"
2799
2799
  source = "registry+https://github.com/rust-lang/crates.io-index"
2800
- checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
2800
+ checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1"
2801
2801
  dependencies = [
2802
2802
  "atomic-waker",
2803
2803
  "fastrand",
@@ -3265,9 +3265,9 @@ dependencies = [
3265
3265
 
3266
3266
  [[package]]
3267
3267
  name = "regex-syntax"
3268
- version = "0.8.9"
3268
+ version = "0.8.10"
3269
3269
  source = "registry+https://github.com/rust-lang/crates.io-index"
3270
- checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c"
3270
+ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
3271
3271
 
3272
3272
  [[package]]
3273
3273
  name = "reqwest"
@@ -3377,9 +3377,9 @@ dependencies = [
3377
3377
 
3378
3378
  [[package]]
3379
3379
  name = "rustix"
3380
- version = "1.1.3"
3380
+ version = "1.1.4"
3381
3381
  source = "registry+https://github.com/rust-lang/crates.io-index"
3382
- checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
3382
+ checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
3383
3383
  dependencies = [
3384
3384
  "bitflags 2.11.0",
3385
3385
  "errno",
@@ -3390,9 +3390,9 @@ dependencies = [
3390
3390
 
3391
3391
  [[package]]
3392
3392
  name = "rustls"
3393
- version = "0.23.36"
3393
+ version = "0.23.37"
3394
3394
  source = "registry+https://github.com/rust-lang/crates.io-index"
3395
- checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b"
3395
+ checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4"
3396
3396
  dependencies = [
3397
3397
  "once_cell",
3398
3398
  "ring",
@@ -3638,9 +3638,9 @@ dependencies = [
3638
3638
 
3639
3639
  [[package]]
3640
3640
  name = "serde_with"
3641
- version = "3.16.1"
3641
+ version = "3.17.0"
3642
3642
  source = "registry+https://github.com/rust-lang/crates.io-index"
3643
- checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7"
3643
+ checksum = "381b283ce7bc6b476d903296fb59d0d36633652b633b27f64db4fb46dcbfc3b9"
3644
3644
  dependencies = [
3645
3645
  "base64 0.22.1",
3646
3646
  "chrono",
@@ -3657,9 +3657,9 @@ dependencies = [
3657
3657
 
3658
3658
  [[package]]
3659
3659
  name = "serde_with_macros"
3660
- version = "3.16.1"
3660
+ version = "3.17.0"
3661
3661
  source = "registry+https://github.com/rust-lang/crates.io-index"
3662
- checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c"
3662
+ checksum = "a6d4e30573c8cb306ed6ab1dca8423eec9a463ea0e155f45399455e0368b27e0"
3663
3663
  dependencies = [
3664
3664
  "darling",
3665
3665
  "proc-macro2",
@@ -4448,9 +4448,9 @@ dependencies = [
4448
4448
 
4449
4449
  [[package]]
4450
4450
  name = "tempfile"
4451
- version = "3.25.0"
4451
+ version = "3.26.0"
4452
4452
  source = "registry+https://github.com/rust-lang/crates.io-index"
4453
- checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1"
4453
+ checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0"
4454
4454
  dependencies = [
4455
4455
  "fastrand",
4456
4456
  "getrandom 0.4.1",
@@ -5037,9 +5037,9 @@ dependencies = [
5037
5037
 
5038
5038
  [[package]]
5039
5039
  name = "wasm-bindgen"
5040
- version = "0.2.110"
5040
+ version = "0.2.114"
5041
5041
  source = "registry+https://github.com/rust-lang/crates.io-index"
5042
- checksum = "1de241cdc66a9d91bd84f097039eb140cdc6eec47e0cdbaf9d932a1dd6c35866"
5042
+ checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e"
5043
5043
  dependencies = [
5044
5044
  "cfg-if",
5045
5045
  "once_cell",
@@ -5050,9 +5050,9 @@ dependencies = [
5050
5050
 
5051
5051
  [[package]]
5052
5052
  name = "wasm-bindgen-futures"
5053
- version = "0.4.60"
5053
+ version = "0.4.64"
5054
5054
  source = "registry+https://github.com/rust-lang/crates.io-index"
5055
- checksum = "a42e96ea38f49b191e08a1bab66c7ffdba24b06f9995b39a9dd60222e5b6f1da"
5055
+ checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8"
5056
5056
  dependencies = [
5057
5057
  "cfg-if",
5058
5058
  "futures-util",
@@ -5064,9 +5064,9 @@ dependencies = [
5064
5064
 
5065
5065
  [[package]]
5066
5066
  name = "wasm-bindgen-macro"
5067
- version = "0.2.110"
5067
+ version = "0.2.114"
5068
5068
  source = "registry+https://github.com/rust-lang/crates.io-index"
5069
- checksum = "e12fdf6649048f2e3de6d7d5ff3ced779cdedee0e0baffd7dff5cdfa3abc8a52"
5069
+ checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6"
5070
5070
  dependencies = [
5071
5071
  "quote",
5072
5072
  "wasm-bindgen-macro-support",
@@ -5074,9 +5074,9 @@ dependencies = [
5074
5074
 
5075
5075
  [[package]]
5076
5076
  name = "wasm-bindgen-macro-support"
5077
- version = "0.2.110"
5077
+ version = "0.2.114"
5078
5078
  source = "registry+https://github.com/rust-lang/crates.io-index"
5079
- checksum = "0e63d1795c565ac3462334c1e396fd46dbf481c40f51f5072c310717bc4fb309"
5079
+ checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3"
5080
5080
  dependencies = [
5081
5081
  "bumpalo",
5082
5082
  "proc-macro2",
@@ -5087,9 +5087,9 @@ dependencies = [
5087
5087
 
5088
5088
  [[package]]
5089
5089
  name = "wasm-bindgen-shared"
5090
- version = "0.2.110"
5090
+ version = "0.2.114"
5091
5091
  source = "registry+https://github.com/rust-lang/crates.io-index"
5092
- checksum = "e9f9cdac23a5ce71f6bf9f8824898a501e511892791ea2a0c6b8568c68b9cb53"
5092
+ checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16"
5093
5093
  dependencies = [
5094
5094
  "unicode-ident",
5095
5095
  ]
@@ -5143,9 +5143,9 @@ dependencies = [
5143
5143
 
5144
5144
  [[package]]
5145
5145
  name = "web-sys"
5146
- version = "0.3.87"
5146
+ version = "0.3.91"
5147
5147
  source = "registry+https://github.com/rust-lang/crates.io-index"
5148
- checksum = "f2c7c5718134e770ee62af3b6b4a84518ec10101aad610c024b64d6ff29bb1ff"
5148
+ checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9"
5149
5149
  dependencies = [
5150
5150
  "js-sys",
5151
5151
  "wasm-bindgen",
@@ -5931,9 +5931,9 @@ dependencies = [
5931
5931
 
5932
5932
  [[package]]
5933
5933
  name = "zbus"
5934
- version = "5.13.2"
5934
+ version = "5.14.0"
5935
5935
  source = "registry+https://github.com/rust-lang/crates.io-index"
5936
- checksum = "1bfeff997a0aaa3eb20c4652baf788d2dfa6d2839a0ead0b3ff69ce2f9c4bdd1"
5936
+ checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc"
5937
5937
  dependencies = [
5938
5938
  "async-broadcast",
5939
5939
  "async-executor",
@@ -5966,9 +5966,9 @@ dependencies = [
5966
5966
 
5967
5967
  [[package]]
5968
5968
  name = "zbus_macros"
5969
- version = "5.13.2"
5969
+ version = "5.14.0"
5970
5970
  source = "registry+https://github.com/rust-lang/crates.io-index"
5971
- checksum = "0bbd5a90dbe8feee5b13def448427ae314ccd26a49cac47905cafefb9ff846f1"
5971
+ checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222"
5972
5972
  dependencies = [
5973
5973
  "proc-macro-crate 3.4.0",
5974
5974
  "proc-macro2",
@@ -5992,18 +5992,18 @@ dependencies = [
5992
5992
 
5993
5993
  [[package]]
5994
5994
  name = "zerocopy"
5995
- version = "0.8.39"
5995
+ version = "0.8.40"
5996
5996
  source = "registry+https://github.com/rust-lang/crates.io-index"
5997
- checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a"
5997
+ checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5"
5998
5998
  dependencies = [
5999
5999
  "zerocopy-derive",
6000
6000
  ]
6001
6001
 
6002
6002
  [[package]]
6003
6003
  name = "zerocopy-derive"
6004
- version = "0.8.39"
6004
+ version = "0.8.40"
6005
6005
  source = "registry+https://github.com/rust-lang/crates.io-index"
6006
- checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517"
6006
+ checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953"
6007
6007
  dependencies = [
6008
6008
  "proc-macro2",
6009
6009
  "quote",
@@ -6078,9 +6078,9 @@ checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
6078
6078
 
6079
6079
  [[package]]
6080
6080
  name = "zvariant"
6081
- version = "5.9.2"
6081
+ version = "5.10.0"
6082
6082
  source = "registry+https://github.com/rust-lang/crates.io-index"
6083
- checksum = "68b64ef4f40c7951337ddc7023dd03528a57a3ce3408ee9da5e948bd29b232c4"
6083
+ checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b"
6084
6084
  dependencies = [
6085
6085
  "endi",
6086
6086
  "enumflags2",
@@ -6092,9 +6092,9 @@ dependencies = [
6092
6092
 
6093
6093
  [[package]]
6094
6094
  name = "zvariant_derive"
6095
- version = "5.9.2"
6095
+ version = "5.10.0"
6096
6096
  source = "registry+https://github.com/rust-lang/crates.io-index"
6097
- checksum = "484d5d975eb7afb52cc6b929c13d3719a20ad650fea4120e6310de3fc55e415c"
6097
+ checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c"
6098
6098
  dependencies = [
6099
6099
  "proc-macro-crate 3.4.0",
6100
6100
  "proc-macro2",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "pake"
3
- version = "3.9.1"
3
+ version = "3.10.0"
4
4
  description = "๐Ÿคฑ๐Ÿป Turn any webpage into a desktop app with Rust."
5
5
  authors = ["Tw93"]
6
6
  license = "MIT"
@@ -19,6 +19,7 @@
19
19
  "maximize": false,
20
20
  "start_to_tray": false,
21
21
  "force_internal_navigation": false,
22
+ "internal_url_regex": "",
22
23
  "new_window": false
23
24
  }
24
25
  ],
@@ -35,5 +36,6 @@
35
36
  "system_tray_path": "icons/icon.png",
36
37
  "inject": [],
37
38
  "proxy_url": "",
38
- "multi_instance": false
39
+ "multi_instance": false,
40
+ "multi_window": false
39
41
  }
@@ -1,6 +1,6 @@
1
1
  use serde::{Deserialize, Serialize};
2
2
 
3
- #[derive(Debug, Serialize, Deserialize)]
3
+ #[derive(Clone, Debug, Serialize, Deserialize)]
4
4
  pub struct WindowConfig {
5
5
  pub url: String,
6
6
  pub hide_title_bar: bool,
@@ -24,6 +24,8 @@ pub struct WindowConfig {
24
24
  pub start_to_tray: bool,
25
25
  #[serde(default)]
26
26
  pub force_internal_navigation: bool,
27
+ #[serde(default)]
28
+ pub internal_url_regex: String,
27
29
  #[serde(default = "default_zoom")]
28
30
  pub zoom: u32,
29
31
  #[serde(default)]
@@ -38,7 +40,7 @@ fn default_zoom() -> u32 {
38
40
  100
39
41
  }
40
42
 
41
- #[derive(Debug, Serialize, Deserialize)]
43
+ #[derive(Clone, Debug, Serialize, Deserialize)]
42
44
  pub struct PlatformSpecific<T> {
43
45
  pub macos: T,
44
46
  pub linux: T,
@@ -70,7 +72,7 @@ where
70
72
  pub type UserAgent = PlatformSpecific<String>;
71
73
  pub type FunctionON = PlatformSpecific<bool>;
72
74
 
73
- #[derive(Debug, Serialize, Deserialize)]
75
+ #[derive(Clone, Debug, Serialize, Deserialize)]
74
76
  pub struct PakeConfig {
75
77
  pub windows: Vec<WindowConfig>,
76
78
  pub user_agent: UserAgent,
@@ -79,6 +81,8 @@ pub struct PakeConfig {
79
81
  pub proxy_url: String,
80
82
  #[serde(default)]
81
83
  pub multi_instance: bool,
84
+ #[serde(default)]
85
+ pub multi_window: bool,
82
86
  }
83
87
 
84
88
  impl PakeConfig {
@@ -1,11 +1,12 @@
1
1
  // Menu functionality is only used on macOS
2
2
  #![cfg(target_os = "macos")]
3
3
 
4
+ use crate::app::window::open_additional_window_safe;
4
5
  use tauri::menu::{AboutMetadata, Menu, MenuItem, PredefinedMenuItem, Submenu};
5
6
  use tauri::{AppHandle, Manager, Wry};
6
7
  use tauri_plugin_opener::OpenerExt;
7
8
 
8
- pub fn get_menu(app: &AppHandle<Wry>) -> tauri::Result<Menu<Wry>> {
9
+ pub fn get_menu(app: &AppHandle<Wry>, allow_multi_window: bool) -> tauri::Result<Menu<Wry>> {
9
10
  let pake_version = env!("CARGO_PKG_VERSION");
10
11
  let pake_menu_item_title = format!("Built with Pake V{}", pake_version);
11
12
 
@@ -13,7 +14,7 @@ pub fn get_menu(app: &AppHandle<Wry>) -> tauri::Result<Menu<Wry>> {
13
14
  app,
14
15
  &[
15
16
  &app_menu(app)?,
16
- &file_menu(app)?,
17
+ &file_menu(app, allow_multi_window)?,
17
18
  &edit_menu(app)?,
18
19
  &view_menu(app)?,
19
20
  &navigation_menu(app)?,
@@ -44,8 +45,18 @@ fn app_menu(app: &AppHandle<Wry>) -> tauri::Result<Submenu<Wry>> {
44
45
  Ok(app_menu)
45
46
  }
46
47
 
47
- fn file_menu(app: &AppHandle<Wry>) -> tauri::Result<Submenu<Wry>> {
48
+ fn file_menu(app: &AppHandle<Wry>, allow_multi_window: bool) -> tauri::Result<Submenu<Wry>> {
48
49
  let file_menu = Submenu::new(app, "File", true)?;
50
+ if allow_multi_window {
51
+ file_menu.append(&MenuItem::with_id(
52
+ app,
53
+ "new_window",
54
+ "New Window",
55
+ true,
56
+ Some("CmdOrCtrl+N"),
57
+ )?)?;
58
+ file_menu.append(&PredefinedMenuItem::separator(app)?)?;
59
+ }
49
60
  file_menu.append(&PredefinedMenuItem::close_window(app, None)?)?;
50
61
  file_menu.append(&PredefinedMenuItem::separator(app)?)?;
51
62
  file_menu.append(&MenuItem::with_id(
@@ -181,6 +192,9 @@ fn help_menu(app: &AppHandle<Wry>, title: &str) -> tauri::Result<Submenu<Wry>> {
181
192
 
182
193
  pub fn handle_menu_click(app_handle: &AppHandle, id: &str) {
183
194
  match id {
195
+ "new_window" => {
196
+ open_additional_window_safe(app_handle);
197
+ }
184
198
  "pake_github_link" => {
185
199
  let _ = app_handle
186
200
  .opener()
@@ -1,3 +1,4 @@
1
+ use crate::app::window::open_additional_window_safe;
1
2
  use std::str::FromStr;
2
3
  use std::sync::{Arc, Mutex};
3
4
  use std::time::{Duration, Instant};
@@ -14,25 +15,36 @@ pub fn set_system_tray(
14
15
  show_system_tray: bool,
15
16
  tray_icon_path: &str,
16
17
  _init_fullscreen: bool,
18
+ allow_multi_window: bool,
17
19
  ) -> tauri::Result<()> {
18
20
  if !show_system_tray {
19
21
  app.remove_tray_by_id("pake-tray");
20
22
  return Ok(());
21
23
  }
22
24
 
25
+ let new_window = MenuItemBuilder::with_id("new_window", "New Window").build(app)?;
23
26
  let hide_app = MenuItemBuilder::with_id("hide_app", "Hide").build(app)?;
24
27
  let show_app = MenuItemBuilder::with_id("show_app", "Show").build(app)?;
25
28
  let quit = MenuItemBuilder::with_id("quit", "Quit").build(app)?;
26
29
 
27
- let menu = MenuBuilder::new(app)
28
- .items(&[&hide_app, &show_app, &quit])
29
- .build()?;
30
+ let menu = if allow_multi_window {
31
+ MenuBuilder::new(app)
32
+ .items(&[&new_window, &hide_app, &show_app, &quit])
33
+ .build()?
34
+ } else {
35
+ MenuBuilder::new(app)
36
+ .items(&[&hide_app, &show_app, &quit])
37
+ .build()?
38
+ };
30
39
 
31
40
  app.app_handle().remove_tray_by_id("pake-tray");
32
41
 
33
42
  let tray = TrayIconBuilder::new()
34
43
  .menu(&menu)
35
44
  .on_menu_event(move |app, event| match event.id().as_ref() {
45
+ "new_window" => {
46
+ open_additional_window_safe(app);
47
+ }
36
48
  "hide_app" => {
37
49
  if let Some(window) = app.get_webview_window("pake") {
38
50
  window.minimize().unwrap();
@@ -1,7 +1,7 @@
1
1
  use crate::app::config::PakeConfig;
2
2
  use crate::util::get_data_dir;
3
- use std::{path::PathBuf, str::FromStr};
4
- use tauri::{App, Config, Url, WebviewUrl, WebviewWindow, WebviewWindowBuilder};
3
+ use std::{path::PathBuf, str::FromStr, sync::Mutex};
4
+ use tauri::{AppHandle, Config, Manager, Url, WebviewUrl, WebviewWindow, WebviewWindowBuilder};
5
5
 
6
6
  #[cfg(target_os = "macos")]
7
7
  use tauri::{Theme, TitleBarStyle};
@@ -22,9 +22,67 @@ fn build_proxy_browser_arg(url: &Url) -> Option<String> {
22
22
  }
23
23
  }
24
24
 
25
- pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) -> WebviewWindow {
25
+ pub struct MultiWindowState {
26
+ pub pake_config: PakeConfig,
27
+ pub tauri_config: Config,
28
+ next_window_index: Mutex<u32>,
29
+ }
30
+
31
+ impl MultiWindowState {
32
+ pub fn new(pake_config: PakeConfig, tauri_config: Config) -> Self {
33
+ Self {
34
+ pake_config,
35
+ tauri_config,
36
+ next_window_index: Mutex::new(0),
37
+ }
38
+ }
39
+
40
+ fn next_window_label(&self) -> String {
41
+ let mut index = self.next_window_index.lock().unwrap();
42
+ *index += 1;
43
+ format!("pake-{}", *index)
44
+ }
45
+ }
46
+
47
+ pub fn set_window(app: &AppHandle, config: &PakeConfig, tauri_config: &Config) -> WebviewWindow {
48
+ build_window_with_label(app, config, tauri_config, "pake").expect("Failed to build window")
49
+ }
50
+
51
+ pub fn open_additional_window(app: &AppHandle) -> tauri::Result<WebviewWindow> {
52
+ let state = app.state::<MultiWindowState>();
53
+ let label = state.next_window_label();
54
+ build_window_with_label(app, &state.pake_config, &state.tauri_config, &label)
55
+ }
56
+
57
+ pub fn open_additional_window_safe(app: &AppHandle) {
58
+ #[cfg(target_os = "windows")]
59
+ {
60
+ let app_handle = app.clone();
61
+ std::thread::spawn(move || {
62
+ if let Ok(window) = open_additional_window(&app_handle) {
63
+ let _ = window.show();
64
+ let _ = window.set_focus();
65
+ }
66
+ });
67
+ }
68
+
69
+ #[cfg(not(target_os = "windows"))]
70
+ {
71
+ if let Ok(window) = open_additional_window(app) {
72
+ let _ = window.show();
73
+ let _ = window.set_focus();
74
+ }
75
+ }
76
+ }
77
+
78
+ fn build_window_with_label(
79
+ app: &AppHandle,
80
+ config: &PakeConfig,
81
+ tauri_config: &Config,
82
+ label: &str,
83
+ ) -> tauri::Result<WebviewWindow> {
26
84
  let package_name = tauri_config.clone().product_name.unwrap();
27
- let _data_dir = get_data_dir(app.handle(), package_name);
85
+ let _data_dir = get_data_dir(app, package_name);
28
86
 
29
87
  let window_config = config
30
88
  .windows
@@ -53,7 +111,7 @@ pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) ->
53
111
  }
54
112
  });
55
113
 
56
- let mut window_builder = WebviewWindowBuilder::new(app, "pake", url)
114
+ let mut window_builder = WebviewWindowBuilder::new(app, label, url)
57
115
  .title(effective_title)
58
116
  .visible(false)
59
117
  .user_agent(user_agent)
@@ -269,5 +327,5 @@ pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) ->
269
327
  true
270
328
  });
271
329
 
272
- window_builder.build().expect("Failed to build window")
330
+ window_builder.build()
273
331
  }
@@ -262,6 +262,15 @@ document.addEventListener("DOMContentLoaded", () => {
262
262
  const invoke = tauri.core.invoke;
263
263
  const pakeConfig = window["pakeConfig"] || {};
264
264
  const forceInternalNavigation = pakeConfig.force_internal_navigation === true;
265
+ const internalUrlRegex = pakeConfig.internal_url_regex || "";
266
+ let internalUrlPattern = null;
267
+ if (internalUrlRegex) {
268
+ try {
269
+ internalUrlPattern = new RegExp(internalUrlRegex);
270
+ } catch (e) {
271
+ console.error("[Pake] Invalid internal_url_regex pattern:", e);
272
+ }
273
+ }
265
274
 
266
275
  if (!document.getElementById("pake-top-dom")) {
267
276
  const topDom = document.createElement("div");
@@ -465,6 +474,22 @@ document.addEventListener("DOMContentLoaded", () => {
465
474
  }
466
475
  };
467
476
 
477
+ // Check if URL should be treated as internal based on regex pattern or domain
478
+ const isInternalUrl = (url) => {
479
+ // If regex pattern is configured, use it as the primary check
480
+ if (internalUrlPattern) {
481
+ try {
482
+ return internalUrlPattern.test(url);
483
+ } catch (e) {
484
+ console.error("[Pake] Error testing internal_url_regex:", e);
485
+ // Fall back to domain check on error
486
+ return isSameDomain(url);
487
+ }
488
+ }
489
+ // Default to domain-based check
490
+ return isSameDomain(url);
491
+ };
492
+
468
493
  const detectAnchorElementClick = (e) => {
469
494
  // Safety check: ensure e.target exists and is an Element with closest method
470
495
  if (!e.target || typeof e.target.closest !== "function") {
@@ -493,8 +518,8 @@ document.addEventListener("DOMContentLoaded", () => {
493
518
  return;
494
519
  }
495
520
 
496
- if (isSameDomain(absoluteUrl)) {
497
- // For same-domain links, let the browser handle it naturally
521
+ if (isInternalUrl(absoluteUrl)) {
522
+ // For internal links (based on regex or domain), let the browser handle it naturally
498
523
  return;
499
524
  }
500
525
 
@@ -537,7 +562,7 @@ document.addEventListener("DOMContentLoaded", () => {
537
562
  return;
538
563
  }
539
564
 
540
- // Handle regular links: same domain allows normal navigation, cross-domain opens new window
565
+ // Handle regular links: internal URLs allow normal navigation, external opens new window
541
566
  if (!target || target === "_self") {
542
567
  // Optimization: Allow previewable media to be handled by the app/browser directly
543
568
  // This fixes issues where CDN links are treated as external
@@ -545,7 +570,7 @@ document.addEventListener("DOMContentLoaded", () => {
545
570
  return;
546
571
  }
547
572
 
548
- if (!isSameDomain(absoluteUrl)) {
573
+ if (!isInternalUrl(absoluteUrl)) {
549
574
  if (forceInternalNavigation) {
550
575
  return;
551
576
  }
@@ -583,7 +608,7 @@ document.addEventListener("DOMContentLoaded", () => {
583
608
  const hrefUrl = new URL(url, baseUrl);
584
609
  const absoluteUrl = hrefUrl.href;
585
610
 
586
- if (!isSameDomain(absoluteUrl)) {
611
+ if (!isInternalUrl(absoluteUrl)) {
587
612
  if (forceInternalNavigation) {
588
613
  return originalWindowOpen.call(window, absoluteUrl, name, specs);
589
614
  }
@@ -17,7 +17,7 @@ use app::{
17
17
  update_theme_mode,
18
18
  },
19
19
  setup::{set_global_shortcut, set_system_tray},
20
- window::set_window,
20
+ window::{open_additional_window_safe, set_window, MultiWindowState},
21
21
  };
22
22
  use util::get_pake_config;
23
23
 
@@ -38,6 +38,7 @@ pub fn run_app() {
38
38
  let init_fullscreen = pake_config.windows[0].fullscreen;
39
39
  let start_to_tray = pake_config.windows[0].start_to_tray && show_system_tray; // Only valid when tray is enabled
40
40
  let multi_instance = pake_config.multi_instance;
41
+ let multi_window = pake_config.multi_window;
41
42
 
42
43
  let window_state_plugin = WindowStatePlugin::default()
43
44
  .with_state_flags(if init_fullscreen {
@@ -59,13 +60,17 @@ pub fn run_app() {
59
60
 
60
61
  // Only add single instance plugin if multiple instances are not allowed
61
62
  if !multi_instance {
62
- app_builder = app_builder.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
63
- if let Some(window) = app.get_webview_window("pake") {
64
- let _ = window.unminimize();
65
- let _ = window.show();
66
- let _ = window.set_focus();
67
- }
68
- }));
63
+ app_builder = app_builder.plugin(tauri_plugin_single_instance::init(
64
+ move |app, _args, _cwd| {
65
+ if multi_window {
66
+ open_additional_window_safe(app);
67
+ } else if let Some(window) = app.get_webview_window("pake") {
68
+ let _ = window.unminimize();
69
+ let _ = window.show();
70
+ let _ = window.set_focus();
71
+ }
72
+ },
73
+ ));
69
74
  }
70
75
 
71
76
  app_builder
@@ -77,10 +82,15 @@ pub fn run_app() {
77
82
  clear_cache_and_restart,
78
83
  ])
79
84
  .setup(move |app| {
85
+ app.manage(MultiWindowState::new(
86
+ pake_config.clone(),
87
+ tauri_config.clone(),
88
+ ));
89
+
80
90
  // --- Menu Construction Start ---
81
91
  #[cfg(target_os = "macos")]
82
92
  {
83
- let menu = app::menu::get_menu(app.app_handle())?;
93
+ let menu = app::menu::get_menu(app.app_handle(), multi_window)?;
84
94
  app.set_menu(menu)?;
85
95
 
86
96
  // Event Handling for Custom Menu Item
@@ -90,12 +100,13 @@ pub fn run_app() {
90
100
  }
91
101
  // --- Menu Construction End ---
92
102
 
93
- let window = set_window(app, &pake_config, &tauri_config);
103
+ let window = set_window(app.app_handle(), &pake_config, &tauri_config);
94
104
  set_system_tray(
95
105
  app.app_handle(),
96
106
  show_system_tray,
97
107
  &pake_config.system_tray_path,
98
108
  init_fullscreen,
109
+ multi_window,
99
110
  )
100
111
  .unwrap();
101
112
  set_global_shortcut(app.app_handle(), activation_shortcut, init_fullscreen).unwrap();
@@ -130,7 +141,7 @@ pub fn run_app() {
130
141
  })
131
142
  .on_window_event(move |_window, _event| {
132
143
  if let tauri::WindowEvent::CloseRequested { api, .. } = _event {
133
- if hide_on_close {
144
+ if hide_on_close && _window.label() == "pake" {
134
145
  // Hide window when hide_on_close is enabled (regardless of tray status)
135
146
  let window = _window.clone();
136
147
  tauri::async_runtime::spawn(async move {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "productName": "Weekly",
3
3
  "identifier": "com.pake.weekly",
4
- "version": "1.0.0",
4
+ "version": "3.10.0",
5
5
  "app": {
6
6
  "withGlobalTauri": true,
7
7
  "trayIcon": {
@@ -1,43 +0,0 @@
1
- {
2
- "windows": [
3
- {
4
- "url": "https://twitter.com/",
5
- "url_type": "web",
6
- "hide_title_bar": false,
7
- "fullscreen": false,
8
- "width": 1200,
9
- "height": 780,
10
- "resizable": true,
11
- "always_on_top": false,
12
- "dark_mode": false,
13
- "activation_shortcut": "",
14
- "disabled_web_shortcuts": false,
15
- "hide_on_close": true,
16
- "incognito": false,
17
- "enable_wasm": false,
18
- "enable_drag_drop": false,
19
- "maximize": false,
20
- "start_to_tray": false,
21
- "force_internal_navigation": false,
22
- "new_window": false,
23
- "zoom": 100,
24
- "min_width": 0,
25
- "min_height": 0,
26
- "ignore_certificate_errors": false
27
- }
28
- ],
29
- "user_agent": {
30
- "macos": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Safari/605.1.15",
31
- "linux": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
32
- "windows": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36"
33
- },
34
- "system_tray": {
35
- "macos": false,
36
- "linux": true,
37
- "windows": true
38
- },
39
- "system_tray_path": "png/icon_512.png",
40
- "inject": [],
41
- "proxy_url": "",
42
- "multi_instance": false
43
- }
@@ -1,44 +0,0 @@
1
- {
2
- "productName": "twitter",
3
- "identifier": "com.pake.4fd9c9",
4
- "version": "1.0.0",
5
- "app": {
6
- "withGlobalTauri": true,
7
- "security": {
8
- "headers": {},
9
- "csp": null
10
- }
11
- },
12
- "build": {
13
- "frontendDist": "../dist"
14
- },
15
- "bundle": {
16
- "icon": [
17
- "icons/icon.icns"
18
- ],
19
- "active": true,
20
- "targets": [
21
- "app"
22
- ],
23
- "macOS": {
24
- "signingIdentity": "-",
25
- "hardenedRuntime": true,
26
- "dmg": {
27
- "background": "assets/macos/dmg/background.png",
28
- "windowSize": {
29
- "width": 680,
30
- "height": 420
31
- },
32
- "appPosition": {
33
- "x": 190,
34
- "y": 250
35
- },
36
- "applicationFolderPosition": {
37
- "x": 500,
38
- "y": 250
39
- }
40
- }
41
- }
42
- },
43
- "mainBinaryName": "pake-twitter"
44
- }
@@ -1,12 +0,0 @@
1
- {
2
- "bundle": {
3
- "icon": ["png/weekly_512.png"],
4
- "active": true,
5
- "linux": {
6
- "deb": {
7
- "depends": ["curl", "wget"]
8
- }
9
- },
10
- "targets": ["deb", "appimage"]
11
- }
12
- }
@@ -1,30 +0,0 @@
1
- {
2
- "bundle": {
3
- "icon": [
4
- "icons/icon.icns"
5
- ],
6
- "active": true,
7
- "targets": [
8
- "app"
9
- ],
10
- "macOS": {
11
- "signingIdentity": "-",
12
- "hardenedRuntime": true,
13
- "dmg": {
14
- "background": "assets/macos/dmg/background.png",
15
- "windowSize": {
16
- "width": 680,
17
- "height": 420
18
- },
19
- "appPosition": {
20
- "x": 190,
21
- "y": 250
22
- },
23
- "applicationFolderPosition": {
24
- "x": 500,
25
- "y": 250
26
- }
27
- }
28
- }
29
- }
30
- }
@@ -1,15 +0,0 @@
1
- {
2
- "bundle": {
3
- "icon": ["png/weekly_256.ico", "png/weekly_32.ico"],
4
- "active": true,
5
- "resources": ["png/weekly_32.ico"],
6
- "targets": ["msi"],
7
- "windows": {
8
- "digestAlgorithm": "sha256",
9
- "wix": {
10
- "language": ["en-US"],
11
- "template": "assets/main.wxs"
12
- }
13
- }
14
- }
15
- }