diff options
author | 2018-01-17 10:34:22 +0400 | |
---|---|---|
committer | 2018-01-17 10:34:22 +0400 | |
commit | 81b49fba430959ec4e0946f905dc182d2733831c (patch) | |
tree | a1979dafda41ac804986ef57a68912a868cb5ac7 /src/stores | |
parent | Remove idle timer dependency (diff) | |
parent | Merge branch 'develop' of github.com:meetfranz/franz into develop (diff) | |
download | ferdium-app-81b49fba430959ec4e0946f905dc182d2733831c.tar.gz ferdium-app-81b49fba430959ec4e0946f905dc182d2733831c.tar.zst ferdium-app-81b49fba430959ec4e0946f905dc182d2733831c.zip |
Merge branch 'develop' into feature/remove-miner
Diffstat (limited to 'src/stores')
-rw-r--r-- | src/stores/AppStore.js | 57 | ||||
-rw-r--r-- | src/stores/ServicesStore.js | 42 |
2 files changed, 90 insertions, 9 deletions
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 3eddff5ed..772b33c67 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js | |||
@@ -1,9 +1,10 @@ | |||
1 | import { remote, ipcRenderer, shell } from 'electron'; | 1 | import { remote, ipcRenderer, shell } from 'electron'; |
2 | import { action, observable } from 'mobx'; | 2 | import { action, computed, observable } from 'mobx'; |
3 | import moment from 'moment'; | 3 | import moment from 'moment'; |
4 | import key from 'keymaster'; | 4 | import key from 'keymaster'; |
5 | import { getDoNotDisturb } from '@meetfranz/electron-notification-state'; | 5 | import { getDoNotDisturb } from '@meetfranz/electron-notification-state'; |
6 | import AutoLaunch from 'auto-launch'; | 6 | import AutoLaunch from 'auto-launch'; |
7 | import prettyBytes from 'pretty-bytes'; | ||
7 | 8 | ||
8 | import Store from './lib/Store'; | 9 | import Store from './lib/Store'; |
9 | import Request from './lib/Request'; | 10 | import Request from './lib/Request'; |
@@ -12,7 +13,10 @@ import { isMac } from '../environment'; | |||
12 | import locales from '../i18n/translations'; | 13 | import locales from '../i18n/translations'; |
13 | import { gaEvent } from '../lib/analytics'; | 14 | import { gaEvent } from '../lib/analytics'; |
14 | 15 | ||
15 | const { app, powerMonitor } = remote; | 16 | import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '../helpers/service-helpers.js'; |
17 | |||
18 | const { app } = remote; | ||
19 | |||
16 | const defaultLocale = DEFAULT_APP_SETTINGS.locale; | 20 | const defaultLocale = DEFAULT_APP_SETTINGS.locale; |
17 | const autoLauncher = new AutoLaunch({ | 21 | const autoLauncher = new AutoLaunch({ |
18 | name: 'Franz', | 22 | name: 'Franz', |
@@ -28,6 +32,8 @@ export default class AppStore extends Store { | |||
28 | }; | 32 | }; |
29 | 33 | ||
30 | @observable healthCheckRequest = new Request(this.api.app, 'health'); | 34 | @observable healthCheckRequest = new Request(this.api.app, 'health'); |
35 | @observable getAppCacheSizeRequest = new Request(this.api.local, 'getAppCacheSize'); | ||
36 | @observable clearAppCacheRequest = new Request(this.api.local, 'clearAppCache'); | ||
31 | 37 | ||
32 | @observable autoLaunchOnStart = true; | 38 | @observable autoLaunchOnStart = true; |
33 | 39 | ||
@@ -40,6 +46,8 @@ export default class AppStore extends Store { | |||
40 | 46 | ||
41 | @observable isSystemMuteOverridden = false; | 47 | @observable isSystemMuteOverridden = false; |
42 | 48 | ||
49 | @observable isClearingAllCache = false; | ||
50 | |||
43 | constructor(...args) { | 51 | constructor(...args) { |
44 | super(...args); | 52 | super(...args); |
45 | 53 | ||
@@ -54,6 +62,7 @@ export default class AppStore extends Store { | |||
54 | this.actions.app.healthCheck.listen(this._healthCheck.bind(this)); | 62 | this.actions.app.healthCheck.listen(this._healthCheck.bind(this)); |
55 | this.actions.app.muteApp.listen(this._muteApp.bind(this)); | 63 | this.actions.app.muteApp.listen(this._muteApp.bind(this)); |
56 | this.actions.app.toggleMuteApp.listen(this._toggleMuteApp.bind(this)); | 64 | this.actions.app.toggleMuteApp.listen(this._toggleMuteApp.bind(this)); |
65 | this.actions.app.clearAllCache.listen(this._clearAllCache.bind(this)); | ||
57 | 66 | ||
58 | this.registerReactions([ | 67 | this.registerReactions([ |
59 | this._offlineCheck.bind(this), | 68 | this._offlineCheck.bind(this), |
@@ -116,9 +125,16 @@ export default class AppStore extends Store { | |||
116 | }); | 125 | }); |
117 | 126 | ||
118 | // Reload all services after a healthy nap | 127 | // Reload all services after a healthy nap |
119 | powerMonitor.on('resume', () => { | 128 | // Alternative solution for powerMonitor as the resume event is not fired |
120 | setTimeout(window.location.reload, 5000); | 129 | // More information: https://github.com/electron/electron/issues/1615 |
121 | }); | 130 | let lastTime = (new Date()).getTime(); |
131 | setInterval(() => { | ||
132 | const currentTime = (new Date()).getTime(); | ||
133 | if (currentTime > (lastTime + TIMEOUT + 2000)) { | ||
134 | this._reactivateServices(); | ||
135 | } | ||
136 | lastTime = currentTime; | ||
137 | }, TIMEOUT); | ||
122 | 138 | ||
123 | // Set active the next service | 139 | // Set active the next service |
124 | key( | 140 | key( |
@@ -143,6 +159,10 @@ export default class AppStore extends Store { | |||
143 | this._healthCheck(); | 159 | this._healthCheck(); |
144 | } | 160 | } |
145 | 161 | ||
162 | @computed get cacheSize() { | ||
163 | return prettyBytes(this.getAppCacheSizeRequest.execute().result || 0); | ||
164 | } | ||
165 | |||
146 | // Actions | 166 | // Actions |
147 | @action _notify({ title, options, notificationId, serviceId = null }) { | 167 | @action _notify({ title, options, notificationId, serviceId = null }) { |
148 | if (this.stores.settings.all.isAppMuted) return; | 168 | if (this.stores.settings.all.isAppMuted) return; |
@@ -233,6 +253,23 @@ export default class AppStore extends Store { | |||
233 | this._muteApp({ isMuted: !this.stores.settings.all.isAppMuted }); | 253 | this._muteApp({ isMuted: !this.stores.settings.all.isAppMuted }); |
234 | } | 254 | } |
235 | 255 | ||
256 | @action async _clearAllCache() { | ||
257 | this.isClearingAllCache = true; | ||
258 | const clearAppCache = this.clearAppCacheRequest.execute(); | ||
259 | const allServiceIds = await getServiceIdsFromPartitions(); | ||
260 | const allOrphanedServiceIds = allServiceIds.filter(id => !this.stores.services.all.find(s => id.replace('service-', '') === s.id)); | ||
261 | |||
262 | await Promise.all(allOrphanedServiceIds.map(id => removeServicePartitionDirectory(id))); | ||
263 | |||
264 | await Promise.all(this.stores.services.all.map(s => this.actions.service.clearCache({ serviceId: s.id }))); | ||
265 | |||
266 | await clearAppCache._promise; | ||
267 | |||
268 | this.getAppCacheSizeRequest.execute(); | ||
269 | |||
270 | this.isClearingAllCache = false; | ||
271 | } | ||
272 | |||
236 | // Reactions | 273 | // Reactions |
237 | _offlineCheck() { | 274 | _offlineCheck() { |
238 | if (!this.isOnline) { | 275 | if (!this.isOnline) { |
@@ -321,6 +358,16 @@ export default class AppStore extends Store { | |||
321 | return autoLauncher.isEnabled() || false; | 358 | return autoLauncher.isEnabled() || false; |
322 | } | 359 | } |
323 | 360 | ||
361 | _reactivateServices(retryCount = 0) { | ||
362 | if (!this.isOnline) { | ||
363 | console.debug('reactivateServices: computer is offline, trying again in 5s, retries:', retryCount); | ||
364 | setTimeout(() => this._reactivateServices(retryCount + 1), 5000); | ||
365 | } else { | ||
366 | console.debug('reactivateServices: reload all services'); | ||
367 | this.actions.service.reloadAll(); | ||
368 | } | ||
369 | } | ||
370 | |||
324 | _systemDND() { | 371 | _systemDND() { |
325 | const dnd = getDoNotDisturb(); | 372 | const dnd = getDoNotDisturb(); |
326 | if (dnd === this.stores.settings.all.isAppMuted || !this.isSystemMuteOverriden) { | 373 | if (dnd === this.stores.settings.all.isAppMuted || !this.isSystemMuteOverriden) { |
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 66f37af26..20e07e540 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js | |||
@@ -16,6 +16,7 @@ export default class ServicesStore extends Store { | |||
16 | @observable updateServiceRequest = new Request(this.api.services, 'update'); | 16 | @observable updateServiceRequest = new Request(this.api.services, 'update'); |
17 | @observable reorderServicesRequest = new Request(this.api.services, 'reorder'); | 17 | @observable reorderServicesRequest = new Request(this.api.services, 'reorder'); |
18 | @observable deleteServiceRequest = new Request(this.api.services, 'delete'); | 18 | @observable deleteServiceRequest = new Request(this.api.services, 'delete'); |
19 | @observable clearCacheRequest = new Request(this.api.services, 'clearCache'); | ||
19 | 20 | ||
20 | @observable filterNeedle = null; | 21 | @observable filterNeedle = null; |
21 | 22 | ||
@@ -31,6 +32,7 @@ export default class ServicesStore extends Store { | |||
31 | this.actions.service.createFromLegacyService.listen(this._createFromLegacyService.bind(this)); | 32 | this.actions.service.createFromLegacyService.listen(this._createFromLegacyService.bind(this)); |
32 | this.actions.service.updateService.listen(this._updateService.bind(this)); | 33 | this.actions.service.updateService.listen(this._updateService.bind(this)); |
33 | this.actions.service.deleteService.listen(this._deleteService.bind(this)); | 34 | this.actions.service.deleteService.listen(this._deleteService.bind(this)); |
35 | this.actions.service.clearCache.listen(this._clearCache.bind(this)); | ||
34 | this.actions.service.setWebviewReference.listen(this._setWebviewReference.bind(this)); | 36 | this.actions.service.setWebviewReference.listen(this._setWebviewReference.bind(this)); |
35 | this.actions.service.focusService.listen(this._focusService.bind(this)); | 37 | this.actions.service.focusService.listen(this._focusService.bind(this)); |
36 | this.actions.service.focusActiveService.listen(this._focusActiveService.bind(this)); | 38 | this.actions.service.focusActiveService.listen(this._focusActiveService.bind(this)); |
@@ -172,9 +174,29 @@ export default class ServicesStore extends Store { | |||
172 | const data = this._cleanUpTeamIdAndCustomUrl(service.recipe.id, serviceData); | 174 | const data = this._cleanUpTeamIdAndCustomUrl(service.recipe.id, serviceData); |
173 | const request = this.updateServiceRequest.execute(serviceId, data); | 175 | const request = this.updateServiceRequest.execute(serviceId, data); |
174 | 176 | ||
177 | const newData = serviceData; | ||
178 | if (serviceData.iconFile) { | ||
179 | await request._promise; | ||
180 | |||
181 | newData.iconUrl = request.result.data.iconUrl; | ||
182 | newData.hasCustomUploadedIcon = true; | ||
183 | } | ||
184 | |||
175 | this.allServicesRequest.patch((result) => { | 185 | this.allServicesRequest.patch((result) => { |
176 | if (!result) return; | 186 | if (!result) return; |
177 | Object.assign(result.find(c => c.id === serviceId), serviceData); | 187 | |
188 | // patch custom icon deletion | ||
189 | if (data.customIcon === 'delete') { | ||
190 | newData.iconUrl = ''; | ||
191 | newData.hasCustomUploadedIcon = false; | ||
192 | } | ||
193 | |||
194 | // patch custom icon url | ||
195 | if (data.customIconUrl) { | ||
196 | newData.iconUrl = data.customIconUrl; | ||
197 | } | ||
198 | |||
199 | Object.assign(result.find(c => c.id === serviceId), newData); | ||
178 | }); | 200 | }); |
179 | 201 | ||
180 | await request._promise; | 202 | await request._promise; |
@@ -205,6 +227,13 @@ export default class ServicesStore extends Store { | |||
205 | gaEvent('Service', 'delete', service.recipe.id); | 227 | gaEvent('Service', 'delete', service.recipe.id); |
206 | } | 228 | } |
207 | 229 | ||
230 | @action async _clearCache({ serviceId }) { | ||
231 | this.clearCacheRequest.reset(); | ||
232 | const request = this.clearCacheRequest.execute(serviceId); | ||
233 | await request._promise; | ||
234 | gaEvent('Service', 'clear cache'); | ||
235 | } | ||
236 | |||
208 | @action _setActive({ serviceId }) { | 237 | @action _setActive({ serviceId }) { |
209 | const service = this.one(serviceId); | 238 | const service = this.one(serviceId); |
210 | 239 | ||
@@ -316,7 +345,7 @@ export default class ServicesStore extends Store { | |||
316 | } | 345 | } |
317 | } else if (channel === 'avatar') { | 346 | } else if (channel === 'avatar') { |
318 | const url = args[0]; | 347 | const url = args[0]; |
319 | if (service.customIconUrl !== url) { | 348 | if (service.iconUrl !== url && !service.hasCustomUploadedIcon) { |
320 | service.customIconUrl = url; | 349 | service.customIconUrl = url; |
321 | 350 | ||
322 | this.actions.service.updateService({ | 351 | this.actions.service.updateService({ |
@@ -327,6 +356,10 @@ export default class ServicesStore extends Store { | |||
327 | redirect: false, | 356 | redirect: false, |
328 | }); | 357 | }); |
329 | } | 358 | } |
359 | } else if (channel === 'new-window') { | ||
360 | const url = args[0]; | ||
361 | |||
362 | this.actions.app.openExternalUrl({ url }); | ||
330 | } | 363 | } |
331 | } | 364 | } |
332 | 365 | ||
@@ -368,7 +401,7 @@ export default class ServicesStore extends Store { | |||
368 | const service = this.one(serviceId); | 401 | const service = this.one(serviceId); |
369 | service.resetMessageCount(); | 402 | service.resetMessageCount(); |
370 | 403 | ||
371 | service.webview.reload(); | 404 | service.webview.loadURL(service.url); |
372 | } | 405 | } |
373 | 406 | ||
374 | @action _reloadActive() { | 407 | @action _reloadActive() { |
@@ -497,12 +530,13 @@ export default class ServicesStore extends Store { | |||
497 | .reduce((a, b) => a + b, 0); | 530 | .reduce((a, b) => a + b, 0); |
498 | 531 | ||
499 | const unreadIndirectMessageCount = this.allDisplayed | 532 | const unreadIndirectMessageCount = this.allDisplayed |
500 | .filter(s => (showMessageBadgeWhenMuted || s.isIndirectMessageBadgeEnabled) && showMessageBadgesEvenWhenMuted && s.isBadgeEnabled) | 533 | .filter(s => (showMessageBadgeWhenMuted && showMessageBadgesEvenWhenMuted) && (s.isBadgeEnabled && s.isIndirectMessageBadgeEnabled)) |
501 | .map(s => s.unreadIndirectMessageCount) | 534 | .map(s => s.unreadIndirectMessageCount) |
502 | .reduce((a, b) => a + b, 0); | 535 | .reduce((a, b) => a + b, 0); |
503 | 536 | ||
504 | // We can't just block this earlier, otherwise the mobx reaction won't be aware of the vars to watch in some cases | 537 | // We can't just block this earlier, otherwise the mobx reaction won't be aware of the vars to watch in some cases |
505 | if (showMessageBadgesEvenWhenMuted) { | 538 | if (showMessageBadgesEvenWhenMuted) { |
539 | console.log('set badge', unreadDirectMessageCount, unreadIndirectMessageCount); | ||
506 | this.actions.app.setBadge({ | 540 | this.actions.app.setBadge({ |
507 | unreadDirectMessageCount, | 541 | unreadDirectMessageCount, |
508 | unreadIndirectMessageCount, | 542 | unreadIndirectMessageCount, |