forked from floating/frame
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
205 lines (154 loc) · 5.25 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import log from 'electron-log'
import store from '../store'
import { openExternal } from '../windows/window'
import AutoUpdater from './autoUpdater'
import manualCheck from './manualCheck'
export interface VersionUpdate {
version: string
location: string
}
const isMac = process.platform === 'darwin'
const isWindows = process.platform === 'win32'
const UPDATE_INTERVAL = parseInt(process.env.UPDATE_INTERVAL || '') || 60 * 60_000
const useAutoUpdater = isMac || isWindows
class Updater {
private autoUpdater?: AutoUpdater
// this will only be set if an upgrade-eligible version is found
private availableUpdate = ''
private availableVersion = ''
private installerReady = false
private setupCheck?: NodeJS.Timeout
private pendingCheck?: NodeJS.Timeout
private notified: Record<string, boolean> = {}
start() {
log.verbose('Starting updater', { useAutoUpdater })
this.stopUpdates()
const check = useAutoUpdater ? () => this.checkForAutoUpdate() : () => this.checkForManualUpdate()
this.setupCheck = setTimeout(() => {
check()
this.pendingCheck = setInterval(check, UPDATE_INTERVAL)
}, 10_000)
}
stop() {
log.verbose('Stopping updater')
this.stopUpdates()
}
get updateReady() {
return this.installerReady
}
fetchUpdate() {
if (this.availableUpdate === 'auto') {
if (!this.autoUpdater) {
log.warn(`update ${this.availableVersion} is asking to be downloaded but autoUpdater is not running!`)
return
}
log.info(`Downloading update for version ${this.availableVersion}`)
this.autoUpdater.downloadUpdate()
} else if (this.availableUpdate.startsWith('https')) {
log.verbose(`Opening release page for version ${this.availableVersion}`)
openExternal(this.availableUpdate)
}
}
quitAndInstall() {
if (this.installerReady) {
if (!this.autoUpdater) {
log.warn(`update ${this.availableVersion} is asking to be installed but autoUpdater is not running!`)
return
}
log.info(`Quitting, will install ${this.availableVersion} on restart`)
this.autoUpdater.quitAndInstall()
}
}
dismissUpdate() {
log.verbose('Dismissed update', { version: this.availableVersion })
this.availableUpdate = ''
this.availableVersion = ''
}
private stopUpdates() {
if (this.setupCheck) {
clearTimeout(this.setupCheck)
this.setupCheck = undefined
}
if (this.pendingCheck) {
clearInterval(this.pendingCheck)
this.pendingCheck = undefined
}
if (this.autoUpdater) {
this.autoUpdater.close()
this.autoUpdater = undefined
}
}
private updateAvailable(version: string, location: string) {
log.verbose('Found available update', {
version,
location,
alreadyNotified: this.notified[version] || false
})
if (!this.notified[version]) {
// a newer version is available
this.availableVersion = version
this.availableUpdate = location
const remindOk = !store('main.updater.dontRemind').includes(version)
if (remindOk) {
store.updateBadge('updateAvailable', this.availableVersion)
} else {
log.verbose(`Update to version ${version} is available but user chose to skip`)
}
this.notified[version] = true
}
}
// an update has been downloaded and is ready to be installed
private readyForInstall() {
this.installerReady = true
store.updateBadge('updateReady')
}
private checkForAutoUpdate() {
log.debug('Doing automatic check for app update')
const switchToManualUpdate = () => {
this.dismissUpdate()
this.checkForManualUpdate()
}
if (!this.autoUpdater) {
this.autoUpdater = new AutoUpdater()
this.autoUpdater.on('update-available', (update: VersionUpdate) => {
const { version, location } = update
log.info('Auto check found available update', { version, location })
this.updateAvailable(version, location)
})
this.autoUpdater.on('update-not-available', () => {
log.info('No available updates found by auto check, checking manually')
switchToManualUpdate()
})
this.autoUpdater.on('update-downloaded', () => {
log.info('Auto check update downloaded and ready for install')
if (!this.installerReady) this.readyForInstall()
})
this.autoUpdater.on('error', (err: Error) => {
this.installerReady = false
log.warn('Error auto checking for update, checking manually', err)
switchToManualUpdate()
})
this.autoUpdater.on('exit', () => {
log.verbose('Auto updater exited')
this.autoUpdater = undefined
})
}
this.autoUpdater.checkForUpdates()
}
private async checkForManualUpdate() {
log.debug('Checking for app update manually')
try {
const update = await manualCheck({ prereleaseTrack: false })
if (!update) {
log.info('Manual check found no updates')
} else {
const { version, location } = update
log.debug('Manual check found available update', { version, location })
this.updateAvailable(version, location)
}
} catch (e) {
log.error('Error performing manual check for updates', e)
}
}
}
export default new Updater()