Feature(custom): add custom update page

This commit is contained in:
Kuingsmile
2026-01-09 15:51:49 +08:00
parent 357b8cc55b
commit a29c1fa93c
20 changed files with 1514 additions and 768 deletions

View File

@@ -271,4 +271,54 @@ windowList.set(IWindowList.TOOLBOX_WINDOW, {
},
})
const updateWindowOptions = {
height: 600,
width: 900,
show: false,
frame: true,
center: true,
fullscreenable: false,
resizable: false,
title: 'PicList Update',
backgroundColor: '#ebeef5',
icon: logo,
webPreferences: {
sandbox: false,
backgroundThrottling: true,
preload: preloadPath,
nodeIntegration: false,
contextIsolation: true,
nodeIntegrationInWorker: false,
webSecurity: false,
},
} as IBrowserWindowOptions
if (process.platform !== 'darwin') {
updateWindowOptions.backgroundColor = '#3f3c37'
updateWindowOptions.autoHideMenuBar = true
updateWindowOptions.transparent = false
}
windowList.set(IWindowList.UPDATE_WINDOW, {
isValid: true,
multiple: false,
options: () => updateWindowOptions,
async callback(window, windowManager) {
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#update-page`)
} else {
window.loadFile(path.join(dirname, '../renderer/index.html'), {
hash: 'update-page',
})
}
const currentWindow = windowManager.getAvailableWindow(true)
if (currentWindow && currentWindow.isVisible()) {
const { x, y, width, height } = currentWindow.getBounds()
const positionX = Math.floor(x + width / 2 - 450)
const positionY = Math.floor(y + height / 2 - 300)
window.setPosition(positionX, positionY, false)
}
},
})
export default windowList

View File

@@ -10,6 +10,7 @@ import { settingRouter } from '~/events/rpc/routes/setting'
import { systemRouter } from '~/events/rpc/routes/system'
import { toolboxRouter } from '~/events/rpc/routes/toolbox'
import { trayRouter } from '~/events/rpc/routes/tray'
import { updaterRouter } from '~/events/rpc/routes/updater'
import { uploadRouter } from '~/events/rpc/routes/upload'
import { IRPCType } from '~/utils/enum'
@@ -67,6 +68,7 @@ const routes = [
toolboxRouter.routes(),
trayRouter.routes(),
uploadRouter.routes(),
updaterRouter.routes(),
manageRouter.routes(),
]

View File

@@ -0,0 +1,49 @@
import db from '@core/datastore'
import { BrowserWindow, shell } from 'electron'
import updater from 'electron-updater'
import { RPCRouter } from '~/events/rpc/router'
import { configPaths } from '~/utils/configPaths'
import { IRPCActionType } from '~/utils/enum'
const updaterRouter = new RPCRouter()
const updaterRoutes = [
{
action: IRPCActionType.DOWNLOAD_UPDATE,
handler: async () => {
updater.autoUpdater.downloadUpdate()
},
},
{
action: IRPCActionType.GO_TO_DOWNLOAD_PAGE,
handler: async () => {
shell.openExternal('https://github.com/Kuingsmile/PicList/releases/latest')
},
},
{
action: IRPCActionType.INSTALL_UPDATE,
handler: async () => {
updater.autoUpdater.quitAndInstall()
},
},
{
action: IRPCActionType.SET_SHOW_UPDATE_TIP,
handler: async (_: IIPCEvent, args: [value: boolean]) => {
db.set(configPaths.settings.showUpdateTip, args[0])
},
},
{
action: IRPCActionType.CLOSE_CURRENT_WINDOW,
handler: async (event: IIPCEvent) => {
const window = BrowserWindow.fromWebContents(event.sender)
if (window) {
window.close()
}
},
},
]
updaterRouter.addBatch(updaterRoutes)
export { updaterRouter }

View File

@@ -12,14 +12,13 @@ import { createTray, setDockMenu } from 'apis/app/system'
import { uploadChoosedFiles, uploadClipboardFiles } from 'apis/app/uploader/apis'
import windowManager from 'apis/app/window/windowManager'
import axios from 'axios'
import { app, dialog, globalShortcut, Notification, protocol, screen, shell } from 'electron'
import { app, globalShortcut, Notification, protocol, screen } from 'electron'
import updater from 'electron-updater'
import fs from 'fs-extra'
import busEventList from '~/events/busEventList'
import { rpcServer } from '~/events/rpc'
import { startFileServer, stopFileServer } from '~/fileServer'
import { T as $t } from '~/i18n'
import fixPath from '~/lifeCycle/fixPath'
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
import getManageApi from '~/manage/Main'
@@ -66,6 +65,7 @@ updater.autoUpdater.setFeedURL({
channel: 'latest',
})
updater.autoUpdater.forceDevUpdateConfig = true
updater.autoUpdater.autoDownload = false
updater.autoUpdater.on('update-available', async (info: updater.UpdateInfo) => {
@@ -82,7 +82,7 @@ updater.autoUpdater.on('update-available', async (info: updater.UpdateInfo) => {
logger.error(e)
}
const maxLogLength = 800
const maxLogLength = 8000
let displayLog = updateLog
let truncatedNote = ''
@@ -95,60 +95,64 @@ updater.autoUpdater.on('update-available', async (info: updater.UpdateInfo) => {
: '\n\n... (See full changelog for more details)'
}
dialog
.showMessageBox({
type: 'info',
title: $t('FIND_NEW_VERSION'),
buttons: ['Yes', 'Go to download page'],
message:
$t('TIPS_FIND_NEW_VERSION', {
v: info.version,
}) +
'\n\n' +
displayLog +
truncatedNote,
checkboxLabel: $t('NO_MORE_NOTICE'),
checkboxChecked: false,
})
.then(result => {
if (result.response === 0) {
updater.autoUpdater.downloadUpdate()
} else {
shell.openExternal('https://github.com/Kuingsmile/PicList/releases/latest')
}
db.set(configPaths.settings.showUpdateTip, !result.checkboxChecked)
})
.catch(err => {
logger.error(err)
windowManager.create(IWindowList.UPDATE_WINDOW)
const updateWindow = windowManager.get(IWindowList.UPDATE_WINDOW)!
updateWindow.webContents.once('did-finish-load', () => {
updateWindow.webContents.send('SHOW_UPDATE_INFO', {
type: 'update-available',
title: lang === II18nLanguage.ZH_CN ? '发现新版本' : 'New Update Available',
version: info.version,
releaseNotes: displayLog + truncatedNote,
})
})
updateWindow.show()
})
updater.autoUpdater.on('download-progress', progressObj => {
const percent = {
progress: progressObj.percent,
}
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
window.webContents.send('updateProgress', percent)
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
const updateWindow = windowManager.get(IWindowList.UPDATE_WINDOW)
if (settingWindow) {
settingWindow.webContents.send('updateProgress', percent)
}
if (updateWindow) {
updateWindow.webContents.send('UPDATE_PROGRESS', percent)
}
})
updater.autoUpdater.on('update-downloaded', () => {
dialog
.showMessageBox({
type: 'info',
title: $t('UPDATE_DOWNLOADED'),
buttons: ['Yes', 'No'],
message: $t('TIPS_UPDATE_DOWNLOADED'),
})
.then(result => {
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
window.webContents.send('updateProgress', { progress: 100 })
if (result.response === 0) {
updater.autoUpdater.quitAndInstall()
}
})
.catch(err => {
logger.error(err)
const lang = db.get(configPaths.settings.language) || II18nLanguage.ZH_CN
if (!windowManager.has(IWindowList.UPDATE_WINDOW)) {
windowManager.create(IWindowList.UPDATE_WINDOW)
}
const updateWindow = windowManager.get(IWindowList.UPDATE_WINDOW)!
const sendUpdateInfo = () => {
updateWindow.webContents.send('SHOW_UPDATE_INFO', {
type: 'update-downloaded',
title: lang === II18nLanguage.ZH_CN ? '更新已下载' : 'Update Downloaded',
message:
lang === II18nLanguage.ZH_CN
? '更新已下载完成,将在下次重启应用时安装。是否立即重启?'
: 'The update has been downloaded and will be installed on the next app restart. Would you like to restart now?',
})
}
if (updateWindow.webContents.isLoading()) {
updateWindow.webContents.once('did-finish-load', sendUpdateInfo)
} else {
sendUpdateInfo()
}
if (!updateWindow.isVisible()) {
updateWindow.show()
}
})
updater.autoUpdater.on('error', err => {

View File

@@ -8,6 +8,12 @@ export interface IConfigStruct {
picBed: {
uploader: string
current?: string
secondUploader?: string
secondUploaderId?: string
secondUploaderConfig?: IStringKeyMap
proxy?: string
transformer?: string
list: IPicBedType[]
smms?: ISMMSConfig
qiniu?: IQiniuConfig
upyun?: IUpYunConfig
@@ -20,9 +26,6 @@ export interface IConfigStruct {
sftpplist?: ISftpPlistConfig
lskyplist?: ILskyConfig
'aws-s3-plist': IAwsS3PListUserConfig
proxy?: string
transformer?: string
list: IPicBedType[]
[others: string]: any
}
settings: {
@@ -125,9 +128,9 @@ export const configPaths = {
showUpdateTip: 'settings.showUpdateTip',
miniWindowPosition: 'settings.miniWindowPosition',
miniWindowOntop: 'settings.miniWindowOntop',
isHideDock: 'settings.isHideDock',
mainWindowWidth: 'settings.mainWindowWidth',
mainWindowHeight: 'settings.mainWindowHeight',
isHideDock: 'settings.isHideDock',
autoCloseMiniWindow: 'settings.autoCloseMiniWindow',
autoCloseMainWindow: 'settings.autoCloseMainWindow',
isCustomMiniIcon: 'settings.isCustomMiniIcon',

View File

@@ -41,6 +41,7 @@ export const IWindowList = {
MINI_WINDOW: 'MINI_WINDOW',
RENAME_WINDOW: 'RENAME_WINDOW',
TOOLBOX_WINDOW: 'TOOLBOX_WINDOW',
UPDATE_WINDOW: 'UPDATE_WINDOW',
}
export const IRemoteNoticeActionType = {
@@ -153,6 +154,13 @@ export const IRPCActionType = {
PLUGIN_IMPORT_LOCAL: 'PLUGIN_IMPORT_LOCAL',
PLUGIN_UPDATE_ALL: 'PLUGIN_UPDATE_ALL',
// updater rpc
DOWNLOAD_UPDATE: 'DOWNLOAD_UPDATE',
GO_TO_DOWNLOAD_PAGE: 'GO_TO_DOWNLOAD_PAGE',
INSTALL_UPDATE: 'INSTALL_UPDATE',
SET_SHOW_UPDATE_TIP: 'SET_SHOW_UPDATE_TIP',
CLOSE_CURRENT_WINDOW: 'CLOSE_CURRENT_WINDOW',
// tray rpc
TRAY_SET_TOOL_TIP: 'TRAY_SET_TOOL_TIP',
TRAY_GET_SHORT_URL: 'TRAY_GET_SHORT_URL',

View File

@@ -27,28 +27,6 @@ export const completeUploaderMetaConfig = (originData: IStringKeyMap): IUploader
}
}
/**
* get picbed config by type
* it will trigger the uploader config function & get the uploader config result
* & not just read from
*/
export const getPicBedConfig = (type: string) => {
const name = picgo.helper.uploader.get(type)?.name || type
if (picgo.helper.uploader.get(type)?.config) {
const _config = picgo.helper.uploader.get(type)!.config!(picgo)
const config = handleConfigWithFunction(_config)
return {
config,
name,
}
} else {
return {
config: [],
name,
}
}
}
export const changeSecondUploader = (type: string, config?: IStringKeyMap, id?: string) => {
if (!type) {
return
@@ -69,9 +47,7 @@ export const changeSecondUploader = (type: string, config?: IStringKeyMap, id?:
}
export const changeCurrentUploader = (type: string, config?: IStringKeyMap, id?: string) => {
if (!type) {
return
}
if (!type) return
if (id) {
picgo.saveConfig({
[`uploader.${type}.defaultId`]: id,