Merge remote-tracking branch 'origin/master' into dev

This commit is contained in:
jeasonnow
2023-07-21 10:30:18 +08:00
12 changed files with 849 additions and 1248 deletions

716
dist/cli.js vendored
View File

@@ -1,313 +1,313 @@
import chalk from 'chalk'; import chalk from 'chalk';
import { InvalidArgumentError, program } from 'commander'; import { InvalidArgumentError, program } from 'commander';
import log from 'loglevel'; import log from 'loglevel';
import path from 'path'; import path from 'path';
import fsExtra from 'fs-extra'; import fsExtra from 'fs-extra';
import prompts from 'prompts'; import prompts from 'prompts';
import shelljs from 'shelljs'; import shelljs from 'shelljs';
import crypto from 'crypto'; import crypto from 'crypto';
import ora from 'ora'; import ora from 'ora';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import dns from 'dns'; import dns from 'dns';
import http from 'http'; import http from 'http';
import { promisify } from 'util'; import { promisify } from 'util';
import fs from 'fs'; import fs from 'fs';
import updateNotifier from 'update-notifier'; import updateNotifier from 'update-notifier';
import axios from 'axios'; import axios from 'axios';
import { dir } from 'tmp-promise'; import { dir } from 'tmp-promise';
import { fileTypeFromBuffer } from 'file-type'; import { fileTypeFromBuffer } from 'file-type';
import psl from 'psl'; import psl from 'psl';
import isUrl from 'is-url'; import isUrl from 'is-url';
var name = "pake-cli"; var name = "pake-cli";
var version = "2.1.12-beta.0"; var version = "2.2.0";
var description = "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 很简单的用 Rust 打包网页生成很小的桌面 App。"; var description = "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 很简单的用 Rust 打包网页生成很小的桌面 App。";
var engines = { var engines = {
node: ">=16.0.0" node: ">=16.0.0"
}; };
var bin = { var bin = {
pake: "./cli.js" pake: "./cli.js"
}; };
var repository = { var repository = {
type: "git", type: "git",
url: "https://github.com/tw93/pake.git" url: "https://github.com/tw93/pake.git"
}; };
var author = { var author = {
name: "Tw93", name: "Tw93",
email: "tw93@qq.com" email: "tw93@qq.com"
}; };
var keywords = [ var keywords = [
"pake", "pake",
"pake-cli", "pake-cli",
"rust", "rust",
"tauri", "tauri",
"no-electron", "no-electron",
"productivity" "productivity"
]; ];
var files = [ var files = [
"dist", "dist",
"src-tauri", "src-tauri",
"cli.js" "cli.js"
]; ];
var scripts = { var scripts = {
start: "npm run dev", start: "npm run dev",
dev: "npm run tauri dev", dev: "npm run tauri dev",
build: "npm run tauri build --release", build: "npm run tauri build --release",
"build:debug": "npm run tauri build -- --debug", "build:debug": "npm run tauri build -- --debug",
"build:mac": "npm run tauri build -- --target universal-apple-darwin", "build:mac": "npm run tauri build -- --target universal-apple-darwin",
"build:all-unix": "chmod +x ./script/build.sh && ./script/build.sh", "build:all-unix": "chmod +x ./script/build.sh && ./script/build.sh",
"build:all-windows": "pwsh ./script/build.ps1", "build:all-windows": "pwsh ./script/build.ps1",
analyze: "cd src-tauri && cargo bloat --release --crates", analyze: "cd src-tauri && cargo bloat --release --crates",
tauri: "tauri", tauri: "tauri",
cli: "rollup -c rollup.config.js --watch", cli: "rollup -c rollup.config.js --watch",
"cli:dev": "cross-env NODE_ENV=development rollup -c rollup.config.js -w", "cli:dev": "cross-env NODE_ENV=development rollup -c rollup.config.js -w",
"cli:build": "cross-env NODE_ENV=production rollup -c rollup.config.js", "cli:build": "cross-env NODE_ENV=production rollup -c rollup.config.js",
prepublishOnly: "npm run cli:build" prepublishOnly: "npm run cli:build"
}; };
var type = "module"; var type = "module";
var exports = "./dist/pake.js"; var exports = "./dist/pake.js";
var license = "MIT"; var license = "MIT";
var dependencies = { var dependencies = {
"@tauri-apps/api": "^1.4.0", "@tauri-apps/api": "^1.4.0",
"@tauri-apps/cli": "^1.4.0", "@tauri-apps/cli": "^1.4.0",
axios: "^1.1.3", axios: "^1.1.3",
chalk: "^5.1.2", chalk: "^5.1.2",
commander: "^11.0.0", commander: "^11.0.0",
"file-type": "^18.0.0", "file-type": "^18.0.0",
"fs-extra": "^11.1.0", "fs-extra": "^11.1.0",
"is-url": "^1.2.4", "is-url": "^1.2.4",
loglevel: "^1.8.1", loglevel: "^1.8.1",
ora: "^6.1.2", ora: "^6.1.2",
prompts: "^2.4.2", prompts: "^2.4.2",
psl: "^1.9.0", psl: "^1.9.0",
shelljs: "^0.8.5", shelljs: "^0.8.5",
"tmp-promise": "^3.0.3", "tmp-promise": "^3.0.3",
"update-notifier": "^6.0.2" "update-notifier": "^6.0.2"
}; };
var devDependencies = { var devDependencies = {
"@rollup/plugin-alias": "^4.0.2", "@rollup/plugin-alias": "^4.0.2",
"@rollup/plugin-commonjs": "^23.0.2", "@rollup/plugin-commonjs": "^23.0.2",
"@rollup/plugin-json": "^5.0.2", "@rollup/plugin-json": "^5.0.2",
"@rollup/plugin-replace": "^5.0.2", "@rollup/plugin-replace": "^5.0.2",
"@rollup/plugin-terser": "^0.1.0", "@rollup/plugin-terser": "^0.1.0",
"@types/fs-extra": "^9.0.13", "@types/fs-extra": "^9.0.13",
"@types/is-url": "^1.2.30", "@types/is-url": "^1.2.30",
"@types/page-icon": "^0.3.4", "@types/page-icon": "^0.3.4",
"@types/prompts": "^2.4.1", "@types/prompts": "^2.4.1",
"@types/psl": "^1.1.0", "@types/psl": "^1.1.0",
"@types/shelljs": "^0.8.11", "@types/shelljs": "^0.8.11",
"@types/tmp": "^0.2.3", "@types/tmp": "^0.2.3",
"@types/update-notifier": "^6.0.1", "@types/update-notifier": "^6.0.1",
"app-root-path": "^3.1.0", "app-root-path": "^3.1.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
rollup: "^3.3.0", rollup: "^3.3.0",
"rollup-plugin-typescript2": "^0.34.1", "rollup-plugin-typescript2": "^0.34.1",
tslib: "^2.4.1", tslib: "^2.4.1",
typescript: "^4.9.3" typescript: "^4.9.3"
}; };
var packageJson = { var packageJson = {
name: name, name: name,
version: version, version: version,
description: description, description: description,
engines: engines, engines: engines,
bin: bin, bin: bin,
repository: repository, repository: repository,
author: author, author: author,
keywords: keywords, keywords: keywords,
files: files, files: files,
scripts: scripts, scripts: scripts,
type: type, type: type,
exports: exports, exports: exports,
license: license, license: license,
dependencies: dependencies, dependencies: dependencies,
devDependencies: devDependencies devDependencies: devDependencies
}; };
var windows = [ var windows = [
{ {
url: "https://weread.qq.com/", url: "https://weread.qq.com/",
transparent: false, transparent: false,
fullscreen: false, fullscreen: false,
width: 1200, width: 1200,
height: 780, height: 780,
resizable: true, resizable: true,
url_type: "web" url_type: "web"
} }
]; ];
var user_agent = { var user_agent = {
macos: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15", macos: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15",
linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36", linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
windows: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" windows: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
}; };
var menu = { var menu = {
macos: false, macos: false,
linux: false, linux: false,
windows: false windows: false
}; };
var system_tray = { var system_tray = {
macos: false, macos: false,
linux: true, linux: true,
windows: true windows: true
}; };
var inject = [ var inject = [
]; ];
var pakeConf = { var pakeConf = {
windows: windows, windows: windows,
user_agent: user_agent, user_agent: user_agent,
menu: menu, menu: menu,
system_tray: system_tray, system_tray: system_tray,
inject: inject inject: inject
}; };
var tauri$3 = { var tauri$3 = {
security: { security: {
csp: null, csp: null,
dangerousRemoteDomainIpcAccess: [ dangerousRemoteDomainIpcAccess: [
{ {
domain: "weread.qq.com", domain: "weread.qq.com",
windows: [ windows: [
"pake" "pake"
], ],
enableTauriAPI: true enableTauriAPI: true
} }
] ]
}, },
updater: { updater: {
active: false active: false
}, },
systemTray: { systemTray: {
iconPath: "png/icon_512.png", iconPath: "png/icon_512.png",
iconAsTemplate: true iconAsTemplate: true
}, },
allowlist: { allowlist: {
all: true, all: true,
fs: { fs: {
all: true, all: true,
scope: [ scope: [
"$DOWNLOAD/*" "$DOWNLOAD/*"
] ]
} }
} }
}; };
var build = { var build = {
withGlobalTauri: true, withGlobalTauri: true,
devPath: "../dist", devPath: "../dist",
distDir: "../dist", distDir: "../dist",
beforeBuildCommand: "", beforeBuildCommand: "",
beforeDevCommand: "" beforeDevCommand: ""
}; };
var CommonConf = { var CommonConf = {
tauri: tauri$3, tauri: tauri$3,
"package": { "package": {
productName: "WeRead", productName: "WeRead",
version: "1.0.0" version: "1.0.0"
}, },
build: build build: build
}; };
var tauri$2 = { var tauri$2 = {
bundle: { bundle: {
icon: [ icon: [
"png/weread_256.ico", "png/weread_256.ico",
"png/weread_32.ico" "png/weread_32.ico"
], ],
identifier: "com.pake.weread", identifier: "com.pake.weread",
active: true, active: true,
category: "DeveloperTool", category: "DeveloperTool",
copyright: "", copyright: "",
externalBin: [ externalBin: [
], ],
longDescription: "", longDescription: "",
resources: [ resources: [
"png/weread_32.ico" "png/weread_32.ico"
], ],
shortDescription: "", shortDescription: "",
targets: [ targets: [
"msi" "msi"
], ],
windows: { windows: {
certificateThumbprint: null, certificateThumbprint: null,
digestAlgorithm: "sha256", digestAlgorithm: "sha256",
timestampUrl: "", timestampUrl: "",
wix: { wix: {
language: [ language: [
"en-US" "en-US"
], ],
template: "assets/main.wxs" template: "assets/main.wxs"
} }
} }
} }
}; };
var WinConf = { var WinConf = {
tauri: tauri$2 tauri: tauri$2
}; };
var tauri$1 = { var tauri$1 = {
bundle: { bundle: {
icon: [ icon: [
"icons/icon.icns" "icons/icon.icns"
], ],
identifier: "com.pake.5b8ae9", identifier: "com.pake.5b8ae9",
active: true, active: true,
category: "DeveloperTool", category: "DeveloperTool",
copyright: "", copyright: "",
externalBin: [ externalBin: [
], ],
longDescription: "", longDescription: "",
macOS: { macOS: {
entitlements: null, entitlements: null,
exceptionDomain: "", exceptionDomain: "",
frameworks: [ frameworks: [
], ],
providerShortName: null, providerShortName: null,
signingIdentity: null signingIdentity: null
}, },
resources: [ resources: [
], ],
shortDescription: "", shortDescription: "",
targets: [ targets: [
"dmg" "dmg"
] ]
} }
}; };
var MacConf = { var MacConf = {
tauri: tauri$1 tauri: tauri$1
}; };
var tauri = { var tauri = {
bundle: { bundle: {
icon: [ icon: [
"png/weread_512.png" "png/weread_512.png"
], ],
identifier: "com.pake.weread", identifier: "com.pake.weread",
active: true, active: true,
category: "DeveloperTool", category: "DeveloperTool",
copyright: "", copyright: "",
deb: { deb: {
depends: [ depends: [
"curl", "curl",
"wget" "wget"
], ],
files: { files: {
"/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop" "/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop"
} }
}, },
externalBin: [ externalBin: [
], ],
longDescription: "", longDescription: "",
resources: [ resources: [
], ],
shortDescription: "", shortDescription: "",
targets: [ targets: [
"deb", "deb",
"appimage" "appimage"
] ]
} }
}; };
var LinuxConf = { var LinuxConf = {
tauri: tauri tauri: tauri
}; };
const platformConfigs = { const platformConfigs = {
win32: WinConf, win32: WinConf,
darwin: MacConf, darwin: MacConf,
@@ -324,8 +324,8 @@ let tauriConfig = {
package: CommonConf.package, package: CommonConf.package,
build: CommonConf.build, build: CommonConf.build,
pake: pakeConf, pake: pakeConf,
}; };
// Generates an identifier based on the given URL. // Generates an identifier based on the given URL.
function getIdentifier(url) { function getIdentifier(url) {
const postFixHash = crypto.createHash('md5').update(url).digest('hex').substring(0, 6); const postFixHash = crypto.createHash('md5').update(url).digest('hex').substring(0, 6);
@@ -353,19 +353,19 @@ function getSpinner(text) {
spinner: loadingType, spinner: loadingType,
color: 'cyan', color: 'cyan',
}).start(); }).start();
} }
const { platform: platform$1 } = process; const { platform: platform$1 } = process;
const IS_MAC = platform$1 === 'darwin'; const IS_MAC = platform$1 === 'darwin';
const IS_WIN = platform$1 === 'win32'; const IS_WIN = platform$1 === 'win32';
const IS_LINUX = platform$1 === 'linux'; const IS_LINUX = platform$1 === 'linux';
// Convert the current module URL to a file path // Convert the current module URL to a file path
const currentModulePath = fileURLToPath(import.meta.url); const currentModulePath = fileURLToPath(import.meta.url);
// Resolve the parent directory of the current module // Resolve the parent directory of the current module
const npmDirectory = path.join(path.dirname(currentModulePath), '..'); const npmDirectory = path.join(path.dirname(currentModulePath), '..');
const tauriConfigDirectory = path.join(npmDirectory, 'src-tauri'); const tauriConfigDirectory = path.join(npmDirectory, 'src-tauri');
function shellExec(command) { function shellExec(command) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
shelljs.exec(command, { async: true, silent: false, cwd: npmDirectory }, code => { shelljs.exec(command, { async: true, silent: false, cwd: npmDirectory }, code => {
@@ -377,8 +377,8 @@ function shellExec(command) {
} }
}); });
}); });
} }
const logger = { const logger = {
info(...msg) { info(...msg) {
log.info(...msg.map(m => chalk.white(m))); log.info(...msg.map(m => chalk.white(m)));
@@ -395,8 +395,8 @@ const logger = {
success(...msg) { success(...msg) {
log.info(...msg.map(m => chalk.green(m))); log.info(...msg.map(m => chalk.green(m)));
}, },
}; };
const resolve = promisify(dns.resolve); const resolve = promisify(dns.resolve);
const ping = async (host) => { const ping = async (host) => {
const lookup = promisify(dns.lookup); const lookup = promisify(dns.lookup);
@@ -440,8 +440,8 @@ async function isChinaIP(ip, domain) {
logger.debug(`ping ${domain} failed!`); logger.debug(`ping ${domain} failed!`);
return true; return true;
} }
} }
async function installRust() { async function installRust() {
const isInChina = await isChinaDomain('sh.rustup.rs'); const isInChina = await isChinaDomain('sh.rustup.rs');
const rustInstallScriptForMac = isInChina const rustInstallScriptForMac = isInChina
@@ -461,8 +461,8 @@ async function installRust() {
} }
function checkRustInstalled() { function checkRustInstalled() {
return shelljs.exec('rustc --version', { silent: true }).code === 0; return shelljs.exec('rustc --version', { silent: true }).code === 0;
} }
async function combineFiles(files, output) { async function combineFiles(files, output) {
const contents = files.map(file => { const contents = files.map(file => {
const fileContent = fs.readFileSync(file); const fileContent = fs.readFileSync(file);
@@ -473,8 +473,8 @@ async function combineFiles(files, output) {
}); });
fs.writeFileSync(output, contents.join('\n')); fs.writeFileSync(output, contents.join('\n'));
return files; return files;
} }
async function mergeConfig(url, options, tauriConf) { async function mergeConfig(url, options, tauriConf) {
const { width, height, fullscreen, transparent, userAgent, showMenu, showSystemTray, systemTrayIcon, iterCopyFile, identifier, name, resizable = true, inject, safeDomain, } = options; const { width, height, fullscreen, transparent, userAgent, showMenu, showSystemTray, systemTrayIcon, iterCopyFile, identifier, name, resizable = true, inject, safeDomain, } = options;
const { platform } = process; const { platform } = process;
@@ -655,8 +655,8 @@ async function mergeConfig(url, options, tauriConf) {
delete tauriConf2.tauri.bundle; delete tauriConf2.tauri.bundle;
const configJsonPath = path.join(tauriConfigDirectory, 'tauri.conf.json'); const configJsonPath = path.join(tauriConfigDirectory, 'tauri.conf.json');
await fsExtra.outputJSON(configJsonPath, tauriConf2, { spaces: 4 }); await fsExtra.outputJSON(configJsonPath, tauriConf2, { spaces: 4 });
} }
class BaseBuilder { class BaseBuilder {
constructor(options) { constructor(options) {
this.options = options; this.options = options;
@@ -738,8 +738,8 @@ class BaseBuilder {
getBuildAppPath(npmDirectory, fileName, fileType) { getBuildAppPath(npmDirectory, fileName, fileType) {
return path.join(npmDirectory, this.getBasePath(), fileType.toLowerCase(), `${fileName}.${fileType}`); return path.join(npmDirectory, this.getBasePath(), fileType.toLowerCase(), `${fileName}.${fileType}`);
} }
} }
class MacBuilder extends BaseBuilder { class MacBuilder extends BaseBuilder {
constructor(options) { constructor(options) {
super(options); super(options);
@@ -764,8 +764,8 @@ class MacBuilder extends BaseBuilder {
? 'src-tauri/target/universal-apple-darwin/release/bundle' ? 'src-tauri/target/universal-apple-darwin/release/bundle'
: super.getBasePath(); : super.getBasePath();
} }
} }
class WinBuilder extends BaseBuilder { class WinBuilder extends BaseBuilder {
constructor(options) { constructor(options) {
super(options); super(options);
@@ -777,8 +777,8 @@ class WinBuilder extends BaseBuilder {
const language = tauriConfig.tauri.bundle.windows.wix.language[0]; const language = tauriConfig.tauri.bundle.windows.wix.language[0];
return `${name}_${tauriConfig.package.version}_${arch}_${language}`; return `${name}_${tauriConfig.package.version}_${arch}_${language}`;
} }
} }
class LinuxBuilder extends BaseBuilder { class LinuxBuilder extends BaseBuilder {
constructor(options) { constructor(options) {
super(options); super(options);
@@ -803,8 +803,8 @@ class LinuxBuilder extends BaseBuilder {
} }
return super.getFileType(target); return super.getFileType(target);
} }
} }
const { platform } = process; const { platform } = process;
const buildersMap = { const buildersMap = {
darwin: MacBuilder, darwin: MacBuilder,
@@ -819,8 +819,8 @@ class BuilderProvider {
} }
return new Builder(options); return new Builder(options);
} }
} }
const DEFAULT_PAKE_OPTIONS = { const DEFAULT_PAKE_OPTIONS = {
icon: '', icon: '',
height: 780, height: 780,
@@ -838,12 +838,12 @@ const DEFAULT_PAKE_OPTIONS = {
debug: false, debug: false,
inject: [], inject: [],
safeDomain: [], safeDomain: [],
}; };
async function checkUpdateTips() { async function checkUpdateTips() {
updateNotifier({ pkg: packageJson, updateCheckInterval: 1000 * 60 }).notify({ isGlobal: true }); updateNotifier({ pkg: packageJson, updateCheckInterval: 1000 * 60 }).notify({ isGlobal: true });
} }
async function handleIcon(options) { async function handleIcon(options) {
if (options.icon) { if (options.icon) {
if (options.icon.startsWith('http')) { if (options.icon.startsWith('http')) {
@@ -888,8 +888,8 @@ async function downloadIcon(iconUrl) {
} }
throw error; throw error;
} }
} }
// Extracts the domain from a given URL. // Extracts the domain from a given URL.
function getDomain(inputUrl) { function getDomain(inputUrl) {
try { try {
@@ -927,8 +927,8 @@ function normalizeUrl(urlToNormalize) {
else { else {
throw new Error(`Your url "${urlWithProtocol}" is invalid`); throw new Error(`Your url "${urlWithProtocol}" is invalid`);
} }
} }
function resolveAppName(name, platform) { function resolveAppName(name, platform) {
const domain = getDomain(name) || 'pake'; const domain = getDomain(name) || 'pake';
return platform !== 'linux' ? capitalizeFirstLetter(domain) : domain; return platform !== 'linux' ? capitalizeFirstLetter(domain) : domain;
@@ -972,8 +972,8 @@ async function handleOptions(options, url) {
}; };
appOptions.icon = await handleIcon(appOptions); appOptions.icon = await handleIcon(appOptions);
return appOptions; return appOptions;
} }
function validateNumberInput(value) { function validateNumberInput(value) {
const parsedValue = Number(value); const parsedValue = Number(value);
if (isNaN(parsedValue)) { if (isNaN(parsedValue)) {
@@ -992,14 +992,14 @@ function validateUrlInput(url) {
} }
} }
return url; return url;
} }
const { green, yellow } = chalk; const { green, yellow } = chalk;
const logo = `${chalk.green(' ____ _')} const logo = `${chalk.green(' ____ _')}
${green('| _ \\ __ _| | _____')} ${green('| _ \\ __ _| | _____')}
${green('| |_) / _` | |/ / _ \\')} ${green('| |_) / _` | |/ / _ \\')}
${green('| __/ (_| | < __/')} ${yellow('https://github.com/tw93/pake')} ${green('| __/ (_| | < __/')} ${yellow('https://github.com/tw93/pake')}
${green('|_| \\__,_|_|\\_\\___| can turn any webpage into a desktop app with Rust.')} ${green('|_| \\__,_|_|\\_\\___| can turn any webpage into a desktop app with Rust.')}
`; `;
program program
.addHelpText('beforeAll', logo) .addHelpText('beforeAll', logo)
@@ -1045,4 +1045,4 @@ program
await builder.prepare(); await builder.prepare();
await builder.build(url); await builder.build(url);
}); });
program.parse(); program.parse();

View File

@@ -1,6 +1,6 @@
{ {
"name": "pake-cli", "name": "pake-cli",
"version": "2.1.12-beta.0", "version": "2.2.0",
"description": "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 很简单的用 Rust 打包网页生成很小的桌面 App。", "description": "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 很简单的用 Rust 打包网页生成很小的桌面 App。",
"engines": { "engines": {
"node": ">=16.0.0" "node": ">=16.0.0"

1122
src-tauri/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -18,8 +18,7 @@ tauri-build = { version = "1.4.0", features = [] }
serde_json = "1.0.96" serde_json = "1.0.96"
serde = { version = "1.0.163", features = ["derive"] } serde = { version = "1.0.163", features = ["derive"] }
tauri = { version = "1.4.1", features = ["api-all", "system-tray"] } tauri = { version = "1.4.1", features = ["api-all", "system-tray"] }
download_rs = { version = "0.2.0", features = ["sync_download"] } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
[dev-dependencies] [dev-dependencies]
cargo-bloat = "0.11.1" cargo-bloat = "0.11.1"

BIN
src-tauri/icons/wechat.icns Normal file

Binary file not shown.

View File

@@ -1,8 +1,9 @@
use std::fs; use std::fs;
use crate::util::{check_file_or_append, get_download_message, MessageType, show_toast};
use crate::util::{check_file_or_append, get_download_message, show_toast};
use download_rs::sync_download::Download;
use tauri::{api, command, AppHandle, Manager, Window}; use tauri::{api, command, AppHandle, Manager, Window};
use tauri::api::http::{ClientBuilder, HttpRequestBuilder, ResponseType};
use std::fs::File;
use std::io::Write;
#[derive(serde::Deserialize)] #[derive(serde::Deserialize)]
pub struct DownloadFileParams { pub struct DownloadFileParams {
@@ -19,16 +20,29 @@ pub struct BinaryDownloadParams {
#[command] #[command]
pub async fn download_file(app: AppHandle, params: DownloadFileParams) -> Result<(), String> { pub async fn download_file(app: AppHandle, params: DownloadFileParams) -> Result<(), String> {
let window: Window = app.get_window("pake").unwrap(); let window: Window = app.get_window("pake").unwrap();
show_toast(&window, &get_download_message(MessageType::Start));
let output_path = api::path::download_dir().unwrap().join(params.filename); let output_path = api::path::download_dir().unwrap().join(params.filename);
let file_path = check_file_or_append(output_path.to_str().unwrap()); let file_path = check_file_or_append(output_path.to_str().unwrap());
let download = Download::new(&params.url, Some(&file_path), None); let client = ClientBuilder::new().build().unwrap();
match download.download() {
Ok(_) => { let response = client.send(
show_toast(&window, &get_download_message()); HttpRequestBuilder::new("GET", &params.url)
.unwrap()
.response_type(ResponseType::Binary)
).await;
match response {
Ok(res) => {
let bytes = res.bytes().await.unwrap().data;
let mut file = File::create(file_path).unwrap();
file.write_all(&bytes).unwrap();
show_toast(&window, &get_download_message(MessageType::Success));
Ok(()) Ok(())
} }
Err(e) => { Err(e) => {
show_toast(&window, &e.to_string()); show_toast(&window, &get_download_message(MessageType::Failure));
Err(e.to_string()) Err(e.to_string())
} }
} }
@@ -40,16 +54,17 @@ pub async fn download_file_by_binary(
params: BinaryDownloadParams, params: BinaryDownloadParams,
) -> Result<(), String> { ) -> Result<(), String> {
let window: Window = app.get_window("pake").unwrap(); let window: Window = app.get_window("pake").unwrap();
show_toast(&window, &get_download_message(MessageType::Start));
let output_path = api::path::download_dir().unwrap().join(params.filename); let output_path = api::path::download_dir().unwrap().join(params.filename);
let file_path = check_file_or_append(output_path.to_str().unwrap()); let file_path = check_file_or_append(output_path.to_str().unwrap());
let download_file_result = fs::write(file_path, &params.binary); let download_file_result = fs::write(file_path, &params.binary);
match download_file_result { match download_file_result {
Ok(_) => { Ok(_) => {
show_toast(&window, &get_download_message()); show_toast(&window, &get_download_message(MessageType::Success));
Ok(()) Ok(())
} }
Err(e) => { Err(e) => {
show_toast(&window, &e.to_string()); show_toast(&window, &get_download_message(MessageType::Failure));
Err(e.to_string()) Err(e.to_string())
} }
} }

View File

@@ -38,7 +38,6 @@ pub fn get_menu() -> Menu {
pub fn menu_event_handle(event: WindowMenuEvent) { pub fn menu_event_handle(event: WindowMenuEvent) {
if event.menu_item_id() == "close" { if event.menu_item_id() == "close" {
event.window().minimize().expect("can't minimize window"); event.window().minimize().expect("can't minimize window");
// event.window().eval("toggleVideoPlayback(true);").unwrap();
} }
if event.menu_item_id() == "goto_url" { if event.menu_item_id() == "goto_url" {

View File

@@ -96,18 +96,18 @@ document.addEventListener('DOMContentLoaded', () => {
const urlSubmit = document.getElementById('pakeUrlSubmit'); const urlSubmit = document.getElementById('pakeUrlSubmit');
const urlClose = document.getElementById('pakeUrlClose'); const urlClose = document.getElementById('pakeUrlClose');
urlSubmit.onclick = function () { urlSubmit.onclick = function() {
const url = urlInput.value; const url = urlInput.value;
if (url) { if (url) {
window.location.href = url; window.location.href = url;
} }
}; };
urlClose.onclick = function () { urlClose.onclick = function() {
urlModal.style.display = 'none'; urlModal.style.display = 'none';
}; };
urlInput.addEventListener('keydown', function (event) { urlInput.addEventListener('keydown', function(event) {
if (event.key === 'Enter') { if (event.key === 'Enter') {
const url = urlInput.value; const url = urlInput.value;
if (url) { if (url) {
@@ -116,13 +116,13 @@ document.addEventListener('DOMContentLoaded', () => {
} }
}); });
document.addEventListener('keydown', function (event) { document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && urlModal.style.display === 'block') { if (event.key === 'Escape' && urlModal.style.display === 'block') {
urlModal.style.display = 'none'; urlModal.style.display = 'none';
} }
}); });
window.showUrlModal = function () { window.showUrlModal = function() {
urlModal.style.display = 'block'; urlModal.style.display = 'block';
urlInput.focus(); urlInput.focus();
}; };
@@ -134,11 +134,11 @@ document.addEventListener('DOMContentLoaded', () => {
m.style.cssText = m.style.cssText =
'max-width:60%;min-width: 80px;padding:0 12px;height: 32px;color: rgb(255, 255, 255);line-height: 32px;text-align: center;border-radius: 8px;position: fixed; bottom:24px;right: 28px;z-index: 999999;background: rgba(0, 0, 0,.8);font-size: 13px;'; 'max-width:60%;min-width: 80px;padding:0 12px;height: 32px;color: rgb(255, 255, 255);line-height: 32px;text-align: center;border-radius: 8px;position: fixed; bottom:24px;right: 28px;z-index: 999999;background: rgba(0, 0, 0,.8);font-size: 13px;';
document.body.appendChild(m); document.body.appendChild(m);
setTimeout(function () { setTimeout(function() {
const d = 0.5; const d = 0.5;
m.style.transition = 'transform ' + d + 's ease-in, opacity ' + d + 's ease-in'; m.style.transition = 'transform ' + d + 's ease-in, opacity ' + d + 's ease-in';
m.style.opacity = '0'; m.style.opacity = '0';
setTimeout(function () { setTimeout(function() {
document.body.removeChild(m); document.body.removeChild(m);
}, d * 1000); }, d * 1000);
}, 3000); }, 3000);
@@ -146,35 +146,4 @@ document.addEventListener('DOMContentLoaded', () => {
window.pakeToast = pakeToast; window.pakeToast = pakeToast;
// chatgpt supports unlimited times of GPT4-Mobile
if (window.location.hostname === 'chat.openai.com') {
const originFetch = fetch;
window.fetch = (url, options) => {
return originFetch(url, options).then(async response => {
if (url.indexOf('/backend-api/models') === -1) {
return response;
}
const responseClone = response.clone();
let res = await responseClone.json();
res.models = res.models.map(m => {
m.tags = m.tags.filter(t => {
return t !== 'mobile';
});
if (m.slug === 'gpt-4-mobile') {
res.categories.push({
browsing_model: null,
category: 'gpt_4',
code_interpreter_model: null,
default_model: 'gpt-4-mobile',
human_category_name: 'GPT-4-Mobile',
plugins_model: null,
subscription_level: 'plus',
});
}
return m;
});
return new Response(JSON.stringify(res), response);
});
};
}
}); });

View File

@@ -1,17 +1,13 @@
const shortcuts = { const shortcuts = {
ArrowUp: () => scrollTo(0, 0), 'ArrowUp': () => scrollTo(0, 0),
ArrowDown: () => scrollTo(0, document.body.scrollHeight), 'ArrowDown': () => scrollTo(0, document.body.scrollHeight),
// Don't use command + ArrowLeft or command + ArrowRight
// When editing text in page, it causes unintended page navigation.
// ArrowLeft: () => window.history.back(),
// ArrowRight: () => window.history.forward(),
'[': () => window.history.back(), '[': () => window.history.back(),
']': () => window.history.forward(), ']': () => window.history.forward(),
r: () => window.location.reload(), 'r': () => window.location.reload(),
'-': () => zoomOut(), '-': () => zoomOut(),
'=': () => zoomIn(), '=': () => zoomIn(),
'+': () => zoomIn(), '+': () => zoomIn(),
0: () => setZoom('100%'), '0': () => setZoom('100%'),
}; };
function setZoom(zoom) { function setZoom(zoom) {
@@ -40,46 +36,6 @@ function handleShortcut(event) {
} }
} }
//这里参考 ChatGPT 的代码
const uid = () => window.crypto.getRandomValues(new Uint32Array(1))[0];
function transformCallback(callback = () => {}, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback(result);
},
writable: false,
configurable: true,
});
return identifier;
}
async function invoke(cmd, args) {
return new Promise((resolve, reject) => {
if (!window.__TAURI_POST_MESSAGE__)
reject('__TAURI_POST_MESSAGE__ does not exist~');
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_POST_MESSAGE__({
cmd,
callback,
error,
...args,
});
});
}
// Judgment of file download. // Judgment of file download.
function isDownloadLink(url) { function isDownloadLink(url) {
const fileExtensions = [ const fileExtensions = [
@@ -105,6 +61,7 @@ function externalTargetLink() {
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const tauri = window.__TAURI__; const tauri = window.__TAURI__;
const appWindow = tauri.window.appWindow; const appWindow = tauri.window.appWindow;
const invoke = tauri.tauri.invoke;
const topDom = document.createElement('div'); const topDom = document.createElement('div');
topDom.id = 'pack-top-dom'; topDom.id = 'pack-top-dom';
@@ -137,44 +94,39 @@ document.addEventListener('DOMContentLoaded', () => {
} }
}); });
const specialDownloadProtocal = ['blob', 'data']; const isExternalLink = (url, host) => window.location.host !== host;
// process special download protocal['data:','blob:']
const isSpecialDownload = (url) => ['blob', 'data'].some(protocal => url.startsWith(protocal));
const isDownloadRequired = (url, anchorElement, e) =>
anchorElement.download || e.metaKey || e.ctrlKey || isDownloadLink(url);
const handleExternalLink = (e, url) => {
e.preventDefault();
tauri.shell.open(url);
};
const handleDownloadLink = (e, url, filename) => {
e.preventDefault();
invoke('download_file', { params: { url, filename } });
};
const detectAnchorElementClick = (e) => { const detectAnchorElementClick = (e) => {
const anchorElement = e.target.closest('a'); const anchorElement = e.target.closest('a');
if (anchorElement && anchorElement.href) { if (anchorElement && anchorElement.href) {
const target = anchorElement.target;
anchorElement.target = '_self';
const hrefUrl = new URL(anchorElement.href); const hrefUrl = new URL(anchorElement.href);
const absoluteUrl = hrefUrl.href; const absoluteUrl = hrefUrl.href;
let filename = anchorElement.download || getFilenameFromUrl(absoluteUrl);
// Handling external link redirection. // Handling external link redirection.
if ( if (isExternalLink(absoluteUrl, hrefUrl.host) && (['_blank', '_new'].includes(anchorElement.target) || externalTargetLink())) {
window.location.host !== hrefUrl.host && handleExternalLink(e, absoluteUrl);
(target === '_blank' || target === '_new' || externalTargetLink())
) {
e.preventDefault && e.preventDefault();
tauri.shell.open(absoluteUrl);
return; return;
} }
let filename = anchorElement.download || getFilenameFromUrl(absoluteUrl);
// Process download links for Rust to handle. // Process download links for Rust to handle.
// If the download attribute is set, the download attribute is used as the file name. if (isDownloadRequired(absoluteUrl, anchorElement, e) && !externalDownLoadLink() && !isSpecialDownload(absoluteUrl)) {
if ( handleDownloadLink(e, absoluteUrl, filename);
(anchorElement.download ||
e.metaKey ||
e.ctrlKey ||
isDownloadLink(absoluteUrl)) &&
!externalDownLoadLink() && specialDownloadProtocal.every(protocal => !absoluteUrl.startsWith(protocal))
) {
e.preventDefault();
invoke('download_file', {
params: {
url: absoluteUrl,
filename,
},
});
} }
} }
}; };
@@ -208,6 +160,12 @@ document.addEventListener('DOMContentLoaded', () => {
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
// Fix Chinese input method "Enter" on Safari
document.addEventListener('keydown', (e) => {
if (e.keyCode === 229) e.stopPropagation();
}, true);
}); });
function setDefaultZoom() { function setDefaultZoom() {
@@ -219,26 +177,7 @@ function setDefaultZoom() {
function getFilenameFromUrl(url) { function getFilenameFromUrl(url) {
const urlPath = new URL(url).pathname; const urlPath = new URL(url).pathname;
const filename = urlPath.substring(urlPath.lastIndexOf('/') + 1); return urlPath.substring(urlPath.lastIndexOf('/') + 1);
return filename;
}
function removeUrlParameters(url) {
const parsedUrl = new URL(url);
parsedUrl.search = '';
return parsedUrl.toString();
}
// Toggle video playback when the window is hidden.
function toggleVideoPlayback(pause) {
const videos = document.getElementsByTagName('video');
for (const video of videos) {
if (pause) {
video.pause();
} else {
video.play();
}
}
} }
// Collect blob urls to blob by overriding window.URL.createObjectURL // Collect blob urls to blob by overriding window.URL.createObjectURL
@@ -297,6 +236,7 @@ function downloadFromBlobUrl(blobUrl, filename) {
}); });
} }
// detect blob download by createElement("a") // detect blob download by createElement("a")
function detectDownloadByCreateAnchor() { function detectDownloadByCreateAnchor() {
const createEle = document.createElement; const createEle = document.createElement;
@@ -319,3 +259,10 @@ function detectDownloadByCreateAnchor() {
return anchorEle; return anchorEle;
}; };
} }
// Determine the language of the current system.
function getSystemLanguage() {
const lang = navigator.language.substr(0, 2);
return lang === 'ch' ? 'ch' : 'en';
}

View File

@@ -171,6 +171,7 @@ window.addEventListener('DOMContentLoaded', _event => {
#react-root [data-testid="AppTabBar_Explore_Link"], #react-root [data-testid="AppTabBar_Explore_Link"],
#react-root a[href*="/lists"][role="link"][aria-label], #react-root a[href*="/lists"][role="link"][aria-label],
#react-root a[href*="/i/communitynotes"][role="link"][aria-label], #react-root a[href*="/i/communitynotes"][role="link"][aria-label],
#react-root a[role="link"][aria-label="Communities"],
#react-root a[href*="/i/verified-orgs-signup"][role="link"][aria-label] { #react-root a[href*="/i/verified-orgs-signup"][role="link"][aria-label] {
display: none !important; display: none !important;
} }

View File

@@ -56,7 +56,6 @@ pub fn run_app() {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
event.window().minimize().unwrap(); event.window().minimize().unwrap();
// event.window().eval("toggleVideoPlayback(true);").unwrap();
} }
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]

View File

@@ -40,19 +40,43 @@ pub fn show_toast(window: &Window, message: &str) {
window.eval(&script).unwrap(); window.eval(&script).unwrap();
} }
pub fn get_download_message() -> String { pub enum MessageType {
let default_message = "Download successful, saved to download directory~"; Start,
let chinese_message = "下载成功,已保存到下载目录~"; Success,
Failure,
}
pub fn get_download_message(message_type: MessageType) -> String {
let default_start_message = "Start downloading~";
let chinese_start_message = "开始下载中~";
let default_success_message = "Download successful, saved to download directory~";
let chinese_success_message = "下载成功,已保存到下载目录~";
let default_failure_message = "Download failed, please check your network connection~";
let chinese_failure_message = "下载失败,请检查你的网络连接~";
env::var("LANG") env::var("LANG")
.map(|lang| { .map(|lang| {
if lang.starts_with("zh") { if lang.starts_with("zh") {
chinese_message match message_type {
MessageType::Start => chinese_start_message,
MessageType::Success => chinese_success_message,
MessageType::Failure => chinese_failure_message,
}
} else { } else {
default_message match message_type {
MessageType::Start => default_start_message,
MessageType::Success => default_success_message,
MessageType::Failure => default_failure_message,
}
} }
}) })
.unwrap_or(default_message) .unwrap_or_else(|_| match message_type {
MessageType::Start => default_start_message,
MessageType::Success => default_success_message,
MessageType::Failure => default_failure_message,
})
.to_string() .to_string()
} }