Skip to content

Commit

Permalink
refactor(updateChecker):optimize automatic updates and add a progress…
Browse files Browse the repository at this point in the history
… bar
  • Loading branch information
ni00 committed Jun 7, 2023
1 parent 802ea60 commit 5d29e36
Show file tree
Hide file tree
Showing 12 changed files with 565 additions and 100 deletions.
26 changes: 19 additions & 7 deletions src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import { app, protocol, BrowserWindow, ipcMain, shell, Menu } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
import { quitAndRenameLogger } from './utils/logger'
import updateChecker, { createUpdateWindow } from './main/updateChecker'
import { createUpdateWindow, autoDownload } from './main/updateDownloader'
import { getCurrentLang } from './main/updateChecker'
import getMenuTemplate from './main/getMenuTemplate'
import saveFile from './main/saveFile'
import saveExcel from './main/saveExcel'
import newWindow from './main/newWindow'
import { onSystemThemeChanged } from './main/systemTheme'
import useConnection, { initOptionModel } from '@/database/useConnection'
import useServices from '@/database/useServices'
import { dialog } from 'electron'

declare const __static: string

Expand Down Expand Up @@ -49,8 +51,8 @@ function handleIpcMessages() {
Menu.setApplicationMenu(menu)
}
})
ipcMain.on('checkUpdate', () => {
updateChecker(false)
ipcMain.on('clickUpdate', (event: Electron.IpcMainEvent) => {
event.sender.send('clickUpdate')
})
ipcMain.on('exportData', (event: Electron.IpcMainEvent, ...args: any[]) => {
const [filename, content, type] = args
Expand All @@ -73,6 +75,20 @@ function handleIpcMessages() {
event.sender.send('getWindowSize', win.getBounds())
}
})
ipcMain.on('startDownloadProgress', (event, updateDetail) => {
getCurrentLang().then((lang) => {
electronStore.set('isShow', false)
autoDownload(event, updateDetail, lang)
})
})
ipcMain.on('showMsg', (event) => {
dialog.showMessageBox({
type: 'info',
title: '',
buttons: ['OK'],
message: 'There are currently no updates available.',
})
})
}

// handle event when APP quit
Expand Down Expand Up @@ -154,10 +170,6 @@ async function createWindow() {
beforeAppQuit()
})
handleIpcMessages()
if (autoCheckUpdate) {
updateChecker()
}
// updateWindow
electronStore.get('isShow') && createUpdateWindow()
}

Expand Down
2 changes: 1 addition & 1 deletion src/lang/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import huLocale from 'element-ui/lib/locale/lang/hu'
import { formati18n } from '@/utils/i18n'

const supportLang: SupportLangModel = ['zh', 'en', 'ja', 'tr', 'hu']
const i18nModules: i18nLocaleModel = ['connections', 'settings', 'common', 'about', 'script', 'log', 'help']
const i18nModules: i18nLocaleModel = ['connections', 'settings', 'common', 'about', 'script', 'log', 'help', 'update']

const { en, zh, ja, tr, hu }: VueI18n.LocaleMessages = formati18n(i18nModules, supportLang)

Expand Down
65 changes: 65 additions & 0 deletions src/lang/update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
export default {
updateTitle: {
zh: '新版本更新',
en: 'New Version Update',
ja: '新しいバージョンの更新',
tr: 'Yeni Sürüm Güncellemesi',
hu: 'Új verzió frissítés',
},
ignoreVersion: {
zh: '忽略此版本',
en: 'Ignore this version',
ja: 'このバージョンを無視する',
tr: 'Bu sürümü yoksay',
hu: 'Figyelmen kívül hagyás',
},
nextRemind: {
zh: '以后提醒',
en: 'Remind me later',
ja: '後でリマインドする',
tr: 'Daha sonra hatırlat',
hu: 'Később emlékeztessen',
},
update: {
zh: '更新',
en: 'Update',
ja: '更新',
tr: 'Güncelle',
hu: 'Frissítés',
},
downloadProgress: {
zh: '下载进度',
en: 'Download Progress',
ja: 'ダウンロード進行状況',
tr: 'İndirme İlerlemesi',
hu: 'Letöltési Előrehaladás',
},
downloading: {
zh: '正在下载更新...',
en: 'Downloading update...',
ja: '更新をダウンロード中...',
tr: 'Güncelleme indiriliyor...',
hu: 'Frissítés letöltése...',
},
downloaded: {
zh: '下载完毕,点击安装并重启',
en: 'Download completed. Click to install and restart',
ja: 'ダウンロードが完了しました。クリックしてインストールして再起動してください',
tr: 'İndirme tamamlandı. Kurmak ve yeniden başlatmak için tıklayın',
hu: 'Letöltés kész. Kattintson a telepítéshez és az újraindításhoz',
},
cancel: {
zh: '取消更新',
en: 'Cancel update',
ja: '更新をキャンセル',
tr: 'Güncellemeyi iptal et',
hu: 'Frissítés megszakítása',
},
install: {
zh: '安装并重启',
en: 'Install and Restart',
ja: 'インストールして再起動',
tr: 'Kur ve Yeniden Başlat',
hu: 'Telepítés és újraindítás',
},
}
3 changes: 1 addition & 2 deletions src/main/getMenuTemplate.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { app, shell, BrowserWindow } from 'electron'
import updateChecker from './updateChecker'
import translations from '../lang/menu'

const isMac = process.platform === 'darwin'
Expand Down Expand Up @@ -35,7 +34,7 @@ const getMenuTemplate = (win: BrowserWindow, lang?: Language): $TSFixed => {
{
label: labels.checkForUpdate,
click: () => {
updateChecker(false)
win.webContents.send('clickUpdate')
},
},
{ type: 'separator' },
Expand Down
143 changes: 58 additions & 85 deletions src/main/updateChecker.ts
Original file line number Diff line number Diff line change
@@ -1,109 +1,82 @@
import { dialog, BrowserWindow } from 'electron'
import { BrowserWindow } from 'electron'
import axios from 'axios'
import version from '@/version'
import useServices from '@/database/useServices'

const { autoUpdater } = require('electron-updater')
const { dialog } = require('electron')
const Store = require('electron-store')
const electronStore = new Store()

const release = 'https://api.github.com/repos/emqx/MQTTX/releases/latest'
let language: string = 'en'
const log4js = require('log4js')

const isUpdate = (latest: string, current: string): boolean => {
const latestVersion: number[] = latest.split('.').map((item) => parseInt(item, 10))
const currentVersion: number[] = current.split('.').map((item) => parseInt(item, 10))
let update: boolean = false

for (let i: number = 0; i < 3; i++) {
if (currentVersion[i] < latestVersion[i]) {
update = true
}
}
log4js.configure({
appenders: {
console: {
type: 'console',
},
file: {
type: 'file',
filename: './logs/app.log', // 指定日志文件路径
},
},
categories: {
default: {
appenders: ['console', 'file'],
level: 'debug',
},
},
})

return update
}
const logger = log4js.getLogger('file')

const autoDownload = (latest: string, language: string): void => {
const urlLang = language === 'zh' ? 'zh' : 'en'
const downloadUrl = `https://www.emqx.com/${urlLang}/downloads/MQTTX/${latest}`
autoUpdater.setFeedURL(downloadUrl)
autoUpdater.checkForUpdatesAndNotify()
autoUpdater.on('checking-for-update', () => {})
autoUpdater.on('update-available', () => {})
autoUpdater.on('update-not-available', () => {})
autoUpdater.on('error', () => {})
autoUpdater.on('download-progress', () => {})
autoUpdater.on('update-downloaded', () => {
electronStore.set('isShow', true)
dialog
.showMessageBox({
type: 'info',
title: 'New Version',
buttons: ['Install', 'No'],
message: `Update available: ${latest}`,
})
.then((res) => {
if (res.response === 0) {
// if selected yes
autoUpdater.quitAndInstall()
} else {
dialog.showMessageBox({
type: 'info',
message: 'Automatic update on do not shut down the computer immediately',
})
}
})
})
export interface versionDetail {
version: string
detail: string
}

const updateChecker = async (isAuto: boolean = true): Promise<void | boolean> => {
const response = await axios.get(release)
export const getCurrentLang = async (): Promise<string> => {
let language: string = 'en'
const { settingService } = useServices()
await settingService.set()
const setting = await settingService.get()
if (setting) {
language = setting.currentLang
}
if (response.status === 200) {
const latest: string = response.data.name
const isPrerelease: boolean = response.data.prerelease
if (latest && isUpdate(latest.slice(1, 6), version) && !isPrerelease) {
autoDownload(latest, language)
} else {
if (!isAuto) {
dialog.showMessageBox({
type: 'info',
title: '',
buttons: ['OK'],
message: 'There are currently no updates available.',
})
return language === 'zh' ? 'zh' : 'en'
}

const getUpdateDtail = async (current: string): Promise<versionDetail | null> => {
const tagsUrl = 'https://api.github.com/repos/emqx/MQTTX/tags'
const tagsRes = await axios.get(tagsUrl)
if (tagsRes.status === 200) {
const tagsList: string[] = tagsRes.data.map((item: any) => item.name)
const latestTagsList: string[] = tagsList.slice(0, tagsList.indexOf(current))
while (latestTagsList.length > 0) {
const latestVersion = latestTagsList.shift()
const versionRes = await axios.get(
`https://community-sites.emqx.com/api/v1/changelogs?product=MQTTX&version=${latestVersion}`,
)
if (latestVersion && versionRes.status === 200) {
return {
version: latestVersion,
detail: versionRes.data.data.changelog,
}
}
}
} else {
return false
}
return null
}
//what's new window
export async function createUpdateWindow() {
const updateWindow = new BrowserWindow({
width: 600,
height: 500,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true,
},
})
const { settingService } = useServices()
await settingService.set()
const setting = await settingService.get()
if (setting) {
language = setting.currentLang

export const updateChecker = async (isAuto: boolean = true): Promise<void | versionDetail | boolean> => {
const currentVersion = `v${version}`
const updateDatail: versionDetail | null = await getUpdateDtail(currentVersion)
const language: string = await getCurrentLang()
if (updateDatail) {
if (isAuto && electronStore.get('isIgnore') === updateDatail.version) {
return false
}
return updateDatail
} else {
return false
}
let link: string = 'https://mqttx.app'
link = language === 'zh' ? `${link}/zh` : link
updateWindow.loadURL(`${link}/changelogs/v${version}`)
electronStore.set('isShow', false)
}
export default updateChecker
54 changes: 54 additions & 0 deletions src/main/updateDownloader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { BrowserWindow, IpcMain, IpcMainEvent, ipcMain } from 'electron'
import version from '@/version'
import { getCurrentLang, versionDetail } from './updateChecker'
import { resolve } from 'path'
const { autoUpdater } = require('electron-updater')
const Store = require('electron-store')
const electronStore = new Store()

export const autoDownload = (event: IpcMainEvent, updateDatail: versionDetail, language: string) => {
const downloadUrl = `https://www.emqx.com/${language}/downloads/MQTTX/${updateDatail.version}`
autoUpdater.setFeedURL(downloadUrl)
autoUpdater.autoDownload = false
autoUpdater.autoInstallOnAppQuit = false
autoUpdater.checkForUpdatesAndNotify()
autoUpdater.on('update-available', () => {
autoUpdater.downloadUpdate()
})
autoUpdater.on('error', (e: any) => {
console.log(e)
})
autoUpdater.on('download-progress', (progressObj: any) => {
event.sender.send('downloadProgressPercent', progressObj.percent)
})
autoUpdater.on('update-downloaded', () => {
event.sender.send('downloadProgressPercent', 100)
})
ipcMain.on('toQuitAndInstall', () => {
electronStore.set('isShow', true)
autoUpdater.quitAndInstall()
})
ipcMain.on('cancelDownload', () => {
autoUpdater.removeAllListeners()
autoUpdater.autoDownload = false
autoUpdater.autoInstallOnAppQuit = false
autoUpdater.autoCheckForUpdates = false
})
}

export async function createUpdateWindow() {
const updateWindow = new BrowserWindow({
width: 600,
height: 500,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true,
},
})
const language: string = await getCurrentLang()
let link: string = 'https://mqttx.app'
link = language === 'zh' ? `${link}/zh` : link
updateWindow.loadURL(`${link}/changelogs/v${version}`)
electronStore.set('isShow', false)
}
2 changes: 1 addition & 1 deletion src/types/locale.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ declare module 'element-ui/lib/locale/lang/ja' {}
declare module 'element-ui/lib/locale/lang/tr-TR' {}
declare module 'element-ui/lib/locale/lang/hu' {}

type i18nLocaleModel = ['connections', 'settings', 'common', 'about', 'script', 'log', 'help']
type i18nLocaleModel = ['connections', 'settings', 'common', 'about', 'script', 'log', 'help', 'update']
type SupportLangModel = ['zh', 'en', 'ja', 'tr', 'hu']

declare module '*.json' {
Expand Down
Loading

0 comments on commit 5d29e36

Please sign in to comment.