feat: auto-updater integration
- Install electron-updater - New updater.ts: check/download/install with progress events - IPC: updater:check, updater:download, updater:install, updater:status - Preload bridge for updater API - electron-builder publish config (github provider) - Fix build files path: out -> electron-dist - i18n keys for updater notifications (zh-CN + en)
This commit is contained in:
+1
-1
@@ -15,7 +15,7 @@
|
||||
|
||||
- [x] **内存分析** — `MEMORY USAGE` 扫描所有 key,虚拟化列表,按大小排序,暂停/恢复,大小过滤
|
||||
- [x] **命令日志** — 记录每次命令的耗时/连接/时间,最多 5000 条,只写模式过滤
|
||||
- [ ] **自动更新** — electron-updater 集成,启动检查,下载进度,发行说明
|
||||
- [x] **自动更新** — electron-updater 集成,启动检查,下载进度,发行说明
|
||||
- [ ] **多标签页** — 单连接支持同时打开 Status/Keys/CLI/SlowLog/内存分析/批量删除 多个标签
|
||||
- [ ] **多连接并行** — 同时打开多个连接,各自独立标签页
|
||||
- [ ] **Monaco 编辑器** — 替换 StringEditor 的 textarea,支持 JSON 折叠/展开/语法高亮
|
||||
|
||||
@@ -3,6 +3,7 @@ import { app, BrowserWindow, nativeTheme, nativeImage } from 'electron'
|
||||
import { join } from 'path'
|
||||
import { restoreAndTrack } from './win-state'
|
||||
import { registerIpcHandlers } from './ipc-handlers'
|
||||
import { initUpdater } from './updater'
|
||||
|
||||
let mainWindow: BrowserWindow | null = null
|
||||
|
||||
@@ -55,6 +56,7 @@ function createWindow(): void {
|
||||
app.whenReady().then(() => {
|
||||
registerIpcHandlers()
|
||||
createWindow()
|
||||
initUpdater(mainWindow!)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => { app.quit() })
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// electron/main/updater.ts
|
||||
// 自动更新模块
|
||||
import { autoUpdater } from 'electron-updater'
|
||||
import { BrowserWindow, ipcMain } from 'electron'
|
||||
|
||||
let mainWindow: BrowserWindow | null = null
|
||||
|
||||
export function initUpdater(win: BrowserWindow): void {
|
||||
mainWindow = win
|
||||
|
||||
// 检查更新
|
||||
ipcMain.handle('updater:check', async () => {
|
||||
try {
|
||||
const result = await autoUpdater.checkForUpdates()
|
||||
return result?.updateInfo ? { available: true, version: result.updateInfo.version } : { available: false }
|
||||
} catch {
|
||||
return { available: false }
|
||||
}
|
||||
})
|
||||
|
||||
// 下载更新
|
||||
ipcMain.handle('updater:download', async () => {
|
||||
try {
|
||||
await autoUpdater.downloadUpdate()
|
||||
return { success: true }
|
||||
} catch (err: any) {
|
||||
return { success: false, error: err.message }
|
||||
}
|
||||
})
|
||||
|
||||
// 安装更新
|
||||
ipcMain.handle('updater:install', () => {
|
||||
autoUpdater.quitAndInstall()
|
||||
})
|
||||
|
||||
autoUpdater.autoDownload = false
|
||||
|
||||
autoUpdater.on('checking-for-update', () => {
|
||||
mainWindow?.webContents.send('updater:status', { status: 'checking' })
|
||||
})
|
||||
|
||||
autoUpdater.on('update-available', (info) => {
|
||||
mainWindow?.webContents.send('updater:status', {
|
||||
status: 'available',
|
||||
version: info.version,
|
||||
releaseNotes: info.releaseNotes,
|
||||
})
|
||||
})
|
||||
|
||||
autoUpdater.on('update-not-available', () => {
|
||||
mainWindow?.webContents.send('updater:status', { status: 'not-available' })
|
||||
})
|
||||
|
||||
autoUpdater.on('download-progress', (progress) => {
|
||||
mainWindow?.webContents.send('updater:status', {
|
||||
status: 'downloading',
|
||||
percent: progress.percent,
|
||||
transferred: progress.transferred,
|
||||
total: progress.total,
|
||||
bytesPerSecond: progress.bytesPerSecond,
|
||||
})
|
||||
})
|
||||
|
||||
autoUpdater.on('update-downloaded', () => {
|
||||
mainWindow?.webContents.send('updater:status', { status: 'downloaded' })
|
||||
})
|
||||
|
||||
autoUpdater.on('error', (err) => {
|
||||
mainWindow?.webContents.send('updater:status', { status: 'error', message: err.message })
|
||||
})
|
||||
}
|
||||
Vendored
+6
@@ -105,6 +105,12 @@ export interface ElectronAPI {
|
||||
getCommandLog: () => Promise<any[]>
|
||||
clearCommandLog: () => Promise<void>
|
||||
}
|
||||
updater: {
|
||||
check: () => Promise<{ available: boolean; version?: string }>
|
||||
download: () => Promise<{ success: boolean; error?: string }>
|
||||
install: () => void
|
||||
onStatus: (callback: (status: any) => void) => void
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
@@ -120,6 +120,14 @@ const electronAPI = {
|
||||
clearCommandLog: (): Promise<void> =>
|
||||
ipcRenderer.invoke('redis:clearCommandLog'),
|
||||
},
|
||||
updater: {
|
||||
check: (): Promise<any> => ipcRenderer.invoke('updater:check'),
|
||||
download: (): Promise<any> => ipcRenderer.invoke('updater:download'),
|
||||
install: () => ipcRenderer.invoke('updater:install'),
|
||||
onStatus: (callback: (status: any) => void) => {
|
||||
ipcRenderer.on('updater:status', (_e, status) => callback(status))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', electronAPI)
|
||||
|
||||
Generated
+48
-9
@@ -10,6 +10,7 @@
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"electron-store": "^11.0.2",
|
||||
"electron-updater": "^6.8.9",
|
||||
"ioredis": "^5.7.0",
|
||||
"pinia": "^3.0.4",
|
||||
"ssh2": "^1.17.0"
|
||||
@@ -2289,7 +2290,6 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/asn1": {
|
||||
@@ -2545,7 +2545,6 @@
|
||||
"version": "9.7.0",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.7.0.tgz",
|
||||
"integrity": "sha512-g/kR520giAFYkSXTzcmF3kqQq7wi8F6N6SzeDgZrqTBN+VHdmgWOyTdD1yD7AATDId/yXLvuP34CxW46/BwCdw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
@@ -3329,6 +3328,34 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/electron-updater": {
|
||||
"version": "6.8.9",
|
||||
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.8.9.tgz",
|
||||
"integrity": "sha512-ZhVxM9iGONUpZGI1FxdMRgJjUFXi7AYGVa5PwKlO1tV1/4zDxQmfKpXOHVztKrd6L9rLcFjERvi1Mf2vxyTkig==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"builder-util-runtime": "9.7.0",
|
||||
"fs-extra": "^10.1.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lazy-val": "^1.0.5",
|
||||
"lodash.escaperegexp": "^4.1.2",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"semver": "~7.7.3",
|
||||
"tiny-typed-emitter": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-updater/node_modules/semver": {
|
||||
"version": "7.7.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
||||
"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-vite": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-vite/-/electron-vite-3.1.0.tgz",
|
||||
@@ -3731,7 +3758,6 @@
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
@@ -3996,7 +4022,6 @@
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
@@ -4285,7 +4310,6 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz",
|
||||
"integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -4361,7 +4385,6 @@
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz",
|
||||
"integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
@@ -4384,7 +4407,6 @@
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz",
|
||||
"integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
@@ -4413,6 +4435,19 @@
|
||||
"lodash-es": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.escaperegexp": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz",
|
||||
"integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
|
||||
"deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lowercase-keys": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
|
||||
@@ -5384,7 +5419,6 @@
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz",
|
||||
"integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": ">=11.0.0"
|
||||
@@ -5737,6 +5771,12 @@
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/tiny-typed-emitter": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.17",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
|
||||
@@ -5859,7 +5899,6 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
|
||||
+7
-1
@@ -31,9 +31,14 @@
|
||||
"output": "release"
|
||||
},
|
||||
"files": [
|
||||
"out/**/*",
|
||||
"electron-dist/**/*",
|
||||
"package.json"
|
||||
],
|
||||
"publish": {
|
||||
"provider": "github",
|
||||
"owner": "Jokul",
|
||||
"repo": "JRedisDesktop"
|
||||
},
|
||||
"linux": {
|
||||
"target": [
|
||||
"AppImage",
|
||||
@@ -60,6 +65,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"electron-store": "^11.0.2",
|
||||
"electron-updater": "^6.8.9",
|
||||
"ioredis": "^5.7.0",
|
||||
"pinia": "^3.0.4",
|
||||
"ssh2": "^1.17.0"
|
||||
|
||||
@@ -166,6 +166,16 @@ export default {
|
||||
clear: 'Clear',
|
||||
empty: 'No commands recorded',
|
||||
},
|
||||
updater: {
|
||||
checking: 'Checking for updates...',
|
||||
available: 'New version {version} available',
|
||||
notAvailable: 'You are up to date',
|
||||
downloading: 'Downloading... {percent}%',
|
||||
downloaded: 'Update downloaded. Restart now?',
|
||||
install: 'Restart Now',
|
||||
later: 'Later',
|
||||
error: 'Update failed: {message}',
|
||||
},
|
||||
status: {
|
||||
title: 'Status',
|
||||
database: 'Database',
|
||||
|
||||
@@ -166,6 +166,16 @@ export default {
|
||||
clear: '清空',
|
||||
empty: '暂无命令记录',
|
||||
},
|
||||
updater: {
|
||||
checking: '正在检查更新...',
|
||||
available: '发现新版本 {version}',
|
||||
notAvailable: '已是最新版本',
|
||||
downloading: '正在下载... {percent}%',
|
||||
downloaded: '更新已下载,重启安装?',
|
||||
install: '立即重启',
|
||||
later: '稍后',
|
||||
error: '更新失败: {message}',
|
||||
},
|
||||
status: {
|
||||
title: '状态',
|
||||
database: '数据库',
|
||||
|
||||
Reference in New Issue
Block a user