Skip to content

Commit

Permalink
Merge pull request #246 from prixe/auto-updater
Browse files Browse the repository at this point in the history
Auto updater - Linux / Windows
  • Loading branch information
zenoxs authored Aug 27, 2022
2 parents 17f96ec + 5e375e4 commit 2778a98
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 159 deletions.
29 changes: 24 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ jobs:
path: |
release/${{ steps.extract_version.outputs.version }}/Lindo-${{ steps.extract_version.outputs.version }}-win.zip
release/${{ steps.extract_version.outputs.version }}/Lindo-${{ steps.extract_version.outputs.version }}-ia32-win.zip
release/${{ steps.extract_version.outputs.version }}/Lindo ${{ steps.extract_version.outputs.version }}.exe
release/${{ steps.extract_version.outputs.version }}/Lindo Setup ${{ steps.extract_version.outputs.version }}.exe
release/${{ steps.extract_version.outputs.version }}/Lindo-${{ steps.extract_version.outputs.version }}.exe
release/${{ steps.extract_version.outputs.version }}/Lindo-Setup-${{ steps.extract_version.outputs.version }}.exe
release/${{ steps.extract_version.outputs.version }}/Lindo-Setup-${{ steps.extract_version.outputs.version }}.exe.blockmap
release/${{ steps.extract_version.outputs.version }}/latest.yml
- name: Upload MacOS artifacts
uses: actions/upload-artifact@v2
Expand All @@ -57,7 +59,14 @@ jobs:
name: macos
path: |
release/${{ steps.extract_version.outputs.version }}/Lindo-${{ steps.extract_version.outputs.version }}.dmg
release/${{ steps.extract_version.outputs.version }}/Lindo-${{ steps.extract_version.outputs.version }}.dmg.blockmap
release/${{ steps.extract_version.outputs.version }}/Lindo-${{ steps.extract_version.outputs.version }}-arm64.dmg
release/${{ steps.extract_version.outputs.version }}/Lindo-${{ steps.extract_version.outputs.version }}-arm64.dmg.blockmap
release/${{ steps.extract_version.outputs.version }}/Lindo-${{ steps.extract_version.outputs.version }}-mac.zip
release/${{ steps.extract_version.outputs.version }}/Lindo-${{ steps.extract_version.outputs.version }}-mac.zip.blockmap
release/${{ steps.extract_version.outputs.version }}/Lindo-${{ steps.extract_version.outputs.version }}-arm64-mac.zip
release/${{ steps.extract_version.outputs.version }}/Lindo-${{ steps.extract_version.outputs.version }}-arm64-mac.zip.blockmap
release/${{ steps.extract_version.outputs.version }}/latest-mac.yml
- name: Upload Linux artifacts
uses: actions/upload-artifact@v2
Expand All @@ -71,6 +80,7 @@ jobs:
release/${{ steps.extract_version.outputs.version }}/lindo-${{ steps.extract_version.outputs.version }}-arm64.tar.gz
release/${{ steps.extract_version.outputs.version }}/lindo_${{ steps.extract_version.outputs.version }}_amd64.deb
release/${{ steps.extract_version.outputs.version }}/lindo_${{ steps.extract_version.outputs.version }}_arm64.deb
release/${{ steps.extract_version.outputs.version }}/latest-linux.yml
create-release:
name: "Upload Release"
Expand Down Expand Up @@ -99,16 +109,25 @@ jobs:
automatic_release_tag: "v${{ steps.extract_version.outputs.version }}"
title: "v${{ steps.extract_version.outputs.version }}"
files: |
windows/Lindo ${{ steps.extract_version.outputs.version }}.exe
windows/Lindo Setup ${{ steps.extract_version.outputs.version }}.exe
windows/Lindo-${{ steps.extract_version.outputs.version }}.exe
windows/Lindo-Setup-${{ steps.extract_version.outputs.version }}.exe
windows/Lindo-Setup-${{ steps.extract_version.outputs.version }}.exe.blockmap
windows/Lindo-${{ steps.extract_version.outputs.version }}-win.zip
windows/Lindo-${{ steps.extract_version.outputs.version }}-ia32-win.zip
windows/latest.yml
linux/Lindo-${{ steps.extract_version.outputs.version }}.AppImage
linux/Lindo-${{ steps.extract_version.outputs.version }}-arm64.AppImage
linux/lindo-${{ steps.extract_version.outputs.version }}.tar.gz
linux/lindo-${{ steps.extract_version.outputs.version }}-arm64.tar.gz
linux/lindo_${{ steps.extract_version.outputs.version }}_amd64.deb
linux/lindo_${{ steps.extract_version.outputs.version }}_arm64.deb
linux/latest-linux.yml
macos/Lindo-${{ steps.extract_version.outputs.version }}.dmg
macos/Lindo-${{ steps.extract_version.outputs.version }}.dmg.blockmap
macos/Lindo-${{ steps.extract_version.outputs.version }}-arm64.dmg
macos/Lindo-${{ steps.extract_version.outputs.version }}-arm64.dmg.blockmap
macos/Lindo-${{ steps.extract_version.outputs.version }}-mac.zip
macos/Lindo-${{ steps.extract_version.outputs.version }}-mac.zip.blockmap
macos/Lindo-${{ steps.extract_version.outputs.version }}-arm64-mac.zip
macos/Lindo-${{ steps.extract_version.outputs.version }}-arm64-mac.zip.blockmap
macos/latest-mac.yml
6 changes: 5 additions & 1 deletion electron-builder.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,20 @@
]
},
"nsis": {
"artifactName": "${productName}-Setup-${version}.${ext}",
"oneClick": false,
"perMachine": false,
"allowToChangeInstallationDirectory": true,
"deleteAppDataOnUninstall": false
},
"portable": {
"artifactName": "${productName}-${version}.${ext}"
},
"afterPack": "./scripts/afterPackHook.js",
"mac": {
"target": [
{
"target": "dmg",
"target": "default",
"arch": [
"x64",
"arm64"
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "lindo",
"productName": "Lindo",
"private": true,
"version": "3.0.0-rc.3",
"version": "3.0.0-rc.8",
"description": "Play Dofus Touch on Linux/OS X/Window",
"homepage": "https://github.com/prixe/lindo",
"author": "Zenoxs <[email protected]>",
Expand All @@ -19,7 +19,6 @@
},
"dependencies": {
"@hfelix/electron-localshortcut": "^4.0.1",
"@octokit/rest": "^19.0.3",
"argon2": "^0.28.7",
"axios": "^0.27.2",
"axios-retry": "^3.2.5",
Expand All @@ -28,6 +27,7 @@
"crypto-js": "^4.1.1",
"custom-electron-titlebar": "^4.1.0",
"electron-store": "^8.0.1",
"electron-updater": "^5.2.1",
"eventemitter3": "^4.0.7",
"express": "^4.18.1",
"firebase": "^9.9.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/i18n/en/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const en: BaseTranslation = {
title: 'New version available {version: string}',
message: 'A new version ({version: string}) of Lindo is available. Do you want to update?',
messageRequired: 'A required update ({version: string}) of Lindo is available, you must download it on GitHub.',
download: 'Download on GitHub',
download: 'Download',
ignore: 'Ignore'
},
gameMenu: {
Expand Down
2 changes: 1 addition & 1 deletion packages/i18n/es/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const es: Translation = {
message: 'Una nueva version ({version}) de Lindo esta disponible. ¿Quieres descargar la actualización?',
messageRequired:
'Está disponible una nueva versión ({version}) obligatoria de Lindo, puedes descárgarla en GitHub.',
download: 'Descárgarla en GitHub.',
download: 'Descárgarla.',
ignore: 'Ignorar'
},
gameMenu: {
Expand Down
2 changes: 1 addition & 1 deletion packages/i18n/fr/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const fr: Translation = {
message: 'Une nouvelle version ({version}) de Lindo est disponible. Voulez-vous télécharger la mise à jour?',
messageRequired:
'Une nouvelle version ({version}) obligatoire de Lindo est disponible, vous pouvez la télécharger sur GitHub.',
download: 'Télécharger sur github',
download: 'Télécharger',
ignore: 'Ignorer'
},
gameMenu: {
Expand Down
5 changes: 5 additions & 0 deletions packages/main/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ export const LOCAL_DOFUS_MANIFEST_PATH = GAME_PATH + 'manifest.json'
export const REMOTE_DOFUS_MANIFEST_URL = DOFUS_ORIGIN + 'manifest.json'
export const LOCAL_VERSIONS_PATH = GAME_PATH + 'versions.json'
export const LOCAL_REGEX_PATH = GAME_PATH + 'regex.json'

// GitHub
export const GITHUB_OWNER = 'prixe'
export const GITHUB_REPO = 'lindo'
export const GITHUB_LATEST_RELEASE_URL = 'https://github.com/' + GITHUB_OWNER + '/' + GITHUB_REPO + '/releases/latest'
95 changes: 74 additions & 21 deletions packages/main/updater/app-updater.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,90 @@
import { RootStore } from '@lindo/shared'
import { Octokit } from '@octokit/rest'
import compareVersions from 'compare-versions'
import { app, dialog, shell } from 'electron'
import { logger } from '../logger'
import { I18n } from '../utils'
import { autoUpdater, UpdateInfo } from 'electron-updater'
import { UpdaterWindow } from '../windows/updater-window'
import { GITHUB_LATEST_RELEASE_URL, GITHUB_OWNER, GITHUB_REPO } from '../constants'

export class AppUpdater {
private readonly _updaterWindow: UpdaterWindow
private readonly _rootStore: RootStore
private readonly _octokit: Octokit
private readonly _i18n: I18n

private constructor(rootStore: RootStore, i18n: I18n) {
private constructor(updaterWindow: UpdaterWindow, rootStore: RootStore, i18n: I18n) {
this._updaterWindow = updaterWindow
this._rootStore = rootStore
this._i18n = i18n
this._octokit = new Octokit()
}

static async init(rootStore: RootStore, i18n: I18n): Promise<AppUpdater> {
return new AppUpdater(rootStore, i18n)
const updaterWindow = await UpdaterWindow.init(rootStore, { show: false })
return new AppUpdater(updaterWindow, rootStore, i18n)
}

async run() {
// set the current version of the app
logger.info('appUpdater -> Start app update checking...')
const currentVersion = app.getVersion()
this._rootStore.appStore.setLindoVersion(currentVersion)

return this._octokit.repos
.getLatestRelease({
owner: 'prixe',
repo: 'lindo'
autoUpdater.logger = logger
autoUpdater.autoDownload = false
autoUpdater.setFeedURL({ provider: 'github', owner: GITHUB_OWNER, repo: GITHUB_REPO })

return new Promise<void>((resolve, reject) => {
autoUpdater.on('checking-for-update', () => {
logger.info('appUpdater -> Checking for updates...')
})
.then((res) => {
const latestVersion = res.data.tag_name.replaceAll('v', '')
const required = res.data.body?.includes('__update:required__') ?? false
logger.info({ latestVersion, currentVersion })
if (compareVersions(latestVersion, currentVersion) === 1) {
return this._showUpdateDialog(latestVersion, required)

autoUpdater.on('update-available', (updateInfo: UpdateInfo) => {
logger.info('appUpdater -> An Update is available v' + updateInfo.version)
let required = false
if (typeof updateInfo.releaseNotes === 'string') {
required = updateInfo.releaseNotes.includes('__update:required__') ?? false
}
this._showUpdateDialog(updateInfo.version, required).then((ignored) => {
// resolve the promise if the update is ignored
if (ignored) {
resolve()
}
})
})

autoUpdater.on('update-not-available', () => {
logger.info('appUpdater -> There is no available update')
resolve()
})

autoUpdater.on('download-progress', ({ percent }) => {
this._updaterWindow.show()
this._updaterWindow.sendProgress({ message: 'DOWNLOADING UPDATE', percent })
})

autoUpdater.on('update-downloaded', () => {
logger.info('appUpdater -> Update downloaded, will install now')
this._updaterWindow.close()
autoUpdater.quitAndInstall()
})

autoUpdater.on('error', (error: Error) => {
if (error) logger.info('appUpdater -> An error occured: ' + error)
reject(error)
})

autoUpdater.checkForUpdatesAndNotify().then(() => {
logger.info('appUpdater -> Update check done')
})
})
}

private _showUpdateDialog(newVersion: string, required: boolean): Promise<void> {
/**
*
* @param newVersion
* @param required
* @returns true if the update is ignored, false otherwise
*/
private _showUpdateDialog(newVersion: string, required: boolean): Promise<boolean> {
const buttons: Array<string> = [this._i18n.LL.main.updater.download()]
if (!required) {
buttons.push(this._i18n.LL.main.updater.ignore())
Expand All @@ -56,12 +100,21 @@ export class AppUpdater {
})
.then((returnValue) => {
if (returnValue.response === 0) {
logger.info('[UPDATE] Redirected to app download page.')
shell.openExternal('https://github.com/prixe/lindo/releases/latest')
app.exit()
return autoUpdater.downloadUpdate().catch(async (err) => {
logger.error('appUpdater -> unable to download automatically the release', err)
await this._downloadFromWeb()
return false
})
} else {
logger.info('[UPDATE] App update ignored.')
logger.info('appUpdater -> App update ignored.')
return true
}
})
}

private async _downloadFromWeb() {
logger.info('appUpdater -> Redirected to app download page.')
await shell.openExternal(GITHUB_LATEST_RELEASE_URL)
app.exit()
}
}
1 change: 1 addition & 0 deletions packages/main/updater/updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const runUpdater = async (rootStore: RootStore, i18n: I18n) => {
logger.error('Error running app updater:', err)
})

logger.info('runUpdater -> Start game update checking...')
const gameUpdater = await GameUpdater.init(rootStore)
await gameUpdater.run().catch((e) => {
console.log(e)
Expand Down
22 changes: 16 additions & 6 deletions packages/main/windows/updater-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ type UpdaterWindowEvents = {
close: (event: Event) => void
}

export interface UpdaterWindowOptions {
show?: boolean // will automatically show the window when dom is ready
}

export class UpdaterWindow extends (EventEmitter as new () => TypedEmitter<UpdaterWindowEvents>) {
private readonly _win: BrowserWindow

private constructor(userAgent: string) {
private constructor(userAgent: string, options?: UpdaterWindowOptions) {
super()
this._win = new BrowserWindow({
show: false,
Expand All @@ -32,9 +36,11 @@ export class UpdaterWindow extends (EventEmitter as new () => TypedEmitter<Updat
// Show window when page is ready
this._win.webContents.on('ipc-message', (event, channel) => {
if (channel === IPCEvents.APP_READY_TO_SHOW) {
setTimeout(() => {
this._win.show()
}, 100)
if (options?.show ?? true) {
setTimeout(() => {
this._win.show()
}, 100)
}
}
})

Expand All @@ -58,9 +64,9 @@ export class UpdaterWindow extends (EventEmitter as new () => TypedEmitter<Updat
}
}

static async init(store: RootStore): Promise<UpdaterWindow> {
static async init(store: RootStore, options?: UpdaterWindowOptions): Promise<UpdaterWindow> {
const userAgent = await generateUserArgent(store.appStore.appVersion)
return new UpdaterWindow(userAgent)
return new UpdaterWindow(userAgent, options)
}

sendProgress(progress: UpdateProgress) {
Expand All @@ -77,6 +83,10 @@ export class UpdaterWindow extends (EventEmitter as new () => TypedEmitter<Updat
this._win.close()
}

show() {
this._win.show()
}

focus = () => this._win.focus()
isMinimized = () => this._win.isMinimized()
restore = () => this._win.restore()
Expand Down
Loading

0 comments on commit 2778a98

Please sign in to comment.