import { dialog , Menu , MenuItem , shell } from "electron" ; import log from "electron-log" ; import { autoUpdater } from "electron-updater" ; import { isAppImage , isDev , isMacAppStore , isWindowsPortable , isWindowsStore } from "./utils" ; import { I18nService } from "jslib-common/abstractions/i18n.service" ; import { WindowMain } from "./window.main" ; const UpdaterCheckInitalDelay = 5 * 1000 ; const UpdaterCheckInterval = 12 * 60 * 60 * 1000 ; export class UpdaterMain { private doingUpdateCheck = false ; private doingUpdateCheckWithFeedback = false ; private canUpdate = false ; constructor ( private i18nService , private windowMain , private gitHubProject , private onCheckingForUpdate = null , private onReset = null , private onUpdateDownloaded = null , private projectName ) { autoUpdater . logger = log ; const linuxCanUpdate = process . platform === "linux" && isAppImage ( ) ; const windowsCanUpdate = process . platform === "win32" && ! isWindowsStore ( ) && ! isWindowsPortable ( ) ; const macCanUpdate = process . platform === "darwin" && ! isMacAppStore ( ) ; this . canUpdate = process . env . ELECTRON_NO_UPDATER !== "1" && ( linuxCanUpdate || windowsCanUpdate || macCanUpdate ) ; } async init ( ) { global . setTimeout ( async ( ) => await this . checkForUpdate ( ) , UpdaterCheckInitalDelay ) ; global . setInterval ( async ( ) => await this . checkForUpdate ( ) , UpdaterCheckInterval ) ; autoUpdater . on ( "checking-for-update" , ( ) => { if ( this . onCheckingForUpdate != null ) { this . onCheckingForUpdate ( ) ; } this . doingUpdateCheck = true ; } ) ; autoUpdater . on ( "update-available" , async ( ) => { if ( this . doingUpdateCheckWithFeedback ) { if ( this . windowMain . win == null ) { this . reset ( ) ; return ; } const result = await dialog . showMessageBox ( this . windowMain . win , { type : "info" , title : this . i18nService . t ( this . projectName ) + " - " + this . i18nService . t ( "updateAvailable" ) , message : this . i18nService . t ( "updateAvailable" ) , detail : this . i18nService . t ( "updateAvailableDesc" ) , buttons : [ this . i18nService . t ( "yes" ) , this . i18nService . t ( "no" ) ] , cancelId : 1 , defaultId : 0 , noLink : true , } ) ; if ( result . response === 0 ) { autoUpdater . downloadUpdate ( ) ; } else { this . reset ( ) ; } } } ) ; autoUpdater . on ( "update-not-available" , ( ) => { if ( this . doingUpdateCheckWithFeedback && this . windowMain . win != null ) { dialog . showMessageBox ( this . windowMain . win , { message : this . i18nService . t ( "noUpdatesAvailable" ) , buttons : [ this . i18nService . t ( "ok" ) ] , defaultId : 0 , noLink : true , } ) ; } this . reset ( ) ; } ) ; autoUpdater . on ( "update-downloaded" , async ( info ) => { if ( this . onUpdateDownloaded != null ) { this . onUpdateDownloaded ( ) ; } if ( this . windowMain . win == null ) { return ; } const result = await dialog . showMessageBox ( this . windowMain . win , { type : "info" , title : this . i18nService . t ( this . projectName ) + " - " + this . i18nService . t ( "restartToUpdate" ) , message : this . i18nService . t ( "restartToUpdate" ) , detail : this . i18nService . t ( "restartToUpdateDesc" , info . version ) , buttons : [ this . i18nService . t ( "restart" ) , this . i18nService . t ( "later" ) ] , cancelId : 1 , defaultId : 0 , noLink : true , } ) ; if ( result . response === 0 ) { autoUpdater . quitAndInstall ( false , true ) ; } } ) ; autoUpdater . on ( "error" , ( error ) => { if ( this . doingUpdateCheckWithFeedback ) { dialog . showErrorBox ( this . i18nService . t ( "updateError" ) , error == null ? this . i18nService . t ( "unknown" ) : ( error . stack || error ) . toString ( ) ) ; } this . reset ( ) ; } ) ; } async checkForUpdate ( withFeedback = false ) { if ( this . doingUpdateCheck || isDev ( ) ) { return ; } if ( ! this . canUpdate ) { if ( withFeedback ) { shell . openExternal ( "https://github.com/bitwarden/" + this . gitHubProject + "/releases" ) ; } return ; } this . doingUpdateCheckWithFeedback = withFeedback ; if ( withFeedback ) { autoUpdater . autoDownload = false ; } await autoUpdater . checkForUpdates ( ) ; } private reset ( ) { if ( this . onReset != null ) { this . onReset ( ) ; } autoUpdater . autoDownload = true ; this . doingUpdateCheck = false ; } }