初始化
This commit is contained in:
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
BIN
assets/icon.ico
Normal file
BIN
assets/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
268
index.html
Normal file
268
index.html
Normal file
@@ -0,0 +1,268 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>YOLO 更新检查</title>
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; style-src 'unsafe-inline' 'self'; script-src 'self' 'unsafe-inline'; img-src 'self' data:;">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<style>
|
||||
:root {
|
||||
--bg: #0b1220;
|
||||
--card: #0f172a;
|
||||
--text: #e5e7eb;
|
||||
--muted: #9ca3af;
|
||||
--accent: #60a5fa;
|
||||
--accent-2: #34d399;
|
||||
--bar-bg: #1f2937;
|
||||
--bar-fg: linear-gradient(90deg, var(--accent), var(--accent-2));
|
||||
--ok: #34d399;
|
||||
--error: #ef4444;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--bg: #f8fafc;
|
||||
--card: #ffffff;
|
||||
--text: #0f172a;
|
||||
--muted: #64748b;
|
||||
--bar-bg: #e5e7eb;
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
|
||||
background: radial-gradient(1200px 600px at 20% -10%, rgba(96, 165, 250, .25), transparent 50%),
|
||||
radial-gradient(1200px 600px at 120% 120%, rgba(52, 211, 153, .25), transparent 50%),
|
||||
var(--bg);
|
||||
color: var(--text);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 560px;
|
||||
max-width: calc(100% - 40px);
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, .04), rgba(255, 255, 255, 0)), var(--card);
|
||||
border: 1px solid rgba(255, 255, 255, .08);
|
||||
border-radius: 20px;
|
||||
padding: 28px;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, .25);
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(135deg, var(--accent), var(--accent-2));
|
||||
display: grid;
|
||||
place-items: center;
|
||||
color: white;
|
||||
font-weight: 900;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, .3);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 18px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sub {
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.status {
|
||||
margin: 20px 0 16px;
|
||||
padding: 12px 14px;
|
||||
background: rgba(255, 255, 255, .04);
|
||||
border: 1px dashed rgba(255, 255, 255, .18);
|
||||
border-radius: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.progress-wrap {
|
||||
background: var(--bar-bg);
|
||||
border-radius: 999px;
|
||||
overflow: hidden;
|
||||
height: 14px;
|
||||
width: 100%;
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, .25);
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 100%;
|
||||
width: 0%;
|
||||
background: var(--bar-fg);
|
||||
transition: width .25s ease;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 14px;
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin-top: 18px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
button {
|
||||
appearance: none;
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
padding: 10px 14px;
|
||||
cursor: pointer;
|
||||
background: linear-gradient(90deg, var(--accent), var(--accent-2));
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
box-shadow: 0 6px 18px rgba(56, 189, 248, .35);
|
||||
}
|
||||
|
||||
button.ghost {
|
||||
background: transparent;
|
||||
border: 1px solid rgba(255, 255, 255, .18);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.ok {
|
||||
color: var(--ok);
|
||||
}
|
||||
|
||||
.err {
|
||||
color: var(--error);
|
||||
}
|
||||
|
||||
.fade {
|
||||
animation: fade .3s ease both;
|
||||
}
|
||||
|
||||
@keyframes fade {
|
||||
from {
|
||||
opacity: .0;
|
||||
transform: translateY(6px)
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: none
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="card fade">
|
||||
<div class="header">
|
||||
<div class="logo">PY</div>
|
||||
<div>
|
||||
<h1>YOLO 启动 / 更新检查</h1>
|
||||
<div class="sub">为你自动检查可用更新并在后台下载</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="status" class="status">正在初始化…</div>
|
||||
|
||||
<div class="progress-wrap" aria-label="下载进度">
|
||||
<div id="bar" class="progress-bar"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div>速度:<span id="speed">0</span> MB/s</div>
|
||||
<div>已下:<span id="transferred">0</span>/<span id="total">0</span> MB</div>
|
||||
<div>进度:<span id="percent">0</span>%</div>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button id="btn-install" style="display:none;">立即重启安装</button>
|
||||
<button id="btn-hide" class="ghost">最小化到托盘</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const statusEl = $('status');
|
||||
const bar = $('bar');
|
||||
const sp = $('speed'), tf = $('transferred'), tt = $('total'), pc = $('percent');
|
||||
const btnInstall = $('btn-install');
|
||||
const btnHide = $('btn-hide');
|
||||
|
||||
// 订阅主进程事件
|
||||
window.electronAPI.onUpdateStatus(({ status, version, notes, currentVersion, message }) => {
|
||||
switch (status) {
|
||||
case 'checking':
|
||||
statusEl.textContent = '正在检查更新…';
|
||||
break;
|
||||
case 'available':
|
||||
statusEl.innerHTML = `检测到新版本 <b>v${version}</b>,正在下载…`;
|
||||
break;
|
||||
case 'none':
|
||||
statusEl.innerHTML = `已是最新版本 <span class="ok">(v${currentVersion})</span>。3 秒后自动最小化。`;
|
||||
bar.style.width = '100%'; pc.textContent = '100';
|
||||
setTimeout(() => window.close(), 3000);
|
||||
break;
|
||||
case 'downloaded':
|
||||
statusEl.innerHTML = `下载完成!可立即安装更新 <b>v${version}</b>。`;
|
||||
bar.style.width = '100%'; pc.textContent = '100';
|
||||
btnInstall.style.display = '';
|
||||
// 也可自动倒计时安装:
|
||||
// setTimeout(() => btnInstall.click(), 3000);
|
||||
break;
|
||||
case 'error':
|
||||
statusEl.innerHTML = `更新失败:<span class="err">${message || '未知错误'}</span>`;
|
||||
break;
|
||||
default:
|
||||
statusEl.textContent = '状态:' + status;
|
||||
}
|
||||
});
|
||||
|
||||
window.electronAPI.onUpdateProgress(({ percent, transferred, total, speed }) => {
|
||||
bar.style.width = Math.max(0, Math.min(100, percent || 0)) + '%';
|
||||
sp.textContent = speed ?? 0;
|
||||
tf.textContent = transferred ?? 0;
|
||||
tt.textContent = total ?? 0;
|
||||
pc.textContent = (percent ?? 0).toFixed(1);
|
||||
});
|
||||
|
||||
// 交互
|
||||
btnInstall.addEventListener('click', () => {
|
||||
statusEl.textContent = '即将重启并安装更新…';
|
||||
window.electronAPI.installNow();
|
||||
});
|
||||
|
||||
btnHide.addEventListener('click', () => {
|
||||
window.close(); // 在 main.js 里拦截 close -> hide()
|
||||
});
|
||||
|
||||
// 首次加载立即请求检查
|
||||
window.electronAPI.checkForUpdates();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
228
main.js
Normal file
228
main.js
Normal file
@@ -0,0 +1,228 @@
|
||||
// main.js
|
||||
const { app, Tray, Menu, dialog, BrowserWindow, ipcMain, nativeTheme } = require('electron');
|
||||
const { autoUpdater } = require('electron-updater');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const { spawn, spawnSync, exec } = require('child_process');
|
||||
const log = require('electron-log');
|
||||
|
||||
Object.assign(console, log.functions);
|
||||
|
||||
const ALLOW_UNSIGNED = process.env.YOLO_ALLOW_UNSIGNED === '1';
|
||||
let installTriggered = false; // NEW: 防止重复触发安装
|
||||
|
||||
// ===== 全局状态 =====
|
||||
let tray = null;
|
||||
let managedChild = null;
|
||||
let quitting = false;
|
||||
let updateWin = null;
|
||||
let pythonStarted = false; // NEW: 已启动 tkpage?
|
||||
let updaterKicked = false; // NEW: 是否已触发检查
|
||||
|
||||
// ===== tkpage 路径 =====
|
||||
function resolveExePath() {
|
||||
const devExe = path.resolve(__dirname, 'resources', 'python', 'tkpage.exe');
|
||||
const prodExe = path.join(process.resourcesPath, 'python', 'tkpage.exe');
|
||||
return app.isPackaged ? prodExe : devExe;
|
||||
}
|
||||
|
||||
// ===== 启动 tkpage(只会启动一次) =====
|
||||
function launchPythonIfNeeded() {
|
||||
if (pythonStarted) return;
|
||||
const exe = resolveExePath();
|
||||
const cwd = path.dirname(exe);
|
||||
|
||||
console.info('[tkpage exe]', exe);
|
||||
if (!fs.existsSync(exe)) {
|
||||
dialog.showErrorBox('启动失败', `未找到可执行文件:\n${exe}`);
|
||||
return;
|
||||
}
|
||||
|
||||
pythonStarted = true;
|
||||
managedChild = spawn(exe, [], {
|
||||
cwd,
|
||||
windowsHide: false,
|
||||
detached: false,
|
||||
stdio: 'ignore',
|
||||
});
|
||||
|
||||
managedChild.on('exit', (code, signal) => {
|
||||
console.info(`[tkpage] exit code=${code} signal=${signal}`);
|
||||
if (!quitting) { quitting = true; app.quit(); }
|
||||
});
|
||||
managedChild.on('close', (code, signal) => {
|
||||
console.info(`[tkpage] close code=${code} signal=${signal}`);
|
||||
if (!quitting) { quitting = true; app.quit(); }
|
||||
});
|
||||
}
|
||||
|
||||
// ===== 结束 tkpage =====
|
||||
function killPythonGUI(killSelf = true) {
|
||||
if (managedChild && managedChild.pid) {
|
||||
try { process.kill(managedChild.pid); } catch (e) {
|
||||
console.warn('[kill] managed kill error:', e?.message || e);
|
||||
} finally { managedChild = null; }
|
||||
}
|
||||
try { spawnSync('taskkill', ['/f', '/t', '/im', 'tkpage.exe'], { windowsHide: true }); } catch { }
|
||||
|
||||
if (killSelf) {
|
||||
try { exec('taskkill /IM YOLO助手.exe /F'); } catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 托盘 =====
|
||||
function createTray() {
|
||||
const iconPath = path.join(__dirname, 'assets', 'icon.ico');
|
||||
tray = new Tray(iconPath);
|
||||
const menu = Menu.buildFromTemplate([
|
||||
{ label: '检查更新', click: () => startUpdateCheck(/*force*/true) },
|
||||
{ type: 'separator' },
|
||||
{ label: '显示更新窗口', click: () => { if (updateWin) { updateWin.show(); updateWin.focus(); } else { createUpdateWindow(); } } },
|
||||
{ type: 'separator' },
|
||||
{ label: '重启 Python GUI', click: () => { killPythonGUI(); pythonStarted = false; launchPythonIfNeeded(); } },
|
||||
{ type: 'separator' },
|
||||
{ label: '退出', click: () => { quitting = true; killPythonGUI(); app.quit(); } },
|
||||
]);
|
||||
tray.setToolTip('YOLO');
|
||||
tray.setContextMenu(menu);
|
||||
}
|
||||
|
||||
// ===== 更新窗口 =====
|
||||
function createUpdateWindow() {
|
||||
if (updateWin && !updateWin.isDestroyed()) { updateWin.show(); updateWin.focus(); return; }
|
||||
updateWin = new BrowserWindow({
|
||||
width: 640, height: 420, resizable: false, fullscreenable: false, maximizable: false,
|
||||
autoHideMenuBar: true, show: true, center: true,
|
||||
backgroundColor: nativeTheme.shouldUseDarkColors ? '#0b1220' : '#ffffff',
|
||||
icon: path.join(__dirname, 'assets', 'icon.ico'),
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
contextIsolation: true, nodeIntegration: false, sandbox: true,
|
||||
}
|
||||
});
|
||||
updateWin.on('close', (e) => { e.preventDefault(); updateWin.hide(); });
|
||||
updateWin.loadFile(path.join(__dirname, 'index.html')).catch(err => console.error('[updateWin] load error', err));
|
||||
}
|
||||
|
||||
// ===== Updater 事件桥接到渲染进程,并控制 tkpage 启动时机 =====
|
||||
function wireUpdaterIpc() {
|
||||
if (ALLOW_UNSIGNED) {
|
||||
console.warn('[updater] verifyUpdateCodeSignature disabled (YOLO_ALLOW_UNSIGNED=1)');
|
||||
autoUpdater.verifyUpdateCodeSignature = async () => null;
|
||||
}
|
||||
autoUpdater.autoDownload = true;
|
||||
autoUpdater.autoInstallOnAppQuit = false;
|
||||
|
||||
const send = (ch, data) => { if (updateWin && !updateWin.isDestroyed()) updateWin.webContents.send(ch, data); };
|
||||
|
||||
autoUpdater.on('checking-for-update', () => {
|
||||
console.info('[updater] Checking');
|
||||
tray?.setToolTip('YOLO - 正在检查更新…');
|
||||
send('update:status', { status: 'checking' });
|
||||
});
|
||||
|
||||
autoUpdater.on('update-available', (info) => {
|
||||
console.info('[updater] Available', info?.version);
|
||||
tray?.setToolTip(`YOLO - 检测到新版本 v${info?.version},开始下载…`);
|
||||
send('update:status', { status: 'available', version: info?.version, notes: info?.releaseNotes || '' });
|
||||
// 此时不启动 tkpage,等待下载完成
|
||||
});
|
||||
|
||||
autoUpdater.on('update-not-available', (info) => {
|
||||
console.info('[updater] None');
|
||||
tray?.setToolTip('YOLO - 已是最新版本');
|
||||
send('update:status', { status: 'none', currentVersion: app.getVersion(), info });
|
||||
// ✅ 没有更新,立刻启动 tkpage
|
||||
launchPythonIfNeeded();
|
||||
// 可隐藏更新窗口(让应用留在托盘+tkpage前台)
|
||||
setTimeout(() => updateWin?.hide(), 1200);
|
||||
});
|
||||
|
||||
autoUpdater.on('download-progress', (p) => {
|
||||
const percent = Math.max(0, Math.min(100, p?.percent || 0));
|
||||
const transferred = Math.floor((p?.transferred || 0) / 1024 / 1024);
|
||||
const total = Math.floor((p?.total || 0) / 1024 / 1024);
|
||||
const speed = Math.floor((p?.bytesPerSecond || 0) / 1024 / 1024);
|
||||
tray?.setToolTip(`YOLO - 正在下载更新:${percent.toFixed(1)}%`);
|
||||
send('update:progress', { percent, transferred, total, speed });
|
||||
});
|
||||
|
||||
autoUpdater.on('update-downloaded', (info) => {
|
||||
console.info('[updater] Downloaded', info?.version);
|
||||
tray?.setToolTip('YOLO - 更新已下载,等待安装…');
|
||||
// 仅通知渲染进程显示“立即安装”按钮;不自动安装
|
||||
send('update:status', { status: 'downloaded', version: info?.version });
|
||||
// 可选择把更新窗口确保前置
|
||||
if (updateWin && !updateWin.isDestroyed()) { updateWin.show(); updateWin.focus(); }
|
||||
});
|
||||
|
||||
autoUpdater.on('error', (err) => {
|
||||
const msg = err?.message || String(err);
|
||||
console.error('[updater] error', msg);
|
||||
tray?.setToolTip('YOLO - 更新失败');
|
||||
dialog.showErrorBox('自动更新失败', msg);
|
||||
send('update:status', { status: 'error', message: msg });
|
||||
// ⚠️ 出错:不阻断主流程,直接启动 tkpage
|
||||
launchPythonIfNeeded();
|
||||
});
|
||||
|
||||
// 渲染侧手动触发
|
||||
ipcMain.on('updater:check', () => startUpdateCheck(/*force*/true));
|
||||
ipcMain.on('updater:install-now', () => {
|
||||
if (installTriggered) return;
|
||||
installTriggered = true;
|
||||
|
||||
console.info('[updater] quitAndInstall requested by renderer');
|
||||
tray?.setToolTip('YOLO - 正在安装更新…');
|
||||
|
||||
quitting = true;
|
||||
try { killPythonGUI(false); } catch (e) {
|
||||
console.warn('[updater] killPythonGUI error:', e?.message || e);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
try {
|
||||
autoUpdater.quitAndInstall(false, true);
|
||||
} catch (e) {
|
||||
installTriggered = false;
|
||||
console.error('[updater] quitAndInstall error:', e?.message || e);
|
||||
dialog.showErrorBox('安装失败', String(e?.message || e));
|
||||
}
|
||||
}, 300);
|
||||
});
|
||||
}
|
||||
|
||||
// ===== 触发更新检查(仅触发一次,托盘点“检查更新”可强制再触发) =====
|
||||
function startUpdateCheck(force = false) {
|
||||
if (updaterKicked && !force) return;
|
||||
updaterKicked = true;
|
||||
// 显示更新窗口(可选:你也可以只在有更新时显示)
|
||||
if (!updateWin || updateWin.isDestroyed()) createUpdateWindow();
|
||||
else { updateWin.show(); updateWin.focus(); }
|
||||
autoUpdater.checkForUpdates().catch(() => { /* 错误会在 on('error') 里处理 */ });
|
||||
}
|
||||
|
||||
// ===== 单例 & 生命周期 =====
|
||||
process.on('unhandledRejection', (r) => console.error('[unhandledRejection]', r));
|
||||
process.on('uncaughtException', (e) => console.error('[uncaughtException]', e));
|
||||
|
||||
const gotLock = app.requestSingleInstanceLock();
|
||||
if (!gotLock) {
|
||||
app.quit();
|
||||
} else {
|
||||
app.on('second-instance', () => { if (updateWin) { updateWin.show(); updateWin.focus(); } });
|
||||
|
||||
app.whenReady().then(() => {
|
||||
if (process.platform === 'win32') {
|
||||
app.setAppUserModelId('com.yolozs.newPage');
|
||||
}
|
||||
createTray();
|
||||
createUpdateWindow();
|
||||
wireUpdaterIpc();
|
||||
// ✅ 启动时:只检查更新,不启动 tkpage。无更新 → 启动;有更新 → 下载并重启安装。
|
||||
startUpdateCheck();
|
||||
});
|
||||
|
||||
app.on('before-quit', () => { quitting = true; killPythonGUI(true); });
|
||||
app.on('window-all-closed', () => { /* 后台常驻 */ });
|
||||
}
|
||||
6840
package-lock.json
generated
Normal file
6840
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
49
package.json
Normal file
49
package.json
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "YOLO",
|
||||
"productName": "YOLO助手",
|
||||
"version": "4.7.0",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "electron .",
|
||||
"build": "electron-builder"
|
||||
},
|
||||
"dependencies": {
|
||||
"electron-log": "^5",
|
||||
"electron-updater": "^6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^31",
|
||||
"electron-builder": "^24"
|
||||
},
|
||||
"build": {
|
||||
"appId": "com.yolozs.newPage",
|
||||
"productName": "YOLO助手",
|
||||
"asar": true,
|
||||
"icon": "icon.ico",
|
||||
"win": {
|
||||
"target": "nsis"
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"allowElevation": true,
|
||||
"allowToChangeInstallationDirectory": true,
|
||||
"perMachine": false,
|
||||
"deleteAppDataOnUninstall": false
|
||||
},
|
||||
"publish": [
|
||||
{
|
||||
"provider": "generic",
|
||||
"url": "http://tkNewPage.yolozs.com/updata/"
|
||||
}
|
||||
],
|
||||
"extraResources": [
|
||||
{
|
||||
"from": "resources/python",
|
||||
"to": "python",
|
||||
"filter": [
|
||||
"**/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
13
preload.js
Normal file
13
preload.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// preload.js
|
||||
const { contextBridge, ipcRenderer } = require('electron');
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
// 主动触发检查
|
||||
checkForUpdates: () => ipcRenderer.send('updater:check'),
|
||||
// 安装更新
|
||||
installNow: () => ipcRenderer.send('updater:install-now'),
|
||||
// 订阅状态
|
||||
onUpdateStatus: (cb) => ipcRenderer.on('update:status', (_e, payload) => cb(payload)),
|
||||
// 订阅进度
|
||||
onUpdateProgress: (cb) => ipcRenderer.on('update:progress', (_e, payload) => cb(payload)),
|
||||
});
|
||||
BIN
resources/python/PIL/_imaging.pyd
Normal file
BIN
resources/python/PIL/_imaging.pyd
Normal file
Binary file not shown.
BIN
resources/python/PIL/_imagingcms.pyd
Normal file
BIN
resources/python/PIL/_imagingcms.pyd
Normal file
Binary file not shown.
BIN
resources/python/PIL/_imagingmath.pyd
Normal file
BIN
resources/python/PIL/_imagingmath.pyd
Normal file
Binary file not shown.
BIN
resources/python/PIL/_imagingtk.pyd
Normal file
BIN
resources/python/PIL/_imagingtk.pyd
Normal file
Binary file not shown.
BIN
resources/python/PIL/_webp.pyd
Normal file
BIN
resources/python/PIL/_webp.pyd
Normal file
Binary file not shown.
BIN
resources/python/PySide6/QtCore.pyd
Normal file
BIN
resources/python/PySide6/QtCore.pyd
Normal file
Binary file not shown.
BIN
resources/python/PySide6/QtGui.pyd
Normal file
BIN
resources/python/PySide6/QtGui.pyd
Normal file
Binary file not shown.
BIN
resources/python/PySide6/QtNetwork.pyd
Normal file
BIN
resources/python/PySide6/QtNetwork.pyd
Normal file
Binary file not shown.
BIN
resources/python/PySide6/QtPrintSupport.pyd
Normal file
BIN
resources/python/PySide6/QtPrintSupport.pyd
Normal file
Binary file not shown.
BIN
resources/python/PySide6/QtSvg.pyd
Normal file
BIN
resources/python/PySide6/QtSvg.pyd
Normal file
Binary file not shown.
BIN
resources/python/PySide6/QtWebChannel.pyd
Normal file
BIN
resources/python/PySide6/QtWebChannel.pyd
Normal file
Binary file not shown.
BIN
resources/python/PySide6/QtWebEngineCore.pyd
Normal file
BIN
resources/python/PySide6/QtWebEngineCore.pyd
Normal file
Binary file not shown.
BIN
resources/python/PySide6/QtWebEngineWidgets.pyd
Normal file
BIN
resources/python/PySide6/QtWebEngineWidgets.pyd
Normal file
Binary file not shown.
BIN
resources/python/PySide6/QtWidgets.pyd
Normal file
BIN
resources/python/PySide6/QtWidgets.pyd
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/iconengines/qsvgicon.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/iconengines/qsvgicon.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/imageformats/qgif.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/imageformats/qgif.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/imageformats/qicns.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/imageformats/qicns.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/imageformats/qico.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/imageformats/qico.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/imageformats/qjpeg.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/imageformats/qjpeg.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/imageformats/qpdf.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/imageformats/qpdf.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/imageformats/qsvg.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/imageformats/qsvg.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/imageformats/qtga.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/imageformats/qtga.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/imageformats/qtiff.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/imageformats/qtiff.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/imageformats/qwbmp.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/imageformats/qwbmp.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/imageformats/qwebp.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/imageformats/qwebp.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/platforms/qdirect2d.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/platforms/qdirect2d.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/platforms/qminimal.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/platforms/qminimal.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/platforms/qoffscreen.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/platforms/qoffscreen.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/platforms/qwindows.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/platforms/qwindows.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/tls/qcertonlybackend.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/tls/qcertonlybackend.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/tls/qopensslbackend.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/tls/qopensslbackend.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/qt-plugins/tls/qschannelbackend.dll
Normal file
BIN
resources/python/PySide6/qt-plugins/tls/qschannelbackend.dll
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_ar.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_ar.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_bg.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_bg.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_cs.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_cs.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_da.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_da.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_de.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_de.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_en.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_en.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_es.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_es.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_fr.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_fr.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_hr.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_hr.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_hu.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_hu.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_ja.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_ja.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_ka.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_ka.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_ko.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_ko.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_nl.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_nl.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_pl.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_pl.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_pt_BR.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_pt_BR.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_ru.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_ru.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_sk.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_sk.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_sl.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_sl.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_sv.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_sv.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_tr.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_tr.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_uk.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_uk.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_zh_CN.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_zh_CN.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/assistant_zh_TW.qm
Normal file
BIN
resources/python/PySide6/translations/assistant_zh_TW.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_ar.qm
Normal file
BIN
resources/python/PySide6/translations/designer_ar.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_bg.qm
Normal file
BIN
resources/python/PySide6/translations/designer_bg.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_cs.qm
Normal file
BIN
resources/python/PySide6/translations/designer_cs.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_da.qm
Normal file
BIN
resources/python/PySide6/translations/designer_da.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_de.qm
Normal file
BIN
resources/python/PySide6/translations/designer_de.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_en.qm
Normal file
BIN
resources/python/PySide6/translations/designer_en.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_es.qm
Normal file
BIN
resources/python/PySide6/translations/designer_es.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_fr.qm
Normal file
BIN
resources/python/PySide6/translations/designer_fr.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_hr.qm
Normal file
BIN
resources/python/PySide6/translations/designer_hr.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_hu.qm
Normal file
BIN
resources/python/PySide6/translations/designer_hu.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_ja.qm
Normal file
BIN
resources/python/PySide6/translations/designer_ja.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_ka.qm
Normal file
BIN
resources/python/PySide6/translations/designer_ka.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_ko.qm
Normal file
BIN
resources/python/PySide6/translations/designer_ko.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_nl.qm
Normal file
BIN
resources/python/PySide6/translations/designer_nl.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_pl.qm
Normal file
BIN
resources/python/PySide6/translations/designer_pl.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_ru.qm
Normal file
BIN
resources/python/PySide6/translations/designer_ru.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_sk.qm
Normal file
BIN
resources/python/PySide6/translations/designer_sk.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_sl.qm
Normal file
BIN
resources/python/PySide6/translations/designer_sl.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_sv.qm
Normal file
BIN
resources/python/PySide6/translations/designer_sv.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_tr.qm
Normal file
BIN
resources/python/PySide6/translations/designer_tr.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_uk.qm
Normal file
BIN
resources/python/PySide6/translations/designer_uk.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_zh_CN.qm
Normal file
BIN
resources/python/PySide6/translations/designer_zh_CN.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/designer_zh_TW.qm
Normal file
BIN
resources/python/PySide6/translations/designer_zh_TW.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/linguist_ar.qm
Normal file
BIN
resources/python/PySide6/translations/linguist_ar.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/linguist_bg.qm
Normal file
BIN
resources/python/PySide6/translations/linguist_bg.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/linguist_cs.qm
Normal file
BIN
resources/python/PySide6/translations/linguist_cs.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/linguist_da.qm
Normal file
BIN
resources/python/PySide6/translations/linguist_da.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/linguist_de.qm
Normal file
BIN
resources/python/PySide6/translations/linguist_de.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/linguist_en.qm
Normal file
BIN
resources/python/PySide6/translations/linguist_en.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/linguist_es.qm
Normal file
BIN
resources/python/PySide6/translations/linguist_es.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/linguist_fr.qm
Normal file
BIN
resources/python/PySide6/translations/linguist_fr.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/linguist_hr.qm
Normal file
BIN
resources/python/PySide6/translations/linguist_hr.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/linguist_hu.qm
Normal file
BIN
resources/python/PySide6/translations/linguist_hu.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/linguist_it.qm
Normal file
BIN
resources/python/PySide6/translations/linguist_it.qm
Normal file
Binary file not shown.
BIN
resources/python/PySide6/translations/linguist_ja.qm
Normal file
BIN
resources/python/PySide6/translations/linguist_ja.qm
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user