Skip to content

Commit 4513d5c

Browse files
committed
feat(updater): implement app updater with auto-update functionality
- Added AppUpdater class to handle application updates using electron-updater. - Implemented methods for checking updates, downloading, and installing updates. - Introduced WebUpdater class as a placeholder for future web resource hot-reload logic. - Created types for AppUpdateState and UpdaterStatus in shared-types package. - Updated IPC communication to include app update state messages. - Enhanced the web application to display update status and control updates. - Improved UI with new styles and layout for the update control panel. - Added error handling and logging for update processes.
1 parent a6e0295 commit 4513d5c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1314
-216
lines changed
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
name: Build
1+
name: Publish Electron App
22

33
on:
44
push:
5-
branches: [main]
5+
branches: [refactor/code]
66
# tags:
77
# - 'v*.*.*'
88
jobs:
@@ -45,7 +45,7 @@ jobs:
4545
- name: Release for Windows
4646
if: matrix.os == 'windows-latest'
4747
run: |
48-
pnpm pack:dev
48+
pnpm pack:prod
4949
5050
- name: Release for MacOS
5151
if: matrix.os == 'macos-latest'
@@ -80,9 +80,9 @@ jobs:
8080
# apply provisioning profile
8181
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
8282
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
83-
pnpm pack:dev
83+
pnpm pack:prod
8484
8585
- name: Release for Linux
8686
if: matrix.os == 'ubuntu-latest'
8787
run: |
88-
pnpm pack:dev
88+
pnpm pack:prod

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"typescript.preferences.importModuleSpecifier": "non-relative",
23
// Disable the default formatter, use eslint instead
34
"prettier.enable": false,
45
"editor.formatOnSave": false,
@@ -84,4 +85,4 @@
8485
"pcss",
8586
"postcss"
8687
]
87-
}
88+
}

apps/electron/.env.development

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# 测试环境配置
22
NODE_ENV=development
3-
VITE_APP_VERSION=0.2.0
3+
VITE_APP_VERSION=0.0.1

apps/electron/dev-app-update.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
1-
provider: generic
2-
url: 'http://localhost:8080'
1+
# provider: generic
2+
# url: 'http://localhost:8080'
3+
4+
provider: github
5+
owner: buqiyuan
6+
repo: electron-vite-monorepo
7+
releaseType: draft # 如果构建脚本发布成 Draft,可保留;否则设为 release/latest
8+
private: false # 若仓库私有则改为 true 并提供 token

apps/electron/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"bundle": "npx rimraf ./dist && webpack --config webpack.config.cjs",
2323
"build:dev": "vite build --mode development && pnpm bundle",
2424
"build:prod": "vite build && pnpm bundle",
25-
"pack:app": "npx tsx scripts/build.ts",
25+
"pack:app": "npx tsx scripts/build.mts",
2626
"pack:dev": "pnpm build:dev && dotenvx run -f .env.development -- pnpm pack:app",
2727
"pack:prod": "pnpm build:prod && dotenvx run -f .env.production -- pnpm pack:app",
2828
"typecheck": "tsc --noEmit -p tsconfig.json",
@@ -33,9 +33,12 @@
3333
"devDependencies": {
3434
"@electron/notarize": "^3.1.1",
3535
"@repo/electron-preload": "workspace:*",
36+
"@repo/shared-types": "workspace:*",
3637
"@types/node": "^22.14.1",
38+
"date-fns": "^4.1.0",
3739
"electron": "39.2.6",
3840
"electron-builder": "26.3.4",
41+
"electron-log": "^5.4.3",
3942
"electron-store": "^11.0.2",
4043
"electron-updater": "6.6.2",
4144
"terser-webpack-plugin": "^5.3.15",

apps/electron/resources/tray.png

783 Bytes
Loading

apps/electron/scripts/build.mts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ const appName = isDev ? 'ElectronAppDev' : 'ElectronApp'
1111
const appId = isDev ? 'com.electron.app' : 'com.electron-dev.app'
1212
const shortcutName = isDev ? 'Electron App Dev' : 'Electron App'
1313

14-
console.log('是否是测试环境:', isDev, appName)
15-
console.log('APP 版本号:', version)
14+
console.log('Development environment:', isDev, appName)
15+
console.log('APP version:', version)
1616

1717
const workDir = path.join(import.meta.dirname, '../')
1818

1919
const copySyncOptions: CopySyncOptions = {
2020
recursive: true,
2121
/**
22-
* 过滤 source map 文件
22+
* Filter out source map files
2323
*/
2424
filter: src => !src.endsWith('.map') && !src.endsWith('.d.ts'),
2525
}
@@ -119,9 +119,9 @@ build({
119119
.then((result) => {
120120
console.log(JSON.stringify(result))
121121
const outDir = path.join(workDir, options.directories!.output!)
122-
console.log('\x1B[32m', `打包完成🎉🎉🎉你要的都在 ${outDir} 目录里🤪🤪🤪`)
122+
console.log('\x1B[32m', `Build complete! 🎉🎉🎉 Everything you need is in ${outDir}`)
123123
})
124124
.catch((error) => {
125-
console.log('\x1B[31m', '打包失败,错误信息:', error)
125+
console.log('\x1B[31m', 'Build failed with error:', error)
126126
exit(1)
127127
})

apps/electron/scripts/notarize-mac.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { AfterPackContext } from 'electron-builder'
44
/**
55
* https://github.com/electron/notarize
66
*
7-
* 验证是否签名成功: codesign -dv --verbose=4 /path/to/your/file.dmg
7+
* Verify signing: codesign -dv --verbose=4 /path/to/your/file.dmg
88
*/
99
export async function notarizeMac(context: AfterPackContext) {
1010
const { electronPlatformName, appOutDir } = context
@@ -18,8 +18,8 @@ export async function notarizeMac(context: AfterPackContext) {
1818
return await notarize({
1919
appPath: `${appOutDir}/${appName}.app`,
2020
tool: 'notarytool',
21-
appleId: process.env.APPLE_ID!, // 苹果开发者账号
22-
appleIdPassword: process.env.APPLE_PASSWORD!, // 苹果开发者密码
23-
teamId: process.env.APPLE_TEAM_ID!, // 开发者团队 id
21+
appleId: process.env.APPLE_ID!, // Apple developer account
22+
appleIdPassword: process.env.APPLE_PASSWORD!, // Apple developer password
23+
teamId: process.env.APPLE_TEAM_ID!, // Developer team ID
2424
})
2525
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { app, dialog } from 'electron'
2+
3+
// Expose the dev build version when running unpackaged so logs stay accurate.
4+
if (!app.isPackaged) {
5+
app.getVersion = () => import.meta.env.VITE_APP_VERSION
6+
}
7+
// (Not recommended) Disable TLS verification (used only when debugging corporate proxies)
8+
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
9+
10+
// Prevent the native error dialog from interrupting the UI
11+
dialog.showErrorBox = function (title, content) {
12+
// Log the failure instead of surfacing a blocking dialog
13+
console.error(`Error logged without system dialog: ${title}\n${content}`)
14+
}
15+
16+
// Capture uncaught exceptions so we can log them centrally
17+
process.on('uncaughtException', (error) => {
18+
console.error('Uncaught exception:', error)
19+
})
20+
21+
// Capture unhandled promise rejections for the same reason
22+
process.on('unhandledRejection', (reason) => {
23+
console.error('Unhandled promise rejection:', reason)
24+
})
25+
26+
// Let Sentry manage crashReporter manually when it is wired up
27+
28+
// Quick helper for locally testing crash reporting
29+
// setTimeout(() => {
30+
// process.crash()
31+
// }, 6000)

apps/electron/src/constants/appConfig.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,26 @@ import { isPackaged } from './common'
55
const sessionDir = app.getPath('sessionData')
66

77
export const appConfig = {
8-
/** 应用数据根目录 */
8+
/** Application data root directory */
99
sessionDir,
10-
/** 系统语言 */
10+
/** System locale */
1111
lang: app.getLocale(),
12-
/** 临时文件目录 */
12+
/** Temporary files directory */
1313
tempDir: join(sessionDir, 'temp'),
14-
/** 应用日志目录 */
14+
/** Application logs directory */
1515
logsDir: app.getPath('logs'),
16-
/** 配置文件 */
16+
/** Configuration file */
1717
configFile: join(sessionDir, 'config.json'),
18-
/** 预加载文件路径 */
18+
/** Preload script file path */
1919
get preloadFilePath() {
2020
return isPackaged ? join(import.meta.dirname, './preload/index.cjs') : join(import.meta.dirname, '../../preload/dist/index.cjs')
2121
},
22+
/** Web resource base URL */
23+
get webBaseURL() {
24+
return !isPackaged && import.meta.env.VITE_DEV_SERVER_URL !== undefined
25+
? import.meta.env.VITE_DEV_SERVER_URL
26+
: `file://${join(__dirname, './web/index.html')}`
27+
},
2228
} as const
2329

2430
console.debug('appConfig', appConfig)

0 commit comments

Comments
 (0)