pake-cli 3.3.6 โ 3.4.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/README.md +12 -4
- package/dist/cli.js +121 -30
- package/package.json +7 -7
- package/src-tauri/.pake/pake.json +2 -1
- package/src-tauri/Cargo.lock +18 -7
- package/src-tauri/Cargo.toml +5 -5
- package/src-tauri/pake.json +2 -1
- package/src-tauri/src/app/config.rs +2 -0
- package/src-tauri/src/inject/event.js +82 -77
- package/src-tauri/src/lib.rs +11 -4
- package/src-tauri/.cargo/config.toml +0 -10
package/README.md
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
- **Beginners**: Download ready-made [Popular Packages](#popular-packages) or use [Online Building](docs/github-actions-usage.md) with no environment setup required
|
|
30
30
|
- **Developers**: Install [CLI Tool](docs/cli-usage.md) for one-command packaging of any website with customizable icons, window settings, and more
|
|
31
31
|
- **Advanced Users**: Clone the project locally for [Custom Development](#development), or check [Advanced Usage](docs/advanced-usage.md) for style customization and feature enhancement
|
|
32
|
+
- **Troubleshooting**: Check [FAQ](docs/faq.md) for common issues and solutions
|
|
32
33
|
|
|
33
34
|
## Popular Packages
|
|
34
35
|
|
|
@@ -434,6 +435,13 @@ Pake's development can not be without these Hackers. They contributed a lot of c
|
|
|
434
435
|
<sub><b>Jiaqi Gu</b></sub>
|
|
435
436
|
</a>
|
|
436
437
|
</td>
|
|
438
|
+
<td align="center">
|
|
439
|
+
<a href="https://github.com/JohannLai">
|
|
440
|
+
<img src="https://avatars.githubusercontent.com/u/10769405?v=4" width="90;" alt="JohannLai"/>
|
|
441
|
+
<br />
|
|
442
|
+
<sub><b>Johannlai</b></sub>
|
|
443
|
+
</a>
|
|
444
|
+
</td>
|
|
437
445
|
<td align="center">
|
|
438
446
|
<a href="https://github.com/Jason6987">
|
|
439
447
|
<img src="https://avatars.githubusercontent.com/u/140222795?v=4" width="90;" alt="Jason6987"/>
|
|
@@ -441,6 +449,8 @@ Pake's development can not be without these Hackers. They contributed a lot of c
|
|
|
441
449
|
<sub><b>Luminall</b></sub>
|
|
442
450
|
</a>
|
|
443
451
|
</td>
|
|
452
|
+
</tr>
|
|
453
|
+
<tr>
|
|
444
454
|
<td align="center">
|
|
445
455
|
<a href="https://github.com/Milo123459">
|
|
446
456
|
<img src="https://avatars.githubusercontent.com/u/50248166?v=4" width="90;" alt="Milo123459"/>
|
|
@@ -448,8 +458,6 @@ Pake's development can not be without these Hackers. They contributed a lot of c
|
|
|
448
458
|
<sub><b>Milo</b></sub>
|
|
449
459
|
</a>
|
|
450
460
|
</td>
|
|
451
|
-
</tr>
|
|
452
|
-
<tr>
|
|
453
461
|
<td align="center">
|
|
454
462
|
<a href="https://github.com/princemaple">
|
|
455
463
|
<img src="https://avatars.githubusercontent.com/u/1329716?v=4" width="90;" alt="princemaple"/>
|
|
@@ -492,6 +500,8 @@ Pake's development can not be without these Hackers. They contributed a lot of c
|
|
|
492
500
|
<sub><b>Null</b></sub>
|
|
493
501
|
</a>
|
|
494
502
|
</td>
|
|
503
|
+
</tr>
|
|
504
|
+
<tr>
|
|
495
505
|
<td align="center">
|
|
496
506
|
<a href="https://github.com/liudonghua123">
|
|
497
507
|
<img src="https://avatars.githubusercontent.com/u/2276718?v=4" width="90;" alt="liudonghua123"/>
|
|
@@ -499,8 +509,6 @@ Pake's development can not be without these Hackers. They contributed a lot of c
|
|
|
499
509
|
<sub><b>Liudonghua</b></sub>
|
|
500
510
|
</a>
|
|
501
511
|
</td>
|
|
502
|
-
</tr>
|
|
503
|
-
<tr>
|
|
504
512
|
<td align="center">
|
|
505
513
|
<a href="https://github.com/liusishan">
|
|
506
514
|
<img src="https://avatars.githubusercontent.com/u/33129823?v=4" width="90;" alt="liusishan"/>
|
package/dist/cli.js
CHANGED
|
@@ -6,6 +6,7 @@ import path from 'path';
|
|
|
6
6
|
import fsExtra from 'fs-extra';
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
8
|
import prompts from 'prompts';
|
|
9
|
+
import os from 'os';
|
|
9
10
|
import { execa, execaSync } from 'execa';
|
|
10
11
|
import crypto from 'crypto';
|
|
11
12
|
import ora from 'ora';
|
|
@@ -22,7 +23,7 @@ import sharp from 'sharp';
|
|
|
22
23
|
import * as psl from 'psl';
|
|
23
24
|
|
|
24
25
|
var name = "pake-cli";
|
|
25
|
-
var version = "3.
|
|
26
|
+
var version = "3.4.0";
|
|
26
27
|
var description = "๐คฑ๐ป Turn any webpage into a desktop app with one command. ๐คฑ๐ป ไธ้ฎๆๅ
็ฝ้กต็ๆ่ฝป้ๆก้ขๅบ็จใ";
|
|
27
28
|
var engines = {
|
|
28
29
|
node: ">=18.0.0"
|
|
@@ -74,12 +75,12 @@ var license = "MIT";
|
|
|
74
75
|
var dependencies = {
|
|
75
76
|
"@tauri-apps/api": "^2.8.0",
|
|
76
77
|
"@tauri-apps/cli": "^2.8.4",
|
|
77
|
-
axios: "^1.
|
|
78
|
-
chalk: "^5.6.
|
|
78
|
+
axios: "^1.12.2",
|
|
79
|
+
chalk: "^5.6.2",
|
|
79
80
|
commander: "^12.1.0",
|
|
80
81
|
execa: "^9.6.0",
|
|
81
82
|
"file-type": "^18.7.0",
|
|
82
|
-
"fs-extra": "^11.3.
|
|
83
|
+
"fs-extra": "^11.3.2",
|
|
83
84
|
"icon-gen": "^5.0.0",
|
|
84
85
|
loglevel: "^1.9.2",
|
|
85
86
|
ora: "^8.2.0",
|
|
@@ -96,7 +97,7 @@ var devDependencies = {
|
|
|
96
97
|
"@rollup/plugin-replace": "^6.0.2",
|
|
97
98
|
"@rollup/plugin-terser": "^0.4.4",
|
|
98
99
|
"@types/fs-extra": "^11.0.4",
|
|
99
|
-
"@types/node": "^20.19.
|
|
100
|
+
"@types/node": "^20.19.21",
|
|
100
101
|
"@types/page-icon": "^0.3.6",
|
|
101
102
|
"@types/prompts": "^2.4.9",
|
|
102
103
|
"@types/tmp": "^0.2.6",
|
|
@@ -104,10 +105,10 @@ var devDependencies = {
|
|
|
104
105
|
"app-root-path": "^3.1.0",
|
|
105
106
|
"cross-env": "^7.0.3",
|
|
106
107
|
prettier: "^3.6.2",
|
|
107
|
-
rollup: "^4.
|
|
108
|
+
rollup: "^4.52.4",
|
|
108
109
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
109
110
|
tslib: "^2.8.1",
|
|
110
|
-
typescript: "^5.9.
|
|
111
|
+
typescript: "^5.9.3"
|
|
111
112
|
};
|
|
112
113
|
var packageJson = {
|
|
113
114
|
name: name,
|
|
@@ -200,11 +201,11 @@ const IS_MAC = platform$1 === 'darwin';
|
|
|
200
201
|
const IS_WIN = platform$1 === 'win32';
|
|
201
202
|
const IS_LINUX = platform$1 === 'linux';
|
|
202
203
|
|
|
203
|
-
async function shellExec(command, timeout = 300000, env) {
|
|
204
|
+
async function shellExec(command, timeout = 300000, env, showOutput = false) {
|
|
204
205
|
try {
|
|
205
206
|
const { exitCode } = await execa(command, {
|
|
206
207
|
cwd: npmDirectory,
|
|
207
|
-
stdio: ['inherit', 'pipe', 'inherit'],
|
|
208
|
+
stdio: showOutput ? 'inherit' : ['inherit', 'pipe', 'inherit'],
|
|
208
209
|
shell: true,
|
|
209
210
|
timeout,
|
|
210
211
|
env: env ? { ...process.env, ...env } : process.env,
|
|
@@ -217,7 +218,18 @@ async function shellExec(command, timeout = 300000, env) {
|
|
|
217
218
|
if (error.timedOut) {
|
|
218
219
|
throw new Error(`Command timed out after ${timeout}ms: "${command}". Try increasing timeout or check network connectivity.`);
|
|
219
220
|
}
|
|
220
|
-
|
|
221
|
+
let errorMsg = `Error occurred while executing command "${command}". Exit code: ${exitCode}. Details: ${errorMessage}`;
|
|
222
|
+
if (process.platform === 'linux' &&
|
|
223
|
+
(errorMessage.includes('linuxdeploy') ||
|
|
224
|
+
errorMessage.includes('appimage') ||
|
|
225
|
+
errorMessage.includes('strip'))) {
|
|
226
|
+
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';
|
|
231
|
+
}
|
|
232
|
+
throw new Error(errorMsg);
|
|
221
233
|
}
|
|
222
234
|
}
|
|
223
235
|
|
|
@@ -284,6 +296,52 @@ async function isChinaIP(ip, domain) {
|
|
|
284
296
|
}
|
|
285
297
|
}
|
|
286
298
|
|
|
299
|
+
function normalizePathForComparison(targetPath) {
|
|
300
|
+
const normalized = path.normalize(targetPath);
|
|
301
|
+
return IS_WIN ? normalized.toLowerCase() : normalized;
|
|
302
|
+
}
|
|
303
|
+
function getCargoHomeCandidates() {
|
|
304
|
+
const candidates = new Set();
|
|
305
|
+
if (process.env.CARGO_HOME) {
|
|
306
|
+
candidates.add(process.env.CARGO_HOME);
|
|
307
|
+
}
|
|
308
|
+
const homeDir = os.homedir();
|
|
309
|
+
if (homeDir) {
|
|
310
|
+
candidates.add(path.join(homeDir, '.cargo'));
|
|
311
|
+
}
|
|
312
|
+
if (IS_WIN && process.env.USERPROFILE) {
|
|
313
|
+
candidates.add(path.join(process.env.USERPROFILE, '.cargo'));
|
|
314
|
+
}
|
|
315
|
+
return Array.from(candidates).filter(Boolean);
|
|
316
|
+
}
|
|
317
|
+
function ensureCargoBinOnPath() {
|
|
318
|
+
const currentPath = process.env.PATH || '';
|
|
319
|
+
const segments = currentPath.split(path.delimiter).filter(Boolean);
|
|
320
|
+
const normalizedSegments = new Set(segments.map((segment) => normalizePathForComparison(segment)));
|
|
321
|
+
const additions = [];
|
|
322
|
+
let cargoHomeSet = Boolean(process.env.CARGO_HOME);
|
|
323
|
+
for (const cargoHome of getCargoHomeCandidates()) {
|
|
324
|
+
const binDir = path.join(cargoHome, 'bin');
|
|
325
|
+
if (fsExtra.pathExistsSync(binDir) &&
|
|
326
|
+
!normalizedSegments.has(normalizePathForComparison(binDir))) {
|
|
327
|
+
additions.push(binDir);
|
|
328
|
+
normalizedSegments.add(normalizePathForComparison(binDir));
|
|
329
|
+
}
|
|
330
|
+
if (!cargoHomeSet && fsExtra.pathExistsSync(cargoHome)) {
|
|
331
|
+
process.env.CARGO_HOME = cargoHome;
|
|
332
|
+
cargoHomeSet = true;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (additions.length) {
|
|
336
|
+
const prefix = additions.join(path.delimiter);
|
|
337
|
+
process.env.PATH = segments.length
|
|
338
|
+
? `${prefix}${path.delimiter}${segments.join(path.delimiter)}`
|
|
339
|
+
: prefix;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
function ensureRustEnv() {
|
|
343
|
+
ensureCargoBinOnPath();
|
|
344
|
+
}
|
|
287
345
|
async function installRust() {
|
|
288
346
|
const isActions = process.env.GITHUB_ACTIONS;
|
|
289
347
|
const isInChina = await isChinaDomain('sh.rustup.rs');
|
|
@@ -293,8 +351,9 @@ async function installRust() {
|
|
|
293
351
|
const rustInstallScriptForWindows = 'winget install --id Rustlang.Rustup';
|
|
294
352
|
const spinner = getSpinner('Downloading Rust...');
|
|
295
353
|
try {
|
|
296
|
-
await shellExec(IS_WIN ? rustInstallScriptForWindows : rustInstallScriptForMac);
|
|
354
|
+
await shellExec(IS_WIN ? rustInstallScriptForWindows : rustInstallScriptForMac, 300000, undefined, true);
|
|
297
355
|
spinner.succeed(chalk.green('โ Rust installed successfully!'));
|
|
356
|
+
ensureRustEnv();
|
|
298
357
|
}
|
|
299
358
|
catch (error) {
|
|
300
359
|
spinner.fail(chalk.red('โ Rust installation failed!'));
|
|
@@ -303,6 +362,7 @@ async function installRust() {
|
|
|
303
362
|
}
|
|
304
363
|
}
|
|
305
364
|
function checkRustInstalled() {
|
|
365
|
+
ensureCargoBinOnPath();
|
|
306
366
|
try {
|
|
307
367
|
execaSync('rustc', ['--version']);
|
|
308
368
|
return true;
|
|
@@ -343,11 +403,31 @@ function generateLinuxPackageName(name) {
|
|
|
343
403
|
.replace(/-+/g, '-');
|
|
344
404
|
}
|
|
345
405
|
function generateIdentifierSafeName(name) {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
.
|
|
406
|
+
const cleaned = name.replace(/[^a-zA-Z0-9\u4e00-\u9fff]/g, '').toLowerCase();
|
|
407
|
+
if (cleaned === '') {
|
|
408
|
+
const fallback = Array.from(name)
|
|
409
|
+
.map((char) => {
|
|
410
|
+
const code = char.charCodeAt(0);
|
|
411
|
+
if ((code >= 48 && code <= 57) ||
|
|
412
|
+
(code >= 65 && code <= 90) ||
|
|
413
|
+
(code >= 97 && code <= 122)) {
|
|
414
|
+
return char.toLowerCase();
|
|
415
|
+
}
|
|
416
|
+
return code.toString(16);
|
|
417
|
+
})
|
|
418
|
+
.join('')
|
|
419
|
+
.slice(0, 50);
|
|
420
|
+
return fallback || 'pake-app';
|
|
421
|
+
}
|
|
422
|
+
return cleaned;
|
|
349
423
|
}
|
|
350
424
|
|
|
425
|
+
/**
|
|
426
|
+
* Helper function to generate safe lowercase app name for file paths
|
|
427
|
+
*/
|
|
428
|
+
function getSafeAppName(name) {
|
|
429
|
+
return generateSafeFilename(name).toLowerCase();
|
|
430
|
+
}
|
|
351
431
|
async function mergeConfig(url, options, tauriConf) {
|
|
352
432
|
// Ensure .pake directory exists and copy source templates if needed
|
|
353
433
|
const srcTauriDir = path.join(npmDirectory, 'src-tauri');
|
|
@@ -368,7 +448,7 @@ async function mergeConfig(url, options, tauriConf) {
|
|
|
368
448
|
await fsExtra.copy(sourcePath, destPath);
|
|
369
449
|
}
|
|
370
450
|
}));
|
|
371
|
-
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, } = options;
|
|
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;
|
|
372
452
|
const { platform } = process;
|
|
373
453
|
const platformHideOnClose = hideOnClose ?? platform === 'darwin';
|
|
374
454
|
const tauriConfWindowOptions = {
|
|
@@ -438,7 +518,7 @@ async function mergeConfig(url, options, tauriConf) {
|
|
|
438
518
|
// Remove hardcoded desktop files and regenerate with correct app name
|
|
439
519
|
delete tauriConf.bundle.linux.deb.files;
|
|
440
520
|
// Generate correct desktop file configuration
|
|
441
|
-
const appNameSafe =
|
|
521
|
+
const appNameSafe = getSafeAppName(name);
|
|
442
522
|
const identifier = `com.pake.${appNameSafe}`;
|
|
443
523
|
const desktopFileName = `${identifier}.desktop`;
|
|
444
524
|
// Create desktop file content
|
|
@@ -489,22 +569,23 @@ StartupNotify=true
|
|
|
489
569
|
}
|
|
490
570
|
}
|
|
491
571
|
// Set icon.
|
|
572
|
+
const safeAppName = getSafeAppName(name);
|
|
492
573
|
const platformIconMap = {
|
|
493
574
|
win32: {
|
|
494
575
|
fileExt: '.ico',
|
|
495
|
-
path: `png/${
|
|
576
|
+
path: `png/${safeAppName}_256.ico`,
|
|
496
577
|
defaultIcon: 'png/icon_256.ico',
|
|
497
578
|
message: 'Windows icon must be .ico and 256x256px.',
|
|
498
579
|
},
|
|
499
580
|
linux: {
|
|
500
581
|
fileExt: '.png',
|
|
501
|
-
path: `png/${
|
|
582
|
+
path: `png/${safeAppName}_512.png`,
|
|
502
583
|
defaultIcon: 'png/icon_512.png',
|
|
503
584
|
message: 'Linux icon must be .png and 512x512px.',
|
|
504
585
|
},
|
|
505
586
|
darwin: {
|
|
506
587
|
fileExt: '.icns',
|
|
507
|
-
path: `icons/${
|
|
588
|
+
path: `icons/${safeAppName}.icns`,
|
|
508
589
|
defaultIcon: 'icons/icon.icns',
|
|
509
590
|
message: 'macOS icon must be .icns type.',
|
|
510
591
|
},
|
|
@@ -548,8 +629,8 @@ StartupNotify=true
|
|
|
548
629
|
// ้่ฆๅคๆญๅพๆ ๆ ผๅผ๏ผ้ป่ฎคๅชๆฏๆicoๅpngไธค็ง
|
|
549
630
|
let iconExt = path.extname(systemTrayIcon).toLowerCase();
|
|
550
631
|
if (iconExt == '.png' || iconExt == '.ico') {
|
|
551
|
-
const trayIcoPath = path.join(npmDirectory, `src-tauri/png/${
|
|
552
|
-
trayIconPath = `png/${
|
|
632
|
+
const trayIcoPath = path.join(npmDirectory, `src-tauri/png/${safeAppName}${iconExt}`);
|
|
633
|
+
trayIconPath = `png/${safeAppName}${iconExt}`;
|
|
553
634
|
await fsExtra.copy(systemTrayIcon, trayIcoPath);
|
|
554
635
|
}
|
|
555
636
|
else {
|
|
@@ -583,6 +664,7 @@ StartupNotify=true
|
|
|
583
664
|
await fsExtra.writeFile(injectFilePath, '');
|
|
584
665
|
}
|
|
585
666
|
tauriConf.pake.proxy_url = proxyUrl || '';
|
|
667
|
+
tauriConf.pake.multi_instance = multiInstance;
|
|
586
668
|
// Configure WASM support with required HTTP headers
|
|
587
669
|
if (wasm) {
|
|
588
670
|
tauriConf.app.security = {
|
|
@@ -659,6 +741,7 @@ class BaseBuilder {
|
|
|
659
741
|
logger.warn('โผ The first use requires installing system dependencies.');
|
|
660
742
|
logger.warn('โผ See more in https://tauri.app/start/prerequisites/.');
|
|
661
743
|
}
|
|
744
|
+
ensureRustEnv();
|
|
662
745
|
if (!checkRustInstalled()) {
|
|
663
746
|
const res = await prompts({
|
|
664
747
|
type: 'confirm',
|
|
@@ -691,10 +774,10 @@ class BaseBuilder {
|
|
|
691
774
|
logger.info(`โบ Located in China, using ${packageManager}/rsProxy CN mirror.`);
|
|
692
775
|
const projectCnConf = path.join(tauriSrcPath, 'rust_proxy.toml');
|
|
693
776
|
await fsExtra.copy(projectCnConf, projectConf);
|
|
694
|
-
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}
|
|
777
|
+
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}`, timeout, buildEnv, this.options.debug);
|
|
695
778
|
}
|
|
696
779
|
else {
|
|
697
|
-
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${peerDepsOption}
|
|
780
|
+
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${peerDepsOption}`, timeout, buildEnv, this.options.debug);
|
|
698
781
|
}
|
|
699
782
|
spinner.succeed(chalk.green('Package installed!'));
|
|
700
783
|
if (!tauriTargetPathExists) {
|
|
@@ -719,8 +802,11 @@ class BaseBuilder {
|
|
|
719
802
|
buildSpinner.stop();
|
|
720
803
|
// Show static message to keep the status visible
|
|
721
804
|
logger.warn('โธ Building app...');
|
|
722
|
-
const buildEnv =
|
|
723
|
-
|
|
805
|
+
const buildEnv = {
|
|
806
|
+
...this.getBuildEnvironment(),
|
|
807
|
+
...(process.env.NO_STRIP && { NO_STRIP: process.env.NO_STRIP }),
|
|
808
|
+
};
|
|
809
|
+
await shellExec(`cd "${npmDirectory}" && ${this.getBuildCommand(packageManager)}`, this.getBuildTimeout(), buildEnv, this.options.debug);
|
|
724
810
|
// Copy app
|
|
725
811
|
const fileName = this.getFileName();
|
|
726
812
|
const fileType = this.getFileType(target);
|
|
@@ -1162,6 +1248,7 @@ const DEFAULT_PAKE_OPTIONS = {
|
|
|
1162
1248
|
wasm: false,
|
|
1163
1249
|
enableDragDrop: false,
|
|
1164
1250
|
keepBinary: false,
|
|
1251
|
+
multiInstance: false,
|
|
1165
1252
|
};
|
|
1166
1253
|
|
|
1167
1254
|
async function checkUpdateTips() {
|
|
@@ -1190,7 +1277,9 @@ const API_KEYS = {
|
|
|
1190
1277
|
brandfetch: ['1idqvJC0CeFSeyp3Yf7', '1idej-yhU_ThggIHFyG'],
|
|
1191
1278
|
};
|
|
1192
1279
|
function generateIconPath(appName, isDefault = false) {
|
|
1193
|
-
const safeName = isDefault
|
|
1280
|
+
const safeName = isDefault
|
|
1281
|
+
? 'icon'
|
|
1282
|
+
: generateSafeFilename(appName).toLowerCase();
|
|
1194
1283
|
const baseName = safeName;
|
|
1195
1284
|
if (IS_WIN) {
|
|
1196
1285
|
return path.join(npmDirectory, 'src-tauri', 'png', `${baseName}_256.ico`);
|
|
@@ -1603,8 +1692,7 @@ ${green('|_| \\__,_|_|\\_\\___| can turn any webpage into a desktop app with
|
|
|
1603
1692
|
program
|
|
1604
1693
|
.addHelpText('beforeAll', logo)
|
|
1605
1694
|
.usage(`[url] [options]`)
|
|
1606
|
-
.showHelpAfterError()
|
|
1607
|
-
.helpOption(false);
|
|
1695
|
+
.showHelpAfterError();
|
|
1608
1696
|
program
|
|
1609
1697
|
.argument('[url]', 'The web URL you want to package', validateUrlInput)
|
|
1610
1698
|
// Refer to https://github.com/tj/commander.js#custom-option-processing, turn string array into a string connected with custom connectors.
|
|
@@ -1683,6 +1771,9 @@ program
|
|
|
1683
1771
|
.addOption(new Option('--keep-binary', 'Keep raw binary file alongside installer')
|
|
1684
1772
|
.default(DEFAULT_PAKE_OPTIONS.keepBinary)
|
|
1685
1773
|
.hideHelp())
|
|
1774
|
+
.addOption(new Option('--multi-instance', 'Allow multiple app instances')
|
|
1775
|
+
.default(DEFAULT_PAKE_OPTIONS.multiInstance)
|
|
1776
|
+
.hideHelp())
|
|
1686
1777
|
.addOption(new Option('--installer-language <string>', 'Installer language')
|
|
1687
1778
|
.default(DEFAULT_PAKE_OPTIONS.installerLanguage)
|
|
1688
1779
|
.hideHelp())
|
|
@@ -1690,12 +1781,12 @@ program
|
|
|
1690
1781
|
.configureHelp({
|
|
1691
1782
|
sortSubcommands: true,
|
|
1692
1783
|
optionTerm: (option) => {
|
|
1693
|
-
if (option.flags === '-v, --version')
|
|
1784
|
+
if (option.flags === '-v, --version' || option.flags === '-h, --help')
|
|
1694
1785
|
return '';
|
|
1695
1786
|
return option.flags;
|
|
1696
1787
|
},
|
|
1697
1788
|
optionDescription: (option) => {
|
|
1698
|
-
if (option.flags === '-v, --version')
|
|
1789
|
+
if (option.flags === '-v, --version' || option.flags === '-h, --help')
|
|
1699
1790
|
return '';
|
|
1700
1791
|
return option.description;
|
|
1701
1792
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pake-cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "๐คฑ๐ป Turn any webpage into a desktop app with one command. ๐คฑ๐ป ไธ้ฎๆๅ
็ฝ้กต็ๆ่ฝป้ๆก้ขๅบ็จใ",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -52,12 +52,12 @@
|
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@tauri-apps/api": "^2.8.0",
|
|
54
54
|
"@tauri-apps/cli": "^2.8.4",
|
|
55
|
-
"axios": "^1.
|
|
56
|
-
"chalk": "^5.6.
|
|
55
|
+
"axios": "^1.12.2",
|
|
56
|
+
"chalk": "^5.6.2",
|
|
57
57
|
"commander": "^12.1.0",
|
|
58
58
|
"execa": "^9.6.0",
|
|
59
59
|
"file-type": "^18.7.0",
|
|
60
|
-
"fs-extra": "^11.3.
|
|
60
|
+
"fs-extra": "^11.3.2",
|
|
61
61
|
"icon-gen": "^5.0.0",
|
|
62
62
|
"loglevel": "^1.9.2",
|
|
63
63
|
"ora": "^8.2.0",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@rollup/plugin-replace": "^6.0.2",
|
|
75
75
|
"@rollup/plugin-terser": "^0.4.4",
|
|
76
76
|
"@types/fs-extra": "^11.0.4",
|
|
77
|
-
"@types/node": "^20.19.
|
|
77
|
+
"@types/node": "^20.19.21",
|
|
78
78
|
"@types/page-icon": "^0.3.6",
|
|
79
79
|
"@types/prompts": "^2.4.9",
|
|
80
80
|
"@types/tmp": "^0.2.6",
|
|
@@ -82,9 +82,9 @@
|
|
|
82
82
|
"app-root-path": "^3.1.0",
|
|
83
83
|
"cross-env": "^7.0.3",
|
|
84
84
|
"prettier": "^3.6.2",
|
|
85
|
-
"rollup": "^4.
|
|
85
|
+
"rollup": "^4.52.4",
|
|
86
86
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
87
87
|
"tslib": "^2.8.1",
|
|
88
|
-
"typescript": "^5.9.
|
|
88
|
+
"typescript": "^5.9.3"
|
|
89
89
|
}
|
|
90
90
|
}
|
package/src-tauri/Cargo.lock
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This file is automatically @generated by Cargo.
|
|
2
2
|
# It is not intended for manual editing.
|
|
3
|
-
version =
|
|
3
|
+
version = 4
|
|
4
4
|
|
|
5
5
|
[[package]]
|
|
6
6
|
name = "addr2line"
|
|
@@ -3546,10 +3546,11 @@ dependencies = [
|
|
|
3546
3546
|
|
|
3547
3547
|
[[package]]
|
|
3548
3548
|
name = "serde"
|
|
3549
|
-
version = "1.0.
|
|
3549
|
+
version = "1.0.228"
|
|
3550
3550
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3551
|
-
checksum = "
|
|
3551
|
+
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
|
3552
3552
|
dependencies = [
|
|
3553
|
+
"serde_core",
|
|
3553
3554
|
"serde_derive",
|
|
3554
3555
|
]
|
|
3555
3556
|
|
|
@@ -3564,11 +3565,20 @@ dependencies = [
|
|
|
3564
3565
|
"typeid",
|
|
3565
3566
|
]
|
|
3566
3567
|
|
|
3568
|
+
[[package]]
|
|
3569
|
+
name = "serde_core"
|
|
3570
|
+
version = "1.0.228"
|
|
3571
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3572
|
+
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
|
3573
|
+
dependencies = [
|
|
3574
|
+
"serde_derive",
|
|
3575
|
+
]
|
|
3576
|
+
|
|
3567
3577
|
[[package]]
|
|
3568
3578
|
name = "serde_derive"
|
|
3569
|
-
version = "1.0.
|
|
3579
|
+
version = "1.0.228"
|
|
3570
3580
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3571
|
-
checksum = "
|
|
3581
|
+
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
|
3572
3582
|
dependencies = [
|
|
3573
3583
|
"proc-macro2",
|
|
3574
3584
|
"quote",
|
|
@@ -3588,14 +3598,15 @@ dependencies = [
|
|
|
3588
3598
|
|
|
3589
3599
|
[[package]]
|
|
3590
3600
|
name = "serde_json"
|
|
3591
|
-
version = "1.0.
|
|
3601
|
+
version = "1.0.145"
|
|
3592
3602
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3593
|
-
checksum = "
|
|
3603
|
+
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
|
|
3594
3604
|
dependencies = [
|
|
3595
3605
|
"itoa",
|
|
3596
3606
|
"memchr",
|
|
3597
3607
|
"ryu",
|
|
3598
3608
|
"serde",
|
|
3609
|
+
"serde_core",
|
|
3599
3610
|
]
|
|
3600
3611
|
|
|
3601
3612
|
[[package]]
|
package/src-tauri/Cargo.toml
CHANGED
|
@@ -15,19 +15,19 @@ crate-type = ["staticlib", "cdylib", "lib"]
|
|
|
15
15
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
16
16
|
|
|
17
17
|
[build-dependencies]
|
|
18
|
-
tauri-build = { version = "2.4.
|
|
18
|
+
tauri-build = { version = "2.4.1", features = [] }
|
|
19
19
|
|
|
20
20
|
[dependencies]
|
|
21
|
-
serde_json = "1.0.
|
|
22
|
-
serde = { version = "1.0.
|
|
21
|
+
serde_json = "1.0.145"
|
|
22
|
+
serde = { version = "1.0.228", features = ["derive"] }
|
|
23
23
|
tokio = { version = "1.47.1", features = ["full"] }
|
|
24
|
-
tauri = { version = "2.8.
|
|
24
|
+
tauri = { version = "2.8.5", features = ["tray-icon", "image-ico", "image-png", "macos-proxy"] }
|
|
25
25
|
tauri-plugin-window-state = "2.4.0"
|
|
26
26
|
tauri-plugin-oauth = "2.0.0"
|
|
27
27
|
tauri-plugin-http = "2.5.2"
|
|
28
28
|
tauri-plugin-global-shortcut = { version = "2.3.0" }
|
|
29
29
|
tauri-plugin-shell = "2.3.1"
|
|
30
|
-
tauri-plugin-single-instance = "2.3.
|
|
30
|
+
tauri-plugin-single-instance = "2.3.4"
|
|
31
31
|
tauri-plugin-notification = "2.3.1"
|
|
32
32
|
|
|
33
33
|
[features]
|
package/src-tauri/pake.json
CHANGED
|
@@ -100,21 +100,6 @@ const DOWNLOADABLE_FILE_EXTENSIONS = {
|
|
|
100
100
|
"scss",
|
|
101
101
|
"sass",
|
|
102
102
|
"less",
|
|
103
|
-
"html",
|
|
104
|
-
"htm",
|
|
105
|
-
"php",
|
|
106
|
-
"py",
|
|
107
|
-
"java",
|
|
108
|
-
"cpp",
|
|
109
|
-
"c",
|
|
110
|
-
"h",
|
|
111
|
-
"cs",
|
|
112
|
-
"rb",
|
|
113
|
-
"go",
|
|
114
|
-
"rs",
|
|
115
|
-
"swift",
|
|
116
|
-
"kt",
|
|
117
|
-
"scala",
|
|
118
103
|
"sh",
|
|
119
104
|
"bat",
|
|
120
105
|
"ps1",
|
|
@@ -163,6 +148,22 @@ function isChineseLanguage(language = getUserLanguage()) {
|
|
|
163
148
|
);
|
|
164
149
|
}
|
|
165
150
|
|
|
151
|
+
// User notification helper
|
|
152
|
+
function showDownloadError(filename) {
|
|
153
|
+
const isChinese = isChineseLanguage();
|
|
154
|
+
const message = isChinese
|
|
155
|
+
? `ไธ่ฝฝๅคฑ่ดฅ: ${filename}`
|
|
156
|
+
: `Download failed: ${filename}`;
|
|
157
|
+
|
|
158
|
+
if (window.Notification && Notification.permission === "granted") {
|
|
159
|
+
new Notification(isChinese ? "ไธ่ฝฝ้่ฏฏ" : "Download Error", {
|
|
160
|
+
body: message,
|
|
161
|
+
});
|
|
162
|
+
} else {
|
|
163
|
+
console.error(message);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
166
167
|
// Unified file detection - replaces both isDownloadLink and isFileLink
|
|
167
168
|
function isDownloadableFile(url) {
|
|
168
169
|
try {
|
|
@@ -266,36 +267,42 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
266
267
|
}
|
|
267
268
|
|
|
268
269
|
// write the ArrayBuffer to a binary, and you're done
|
|
269
|
-
const userLanguage =
|
|
270
|
+
const userLanguage = getUserLanguage();
|
|
270
271
|
invoke("download_file_by_binary", {
|
|
271
272
|
params: {
|
|
272
273
|
filename,
|
|
273
274
|
binary: Array.from(binary),
|
|
274
275
|
language: userLanguage,
|
|
275
276
|
},
|
|
276
|
-
}).catch(error => {
|
|
277
|
-
console.error(
|
|
277
|
+
}).catch((error) => {
|
|
278
|
+
console.error("Failed to download data URI file:", filename, error);
|
|
279
|
+
showDownloadError(filename);
|
|
278
280
|
});
|
|
279
281
|
} catch (error) {
|
|
280
|
-
console.error(
|
|
282
|
+
console.error("Failed to process data URI:", dataURI, error);
|
|
283
|
+
showDownloadError(filename || "file");
|
|
281
284
|
}
|
|
282
285
|
}
|
|
283
286
|
|
|
284
287
|
function downloadFromBlobUrl(blobUrl, filename) {
|
|
285
|
-
convertBlobUrlToBinary(blobUrl)
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
288
|
+
convertBlobUrlToBinary(blobUrl)
|
|
289
|
+
.then((binary) => {
|
|
290
|
+
const userLanguage = getUserLanguage();
|
|
291
|
+
invoke("download_file_by_binary", {
|
|
292
|
+
params: {
|
|
293
|
+
filename,
|
|
294
|
+
binary,
|
|
295
|
+
language: userLanguage,
|
|
296
|
+
},
|
|
297
|
+
}).catch((error) => {
|
|
298
|
+
console.error("Failed to download blob file:", filename, error);
|
|
299
|
+
showDownloadError(filename);
|
|
300
|
+
});
|
|
301
|
+
})
|
|
302
|
+
.catch((error) => {
|
|
303
|
+
console.error("Failed to convert blob to binary:", blobUrl, error);
|
|
304
|
+
showDownloadError(filename);
|
|
295
305
|
});
|
|
296
|
-
}).catch(error => {
|
|
297
|
-
console.error('Failed to convert blob to binary:', blobUrl, error);
|
|
298
|
-
});
|
|
299
306
|
}
|
|
300
307
|
|
|
301
308
|
// detect blob download by createElement("a")
|
|
@@ -335,14 +342,14 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
335
342
|
const handleExternalLink = (url) => {
|
|
336
343
|
// Don't try to open blob: or data: URLs with shell
|
|
337
344
|
if (isSpecialDownload(url)) {
|
|
338
|
-
console.warn(
|
|
345
|
+
console.warn("Cannot open special URL with shell:", url);
|
|
339
346
|
return;
|
|
340
347
|
}
|
|
341
348
|
|
|
342
349
|
invoke("plugin:shell|open", {
|
|
343
350
|
path: url,
|
|
344
|
-
}).catch(error => {
|
|
345
|
-
console.error(
|
|
351
|
+
}).catch((error) => {
|
|
352
|
+
console.error("Failed to open URL with shell:", url, error);
|
|
346
353
|
});
|
|
347
354
|
};
|
|
348
355
|
|
|
@@ -370,7 +377,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
370
377
|
|
|
371
378
|
const detectAnchorElementClick = (e) => {
|
|
372
379
|
// Safety check: ensure e.target exists and is an Element with closest method
|
|
373
|
-
if (!e.target || typeof e.target.closest !==
|
|
380
|
+
if (!e.target || typeof e.target.closest !== "function") {
|
|
374
381
|
return;
|
|
375
382
|
}
|
|
376
383
|
const anchorElement = e.target.closest("a");
|
|
@@ -383,20 +390,21 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
383
390
|
|
|
384
391
|
// Handle _blank links: same domain navigates in-app, cross-domain opens new window
|
|
385
392
|
if (target === "_blank") {
|
|
386
|
-
e.preventDefault();
|
|
387
|
-
e.stopImmediatePropagation();
|
|
388
|
-
|
|
389
393
|
if (isSameDomain(absoluteUrl)) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
window,
|
|
394
|
-
absoluteUrl,
|
|
395
|
-
"_blank",
|
|
396
|
-
"width=1200,height=800,scrollbars=yes,resizable=yes",
|
|
397
|
-
);
|
|
398
|
-
if (!newWindow) handleExternalLink(absoluteUrl);
|
|
394
|
+
// For same-domain links, let the browser/SPA handle it naturally
|
|
395
|
+
// This prevents full page reload in SPA apps like Discord
|
|
396
|
+
return;
|
|
399
397
|
}
|
|
398
|
+
|
|
399
|
+
e.preventDefault();
|
|
400
|
+
e.stopImmediatePropagation();
|
|
401
|
+
const newWindow = originalWindowOpen.call(
|
|
402
|
+
window,
|
|
403
|
+
absoluteUrl,
|
|
404
|
+
"_blank",
|
|
405
|
+
"width=1200,height=800,scrollbars=yes,resizable=yes",
|
|
406
|
+
);
|
|
407
|
+
if (!newWindow) handleExternalLink(absoluteUrl);
|
|
400
408
|
return;
|
|
401
409
|
}
|
|
402
410
|
|
|
@@ -446,39 +454,24 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
446
454
|
// Rewrite the window.open function.
|
|
447
455
|
const originalWindowOpen = window.open;
|
|
448
456
|
window.open = function (url, name, specs) {
|
|
449
|
-
// Apple login and google login
|
|
450
457
|
if (name === "AppleAuthentication") {
|
|
451
|
-
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
) {
|
|
456
|
-
location.href = url;
|
|
457
|
-
} else {
|
|
458
|
+
return originalWindowOpen.call(window, url, name, specs);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
try {
|
|
458
462
|
const baseUrl = window.location.origin + window.location.pathname;
|
|
459
463
|
const hrefUrl = new URL(url, baseUrl);
|
|
460
464
|
const absoluteUrl = hrefUrl.href;
|
|
461
465
|
|
|
462
|
-
|
|
463
|
-
if (isSameDomain(absoluteUrl)) {
|
|
464
|
-
// Same domain: navigate in app or open new window based on specs
|
|
465
|
-
if (name === "_blank" || !name) {
|
|
466
|
-
return originalWindowOpen.call(
|
|
467
|
-
window,
|
|
468
|
-
absoluteUrl,
|
|
469
|
-
"_blank",
|
|
470
|
-
"width=1200,height=800,scrollbars=yes,resizable=yes",
|
|
471
|
-
);
|
|
472
|
-
} else {
|
|
473
|
-
location.href = absoluteUrl;
|
|
474
|
-
}
|
|
475
|
-
} else {
|
|
476
|
-
// Cross domain: open in external browser
|
|
466
|
+
if (!isSameDomain(absoluteUrl)) {
|
|
477
467
|
handleExternalLink(absoluteUrl);
|
|
468
|
+
return null;
|
|
478
469
|
}
|
|
470
|
+
|
|
471
|
+
return originalWindowOpen.call(window, absoluteUrl, name, specs);
|
|
472
|
+
} catch (error) {
|
|
473
|
+
return originalWindowOpen.call(window, url, name, specs);
|
|
479
474
|
}
|
|
480
|
-
// Call the original window.open function to maintain its normal functionality.
|
|
481
|
-
return originalWindowOpen.call(window, url, name, specs);
|
|
482
475
|
};
|
|
483
476
|
|
|
484
477
|
// Set the default zoom, There are problems with Loop without using try-catch.
|
|
@@ -686,13 +679,16 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
686
679
|
}
|
|
687
680
|
} else {
|
|
688
681
|
// Regular HTTP(S) image
|
|
689
|
-
const userLanguage =
|
|
682
|
+
const userLanguage = getUserLanguage();
|
|
690
683
|
invoke("download_file", {
|
|
691
684
|
params: {
|
|
692
685
|
url: imageUrl,
|
|
693
686
|
filename: filename,
|
|
694
687
|
language: userLanguage,
|
|
695
688
|
},
|
|
689
|
+
}).catch((error) => {
|
|
690
|
+
console.error("Failed to download image:", filename, error);
|
|
691
|
+
showDownloadError(filename);
|
|
696
692
|
});
|
|
697
693
|
}
|
|
698
694
|
}
|
|
@@ -723,7 +719,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
723
719
|
}
|
|
724
720
|
|
|
725
721
|
// Check for parent elements with background images
|
|
726
|
-
const parentWithBg =
|
|
722
|
+
const parentWithBg =
|
|
723
|
+
target && typeof target.closest === "function"
|
|
724
|
+
? target.closest('[style*="background-image"]')
|
|
725
|
+
: null;
|
|
727
726
|
if (parentWithBg) {
|
|
728
727
|
const bgImage = parentWithBg.style.backgroundImage;
|
|
729
728
|
const urlMatch = bgImage.match(/url\(["']?([^"')]+)["']?\)/);
|
|
@@ -737,7 +736,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
737
736
|
|
|
738
737
|
// Simplified menu builder
|
|
739
738
|
function buildMenuItems(type, data) {
|
|
740
|
-
const userLanguage =
|
|
739
|
+
const userLanguage = getUserLanguage();
|
|
741
740
|
const items = [];
|
|
742
741
|
|
|
743
742
|
switch (type) {
|
|
@@ -764,6 +763,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
764
763
|
const filename = getFilenameFromUrl(data.url);
|
|
765
764
|
invoke("download_file", {
|
|
766
765
|
params: { url: data.url, filename, language: userLanguage },
|
|
766
|
+
}).catch((error) => {
|
|
767
|
+
console.error("Failed to download file:", filename, error);
|
|
768
|
+
showDownloadError(filename);
|
|
767
769
|
});
|
|
768
770
|
}),
|
|
769
771
|
);
|
|
@@ -792,7 +794,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
792
794
|
const mediaInfo = getMediaInfo(target);
|
|
793
795
|
|
|
794
796
|
// Check for links (but not if it's media)
|
|
795
|
-
const linkElement =
|
|
797
|
+
const linkElement =
|
|
798
|
+
target && typeof target.closest === "function"
|
|
799
|
+
? target.closest("a")
|
|
800
|
+
: null;
|
|
796
801
|
const isLink = linkElement && linkElement.href && !mediaInfo.isMedia;
|
|
797
802
|
|
|
798
803
|
// Only show custom menu for media or links
|
package/src-tauri/src/lib.rs
CHANGED
|
@@ -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 multi_instance = pake_config.multi_instance;
|
|
27
28
|
|
|
28
29
|
let window_state_plugin = WindowStatePlugin::default()
|
|
29
30
|
.with_state_flags(if init_fullscreen {
|
|
@@ -35,19 +36,25 @@ pub fn run_app() {
|
|
|
35
36
|
.build();
|
|
36
37
|
|
|
37
38
|
#[allow(deprecated)]
|
|
38
|
-
tauri_app
|
|
39
|
+
let mut app_builder = tauri_app
|
|
39
40
|
.plugin(window_state_plugin)
|
|
40
41
|
.plugin(tauri_plugin_oauth::init())
|
|
41
42
|
.plugin(tauri_plugin_http::init())
|
|
42
43
|
.plugin(tauri_plugin_shell::init())
|
|
43
|
-
.plugin(tauri_plugin_notification::init())
|
|
44
|
-
|
|
44
|
+
.plugin(tauri_plugin_notification::init());
|
|
45
|
+
|
|
46
|
+
// Only add single instance plugin if multiple instances are not allowed
|
|
47
|
+
if !multi_instance {
|
|
48
|
+
app_builder = app_builder.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
|
|
45
49
|
if let Some(window) = app.get_webview_window("pake") {
|
|
46
50
|
let _ = window.unminimize();
|
|
47
51
|
let _ = window.show();
|
|
48
52
|
let _ = window.set_focus();
|
|
49
53
|
}
|
|
50
|
-
}))
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
app_builder
|
|
51
58
|
.invoke_handler(tauri::generate_handler![
|
|
52
59
|
download_file,
|
|
53
60
|
download_file_by_binary,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
[source.crates-io]
|
|
2
|
-
replace-with = 'rsproxy-sparse'
|
|
3
|
-
[source.rsproxy]
|
|
4
|
-
registry = "https://rsproxy.cn/crates.io-index"
|
|
5
|
-
[source.rsproxy-sparse]
|
|
6
|
-
registry = "sparse+https://rsproxy.cn/index/"
|
|
7
|
-
[registries.rsproxy]
|
|
8
|
-
index = "https://rsproxy.cn/crates.io-index"
|
|
9
|
-
[net]
|
|
10
|
-
git-fetch-with-cli = true
|