feature: 1)检查更新功能,使用 github api,来获取版本数据;2)自动检查更新功能,可配置化。
parent
9d445e31fd
commit
c498dd7cc1
|
@ -24,6 +24,8 @@ module.exports = {
|
|||
url: 'https://gitee.com/wangliang181230/dev-sidecar/raw/docmirror/packages/core/src/config/remote_config.json5'
|
||||
},
|
||||
theme: 'light', // 主题:light=亮色, dark=暗色
|
||||
autoChecked: true, // 是否自动检查更新
|
||||
skipPreRelease: true, // 是否忽略预发布版本
|
||||
dock: {
|
||||
hideWhenWinClose: false
|
||||
},
|
||||
|
|
|
@ -3,17 +3,19 @@ import { autoUpdater } from 'electron-updater'
|
|||
import path from 'path'
|
||||
import request from 'request'
|
||||
import progress from 'request-progress'
|
||||
// win是所有窗口的引用
|
||||
import fs from 'fs'
|
||||
import AdmZip from 'adm-zip'
|
||||
import logger from '../../utils/util.log'
|
||||
import log from '../../utils/util.log'
|
||||
import appPathUtil from '../../utils/util.apppath'
|
||||
import pkg from '../../../package.json'
|
||||
import DevSidecar from '@docmirror/dev-sidecar'
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const isMac = process.platform === 'darwin'
|
||||
const isLinux = process.platform === 'linux'
|
||||
|
||||
function downloadFile (uri, filePath, onProgress, onSuccess, onError) {
|
||||
logger.info('download url', uri)
|
||||
log.info('download url', uri)
|
||||
progress(request(uri), {
|
||||
// throttle: 2000, // Throttle the progress event to 2000ms, defaults to 1000ms
|
||||
// delay: 1000, // Only start to emit after 1000ms delay, defaults to 0ms
|
||||
|
@ -21,11 +23,11 @@ function downloadFile (uri, filePath, onProgress, onSuccess, onError) {
|
|||
})
|
||||
.on('progress', function (state) {
|
||||
onProgress(state.percent * 100)
|
||||
logger.log('progress', state.percent)
|
||||
log.log('progress', state.percent)
|
||||
})
|
||||
.on('error', function (err) {
|
||||
// Do something with err
|
||||
logger.error('下载升级包失败', err)
|
||||
log.error('下载升级包失败', err)
|
||||
onError(err)
|
||||
})
|
||||
.on('end', function () {
|
||||
|
@ -35,7 +37,11 @@ function downloadFile (uri, filePath, onProgress, onSuccess, onError) {
|
|||
.pipe(fs.createWriteStream(filePath))
|
||||
}
|
||||
|
||||
// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
|
||||
/**
|
||||
* 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
|
||||
*
|
||||
* @param win win是所有窗口的引用
|
||||
*/
|
||||
function updateHandle (app, api, win, beforeQuit, quit, log) {
|
||||
// // 更新前,删除本地安装包 ↓
|
||||
// const updaterCacheDirName = 'dev-sidecar-updater'
|
||||
|
@ -64,15 +70,115 @@ function updateHandle (app, api, win, beforeQuit, quit, log) {
|
|||
}
|
||||
}
|
||||
|
||||
logger.info('auto updater', autoUpdater.getFeedURL())
|
||||
log.info('auto updater', autoUpdater.getFeedURL())
|
||||
autoUpdater.autoDownload = false
|
||||
|
||||
let partPackagePath = null
|
||||
|
||||
// 检查更新
|
||||
const releasesApiUrl = 'https://api.github.com/repos/docmirror/dev-sidecar/releases'
|
||||
async function checkForUpdatesFromGitHub () {
|
||||
log.info('DevSidecar.api.config.app.skipPreRelease:', DevSidecar.api.config.get().app.skipPreRelease)
|
||||
request(releasesApiUrl, { headers: { 'User-Agent': 'DS/' + pkg.version } }, (error, response, body) => {
|
||||
try {
|
||||
if (error) {
|
||||
log.error('检查更新失败:', error)
|
||||
const errorMsg = '检查更新失败:' + error
|
||||
win.webContents.send('update', { key: 'error', error: errorMsg })
|
||||
return
|
||||
}
|
||||
if (response && response.statusCode === 200) {
|
||||
if (body == null || body.length < 2) {
|
||||
log.warn('检查更新失败,github API返回数据为空:', body)
|
||||
win.webContents.send('update', { key: 'error', error: '检查更新失败,github 返回数据为空' })
|
||||
return
|
||||
}
|
||||
|
||||
// 尝试解析API响应内容
|
||||
let data
|
||||
try {
|
||||
data = JSON.parse(body)
|
||||
} catch (e) {
|
||||
log.error(`检查更新失败,github API返回数据格式不正确, url: ${releasesApiUrl}, body: ${body}`)
|
||||
win.webContents.send('update', { key: 'error', error: '检查更新失败,github API返回数据格式不正确' })
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof data !== 'object' || data.length === undefined) {
|
||||
win.webContents.send('update', { key: 'error', error: '检查更新失败,github API返回数据格式不正确' })
|
||||
return
|
||||
}
|
||||
|
||||
log.info('github api返回的release数据:', JSON.stringify(data, null, '\t'))
|
||||
|
||||
// 检查更新
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const versionData = data[i]
|
||||
|
||||
if (!versionData.assets || versionData.assets.length === 0) {
|
||||
continue // 跳过空版本,即上传过安装包
|
||||
}
|
||||
if (DevSidecar.api.config.app.skipPreRelease && versionData.name.indexOf('Pre-release') >= 0) {
|
||||
continue // 跳过预发布版本
|
||||
}
|
||||
|
||||
// log.info('最近正式版本数据:', versionData)
|
||||
|
||||
let version = versionData.tag_name
|
||||
if (version.indexOf('v') === 0) {
|
||||
version = version.substring(1)
|
||||
}
|
||||
if (version !== pkg.version) {
|
||||
log.info('检查更新-发现新版本:', version)
|
||||
win.webContents.send('update', {
|
||||
key: 'available',
|
||||
value: {
|
||||
version: versionData.tag_name,
|
||||
releaseNotes: [
|
||||
'请查看发布公告:' + versionData.html_url
|
||||
]
|
||||
}
|
||||
})
|
||||
} else {
|
||||
log.info('检查更新-没有新版本,最新版本号为:', version)
|
||||
win.webContents.send('update', { key: 'notAvailable' })
|
||||
}
|
||||
|
||||
return // 只检查最近一个正式版本
|
||||
}
|
||||
|
||||
log.info('检查更新-没有正式版本数据')
|
||||
win.webContents.send('update', { key: 'notAvailable' })
|
||||
} else {
|
||||
log.error('检查更新失败, status:', response.statusCode, ', body:', body)
|
||||
|
||||
let bodyObj
|
||||
try {
|
||||
bodyObj = JSON.parse(body)
|
||||
} catch (e) {
|
||||
bodyObj = null
|
||||
}
|
||||
|
||||
let message
|
||||
if (response) {
|
||||
message = '检查更新失败: ' + (bodyObj && bodyObj.message ? bodyObj.message : response.message) + ', code: ' + response.statusCode
|
||||
} else {
|
||||
message = '检查更新失败: ' + (bodyObj && bodyObj.message ? bodyObj.message : body)
|
||||
}
|
||||
win.webContents.send('update', { key: 'error', error: message })
|
||||
}
|
||||
} catch (e) {
|
||||
log.error('检查更新失败:', e)
|
||||
win.webContents.send('update', { key: 'error', error: '检查更新失败:' + e.message })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 下载升级包
|
||||
function downloadPart (app, value) {
|
||||
const appPath = appPathUtil.getAppRootPath(app)
|
||||
const fileDir = path.join(appPath, 'update')
|
||||
logger.info('download dir', fileDir)
|
||||
log.info('download dir', fileDir)
|
||||
try {
|
||||
fs.accessSync(fileDir, fs.constants.F_OK)
|
||||
} catch (e) {
|
||||
|
@ -85,7 +191,7 @@ function updateHandle (app, api, win, beforeQuit, quit, log) {
|
|||
}, () => {
|
||||
// 文件下载完成
|
||||
win.webContents.send('update', { key: 'progress', value: 100 })
|
||||
logger.info('升级包下载成功:', filePath)
|
||||
log.info('升级包下载成功:', filePath)
|
||||
partPackagePath = filePath
|
||||
win.webContents.send('update', {
|
||||
key: 'downloaded',
|
||||
|
@ -168,8 +274,11 @@ function updateHandle (app, api, win, beforeQuit, quit, log) {
|
|||
})
|
||||
} else if (arg.key === 'checkForUpdate') {
|
||||
// 执行自动更新检查
|
||||
log.info('autoUpdater checkForUpdates')
|
||||
autoUpdater.checkForUpdates()
|
||||
log.info('autoUpdater checkForUpdates:', arg.fromUser)
|
||||
|
||||
// 调用 github API,获取release数据,来检查更新
|
||||
// autoUpdater.checkForUpdates()
|
||||
checkForUpdatesFromGitHub()
|
||||
} else if (arg.key === 'downloadUpdate') {
|
||||
// 下载新版本
|
||||
log.info('autoUpdater downloadUpdate')
|
||||
|
@ -177,7 +286,6 @@ function updateHandle (app, api, win, beforeQuit, quit, log) {
|
|||
} else if (arg.key === 'downloadPart') {
|
||||
// 下载增量更新版本
|
||||
log.info('autoUpdater downloadPart')
|
||||
// autoUpdater.downloadUpdate()
|
||||
downloadPart(app, arg.value)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
function install (app, api) {
|
||||
const updateParams = app.$global.update = { fromUser: false, autoDownload: false, progress: 0, downloading: false, newVersion: false, isFullUpdate: true }
|
||||
const updateParams = app.$global.update = { fromUser: false, autoDownload: false, progress: 0, checking: false, downloading: false, newVersion: false, isFullUpdate: true }
|
||||
api.ipc.on('update', (event, message) => {
|
||||
console.log('on message', event, message)
|
||||
handleUpdateMessage(message, app)
|
||||
|
@ -10,7 +10,10 @@ function install (app, api) {
|
|||
if (fromUser != null) {
|
||||
updateParams.fromUser = fromUser
|
||||
}
|
||||
api.ipc.send('update', { key: 'checkForUpdate' })
|
||||
if (updateParams.fromUser) {
|
||||
updateParams.checking = true
|
||||
}
|
||||
api.ipc.send('update', { key: 'checkForUpdate', fromUser })
|
||||
},
|
||||
downloadUpdate () {
|
||||
api.ipc.send('update', { key: 'downloadUpdate' })
|
||||
|
@ -27,8 +30,10 @@ function install (app, api) {
|
|||
function handleUpdateMessage (message) {
|
||||
const type = message.key
|
||||
if (type === 'available') {
|
||||
updateParams.checking = false
|
||||
foundNewVersion(message.value)
|
||||
} else if (type === 'notAvailable') {
|
||||
updateParams.checking = false
|
||||
noNewVersion()
|
||||
} else if (type === 'downloaded') {
|
||||
// 更新包已下载完成,让用户确认是否更新
|
||||
|
@ -38,12 +43,14 @@ function install (app, api) {
|
|||
} else if (type === 'progress') {
|
||||
progressUpdate(message.value)
|
||||
} else if (type === 'error') {
|
||||
updateParams.checking = false
|
||||
updateParams.downloading = false
|
||||
const error = message.error
|
||||
app.$message.error('Error: ' + (error == null ? '未知错误' : (error.stack || error).toString()))
|
||||
app.$message.error((error == null ? '未知错误' : (error.stack || error).toString()))
|
||||
}
|
||||
}
|
||||
|
||||
function noNewVersion (value) {
|
||||
function noNewVersion () {
|
||||
updateParams.newVersion = false
|
||||
if (updateParams.fromUser) {
|
||||
app.$message.info('当前已经是最新版本')
|
||||
|
@ -55,8 +62,10 @@ function install (app, api) {
|
|||
}
|
||||
|
||||
function goManualUpdate (value) {
|
||||
updateParams.newVersion = false
|
||||
app.$confirm({
|
||||
title: '暂不支持自动升级',
|
||||
// title: '暂不支持自动升级',
|
||||
title: '暂不提供自动升级',
|
||||
cancelText: '取消',
|
||||
okText: '确定',
|
||||
content: h => {
|
||||
|
@ -64,50 +73,49 @@ function install (app, api) {
|
|||
api.ipc.openExternal('https://github.com/docmirror/dev-sidecar/releases')
|
||||
}
|
||||
return <div>
|
||||
<div>请前往github项目release页面下载新版本手动安装</div>
|
||||
<ol>
|
||||
<li><a onClick={openGithubUrl}>Github release</a></li>
|
||||
</ol>
|
||||
<div>请前往 <a onClick={openGithubUrl}>github项目release页面</a> 下载新版本手动安装</div>
|
||||
</div>
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否小版本升级
|
||||
* @param version1
|
||||
* @param version2
|
||||
*/
|
||||
async function isSupportPartUpdate (value) {
|
||||
const info = await api.info.get()
|
||||
console.log('升级版本:', value.version)
|
||||
console.log('增量更新最小版本:', value.partMiniVersion)
|
||||
console.log('当前版本:', info.version)
|
||||
if (!value.partPackage) {
|
||||
return false
|
||||
}
|
||||
return !!(value.partMiniVersion && value.partMiniVersion < info.version)
|
||||
}
|
||||
// /**
|
||||
// * 是否小版本升级
|
||||
// * @param value
|
||||
// */
|
||||
// async function isSupportPartUpdate (value) {
|
||||
// const info = await api.info.get()
|
||||
// console.log('升级版本:', value.version)
|
||||
// console.log('增量更新最小版本:', value.partMiniVersion)
|
||||
// console.log('当前版本:', info.version)
|
||||
// if (!value.partPackage) {
|
||||
// return false
|
||||
// }
|
||||
// return !!(value.partMiniVersion && value.partMiniVersion < info.version)
|
||||
// }
|
||||
|
||||
async function downloadNewVersion (value) {
|
||||
const platform = await api.shell.getSystemPlatform()
|
||||
console.log('download new version platform', platform)
|
||||
if (platform === 'linux') {
|
||||
goManualUpdate(app, value)
|
||||
return
|
||||
}
|
||||
const partUpdate = await isSupportPartUpdate(value)
|
||||
if (partUpdate) {
|
||||
// 有增量更新
|
||||
api.update.downloadPart(value)
|
||||
} else {
|
||||
if (platform === 'mac') {
|
||||
goManualUpdate(value)
|
||||
return
|
||||
}
|
||||
updateParams.downloading = true
|
||||
api.update.downloadUpdate()
|
||||
}
|
||||
// 暂时取消自动更新功能
|
||||
goManualUpdate(value)
|
||||
|
||||
// const platform = await api.shell.getSystemPlatform()
|
||||
// console.log(`download new version: ${JSON.stringify(value)}, platform: ${platform}`)
|
||||
// if (platform === 'linux') {
|
||||
// goManualUpdate(value)
|
||||
// return
|
||||
// }
|
||||
// const partUpdate = await isSupportPartUpdate(value)
|
||||
// if (partUpdate) {
|
||||
// // 有增量更新
|
||||
// api.update.downloadPart(value)
|
||||
// } else {
|
||||
// if (platform === 'mac') {
|
||||
// goManualUpdate(value)
|
||||
// return
|
||||
// }
|
||||
// updateParams.downloading = true
|
||||
// api.update.downloadUpdate()
|
||||
// }
|
||||
}
|
||||
function foundNewVersion (value) {
|
||||
updateParams.newVersion = true
|
||||
|
@ -118,18 +126,23 @@ function install (app, api) {
|
|||
downloadNewVersion(value)
|
||||
return
|
||||
}
|
||||
console.log(value)
|
||||
app.$confirm({
|
||||
title: '发现新版本',
|
||||
title: '发现新版本:' + value.version,
|
||||
cancelText: '暂不升级',
|
||||
okText: '升级',
|
||||
width: 600,
|
||||
content: h => {
|
||||
console.log(value)
|
||||
if (value.releaseNotes) {
|
||||
const notes = []
|
||||
for (const note of value.releaseNotes) {
|
||||
notes.push(<li>{note}</li>)
|
||||
if (typeof value.releaseNotes === 'string') {
|
||||
return <div><div>更新内容:</div><div>{value.releaseNotes}</div></div>
|
||||
} else {
|
||||
const notes = []
|
||||
for (const note of value.releaseNotes) {
|
||||
notes.push(<li>{note}</li>)
|
||||
}
|
||||
return <div><div>更新内容:</div><ol>{notes}</ol></div>
|
||||
}
|
||||
return <div><div>更新内容:</div><ol>{notes}</ol></div>
|
||||
}
|
||||
},
|
||||
onOk () {
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
<a-badge :count="_rootCaSetuped?0:1" dot>安装根证书</a-badge>
|
||||
</a-button>
|
||||
|
||||
<a-button style="margin-right:10px" @click="doCheckUpdate(true)" :loading="update.downloading"
|
||||
<a-button style="margin-right:10px" @click="doCheckUpdate(true)" :loading="update.downloading || update.checking"
|
||||
:title="'当前版本:'+info.version">
|
||||
<a-badge :count="update.newVersion?1:0" dot>
|
||||
<span v-if="update.downloading">{{ update.progress }}%</span>{{ update.downloading ? '新版本下载中' : '检查更新' }}
|
||||
<span v-if="update.downloading">{{ update.progress }}%</span>{{ update.downloading ? '新版本下载中' : ('检查更新' + (update.checking ? '中' : '')) }}
|
||||
</a-badge>
|
||||
</a-button>
|
||||
</span>
|
||||
|
@ -161,7 +161,7 @@ export default {
|
|||
setupCa: {
|
||||
visible: false
|
||||
},
|
||||
update: { downloading: false, progress: 0, newVersion: false }
|
||||
update: { checking: false, downloading: false, progress: 0, newVersion: false }
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
|
@ -170,8 +170,8 @@ export default {
|
|||
this.$set(this, 'status', this.$status)
|
||||
this.switchBtns = this.createSwitchBtns()
|
||||
this.$set(this, 'update', this.$global.update)
|
||||
if (!this.update.autoChecked) {
|
||||
this.update.autoChecked = true
|
||||
if (!this.update.autoChecked && this.config.app.autoChecked) {
|
||||
this.update.autoChecked = true // 应用启动时,只执行一遍
|
||||
this.doCheckUpdate(false)
|
||||
}
|
||||
this.$api.info.get().then(ret => {
|
||||
|
|
|
@ -52,6 +52,29 @@
|
|||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="自动检查更新" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-radio-group v-model="config.app.autoChecked" default-value="light" button-style="solid">
|
||||
<a-radio-button :value="true">
|
||||
开启
|
||||
</a-radio-button>
|
||||
<a-radio-button :value="false">
|
||||
关闭
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
<div class="form-help">
|
||||
开启自动检查更新后,每次应用启动时会检查一次更新,如有新版本,则会弹出提示。
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="config.app.autoChecked" label="忽略预发布版本" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-radio-group v-model="config.app.skipPreRelease" default-value="light" button-style="solid">
|
||||
<a-radio-button :value="true">
|
||||
忽略
|
||||
</a-radio-button>
|
||||
<a-radio-button :value="false">
|
||||
不忽略
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="首页提示" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-radio-group v-model="config.app.showShutdownTip"
|
||||
default-value="true" button-style="solid">
|
||||
|
|
Loading…
Reference in New Issue