11import { RootStore } from '@lindo/shared'
2- import { Octokit } from '@octokit/rest'
3- import compareVersions from 'compare-versions'
42import { app , dialog , shell } from 'electron'
53import { logger } from '../logger'
64import { I18n } from '../utils'
5+ import { autoUpdater , UpdateInfo } from 'electron-updater'
6+ import { UpdaterWindow } from '../windows/updater-window'
7+ import { GITHUB_LATEST_RELEASE_URL , GITHUB_OWNER , GITHUB_REPO } from '../constants'
78
89export class AppUpdater {
10+ private readonly _updaterWindow : UpdaterWindow
911 private readonly _rootStore : RootStore
10- private readonly _octokit : Octokit
1112 private readonly _i18n : I18n
1213
13- private constructor ( rootStore : RootStore , i18n : I18n ) {
14+ private constructor ( updaterWindow : UpdaterWindow , rootStore : RootStore , i18n : I18n ) {
15+ this . _updaterWindow = updaterWindow
1416 this . _rootStore = rootStore
1517 this . _i18n = i18n
16- this . _octokit = new Octokit ( )
1718 }
1819
1920 static async init ( rootStore : RootStore , i18n : I18n ) : Promise < AppUpdater > {
20- return new AppUpdater ( rootStore , i18n )
21+ const updaterWindow = await UpdaterWindow . init ( rootStore , { show : false } )
22+ return new AppUpdater ( updaterWindow , rootStore , i18n )
2123 }
2224
2325 async run ( ) {
2426 // set the current version of the app
27+ logger . info ( 'appUpdater -> Start app update checking...' )
2528 const currentVersion = app . getVersion ( )
2629 this . _rootStore . appStore . setLindoVersion ( currentVersion )
2730
28- return this . _octokit . repos
29- . getLatestRelease ( {
30- owner : 'prixe' ,
31- repo : 'lindo'
31+ autoUpdater . logger = logger
32+ autoUpdater . autoDownload = false
33+ autoUpdater . setFeedURL ( { provider : 'github' , owner : GITHUB_OWNER , repo : GITHUB_REPO } )
34+
35+ return new Promise < void > ( ( resolve , reject ) => {
36+ autoUpdater . on ( 'checking-for-update' , ( ) => {
37+ logger . info ( 'appUpdater -> Checking for updates...' )
3238 } )
33- . then ( ( res ) => {
34- const latestVersion = res . data . tag_name . replaceAll ( 'v ', '' )
35- const required = res . data . body ?. includes ( '__update:required__' ) ?? false
36- logger . info ( { latestVersion , currentVersion } )
37- if ( compareVersions ( latestVersion , currentVersion ) === 1 ) {
38- return this . _showUpdateDialog ( latestVersion , required )
39+
40+ autoUpdater . on ( 'update-available ', ( updateInfo : UpdateInfo ) => {
41+ logger . info ( 'appUpdater -> An Update is available v' + updateInfo . version )
42+ let required = false
43+ if ( typeof updateInfo . releaseNotes === 'string' ) {
44+ required = updateInfo . releaseNotes . includes ( '__update:required__' ) ?? false
3945 }
46+ this . _showUpdateDialog ( updateInfo . version , required ) . then ( ( ignored ) => {
47+ // resolve the promise if the update is ignored
48+ if ( ignored ) {
49+ resolve ( )
50+ }
51+ } )
52+ } )
53+
54+ autoUpdater . on ( 'update-not-available' , ( ) => {
55+ logger . info ( 'appUpdater -> There is no available update' )
56+ resolve ( )
57+ } )
58+
59+ autoUpdater . on ( 'download-progress' , ( { percent } ) => {
60+ this . _updaterWindow . show ( )
61+ this . _updaterWindow . sendProgress ( { message : 'DOWNLOADING UPDATE' , percent } )
62+ } )
63+
64+ autoUpdater . on ( 'update-downloaded' , ( ) => {
65+ logger . info ( 'appUpdater -> Update downloaded, will install now' )
66+ this . _updaterWindow . close ( )
67+ autoUpdater . quitAndInstall ( )
68+ } )
69+
70+ autoUpdater . on ( 'error' , ( error : Error ) => {
71+ if ( error ) logger . info ( 'appUpdater -> An error occured: ' + error )
72+ reject ( error )
4073 } )
74+
75+ autoUpdater . checkForUpdatesAndNotify ( ) . then ( ( ) => {
76+ logger . info ( 'appUpdater -> Update check done' )
77+ } )
78+ } )
4179 }
4280
43- private _showUpdateDialog ( newVersion : string , required : boolean ) : Promise < void > {
81+ /**
82+ *
83+ * @param newVersion
84+ * @param required
85+ * @returns true if the update is ignored, false otherwise
86+ */
87+ private _showUpdateDialog ( newVersion : string , required : boolean ) : Promise < boolean > {
4488 const buttons : Array < string > = [ this . _i18n . LL . main . updater . download ( ) ]
4589 if ( ! required ) {
4690 buttons . push ( this . _i18n . LL . main . updater . ignore ( ) )
@@ -56,12 +100,21 @@ export class AppUpdater {
56100 } )
57101 . then ( ( returnValue ) => {
58102 if ( returnValue . response === 0 ) {
59- logger . info ( '[UPDATE] Redirected to app download page.' )
60- shell . openExternal ( 'https://github.com/prixe/lindo/releases/latest' )
61- app . exit ( )
103+ return autoUpdater . downloadUpdate ( ) . catch ( async ( err ) => {
104+ logger . error ( 'appUpdater -> unable to download automatically the release' , err )
105+ await this . _downloadFromWeb ( )
106+ return false
107+ } )
62108 } else {
63- logger . info ( '[UPDATE] App update ignored.' )
109+ logger . info ( 'appUpdater -> App update ignored.' )
110+ return true
64111 }
65112 } )
66113 }
114+
115+ private async _downloadFromWeb ( ) {
116+ logger . info ( 'appUpdater -> Redirected to app download page.' )
117+ await shell . openExternal ( GITHUB_LATEST_RELEASE_URL )
118+ app . exit ( )
119+ }
67120}
0 commit comments