diff options
Diffstat (limited to 'src/stores')
-rw-r--r-- | src/stores/AppStore.js | 60 | ||||
-rw-r--r-- | src/stores/ServicesStore.js | 53 | ||||
-rw-r--r-- | src/stores/SettingsStore.js | 18 | ||||
-rw-r--r-- | src/stores/UIStore.js | 8 | ||||
-rw-r--r-- | src/stores/UserStore.js | 6 |
5 files changed, 116 insertions, 29 deletions
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 14bdab094..5a6c12ee1 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js | |||
@@ -45,7 +45,7 @@ export default class AppStore extends Store { | |||
45 | miner = null; | 45 | miner = null; |
46 | @observable minerHashrate = 0.0; | 46 | @observable minerHashrate = 0.0; |
47 | 47 | ||
48 | @observable isSystemMuted = false; | 48 | @observable isSystemMuteOverridden = false; |
49 | 49 | ||
50 | constructor(...args) { | 50 | constructor(...args) { |
51 | super(...args); | 51 | super(...args); |
@@ -67,6 +67,7 @@ export default class AppStore extends Store { | |||
67 | this._setLocale.bind(this), | 67 | this._setLocale.bind(this), |
68 | this._handleMiner.bind(this), | 68 | this._handleMiner.bind(this), |
69 | this._handleMinerThrottle.bind(this), | 69 | this._handleMinerThrottle.bind(this), |
70 | this._muteAppHandler.bind(this), | ||
70 | ]); | 71 | ]); |
71 | } | 72 | } |
72 | 73 | ||
@@ -115,6 +116,14 @@ export default class AppStore extends Store { | |||
115 | } | 116 | } |
116 | }); | 117 | }); |
117 | 118 | ||
119 | // Handle deep linking (franz://) | ||
120 | ipcRenderer.on('navigateFromDeepLink', (event, data) => { | ||
121 | const { url } = data; | ||
122 | if (!url) return; | ||
123 | |||
124 | this.stores.router.push(data.url); | ||
125 | }); | ||
126 | |||
118 | // Check system idle time every minute | 127 | // Check system idle time every minute |
119 | setInterval(() => { | 128 | setInterval(() => { |
120 | this.idleTime = idleTimer.getIdleTime(); | 129 | this.idleTime = idleTimer.getIdleTime(); |
@@ -127,16 +136,22 @@ export default class AppStore extends Store { | |||
127 | 136 | ||
128 | // Set active the next service | 137 | // Set active the next service |
129 | key( | 138 | key( |
130 | '⌘+pagedown, ctrl+pagedown, ⌘+tab, ctrl+tab', () => { | 139 | '⌘+pagedown, ctrl+pagedown, ⌘+alt+right, ctrl+tab', () => { |
131 | this.actions.service.setActiveNext(); | 140 | this.actions.service.setActiveNext(); |
132 | }); | 141 | }); |
133 | 142 | ||
134 | // Set active the prev service | 143 | // Set active the prev service |
135 | key( | 144 | key( |
136 | '⌘+pageup, ctrl+pageup, ⌘+shift+tab, ctrl+shift+tab', () => { | 145 | '⌘+pageup, ctrl+pageup, ⌘+alt+left, ctrl+shift+tab', () => { |
137 | this.actions.service.setActivePrev(); | 146 | this.actions.service.setActivePrev(); |
138 | }); | 147 | }); |
139 | 148 | ||
149 | // Global Mute | ||
150 | key( | ||
151 | '⌘+shift+m ctrl+shift+m', () => { | ||
152 | this.actions.app.toggleMuteApp(); | ||
153 | }); | ||
154 | |||
140 | this.locale = this._getDefaultLocale(); | 155 | this.locale = this._getDefaultLocale(); |
141 | 156 | ||
142 | this._healthCheck(); | 157 | this._healthCheck(); |
@@ -144,6 +159,8 @@ export default class AppStore extends Store { | |||
144 | 159 | ||
145 | // Actions | 160 | // Actions |
146 | @action _notify({ title, options, notificationId, serviceId = null }) { | 161 | @action _notify({ title, options, notificationId, serviceId = null }) { |
162 | if (this.stores.settings.all.isAppMuted) return; | ||
163 | |||
147 | const notification = new window.Notification(title, options); | 164 | const notification = new window.Notification(title, options); |
148 | notification.onclick = (e) => { | 165 | notification.onclick = (e) => { |
149 | if (serviceId) { | 166 | if (serviceId) { |
@@ -154,6 +171,11 @@ export default class AppStore extends Store { | |||
154 | }); | 171 | }); |
155 | 172 | ||
156 | this.actions.service.setActive({ serviceId }); | 173 | this.actions.service.setActive({ serviceId }); |
174 | |||
175 | if (!isMac) { | ||
176 | const mainWindow = remote.getCurrentWindow(); | ||
177 | mainWindow.restore(); | ||
178 | } | ||
157 | } | 179 | } |
158 | }; | 180 | }; |
159 | } | 181 | } |
@@ -211,16 +233,18 @@ export default class AppStore extends Store { | |||
211 | this.healthCheckRequest.execute(); | 233 | this.healthCheckRequest.execute(); |
212 | } | 234 | } |
213 | 235 | ||
214 | @action _muteApp({ isMuted }) { | 236 | @action _muteApp({ isMuted, overrideSystemMute = true }) { |
237 | this.isSystemMuteOverriden = overrideSystemMute; | ||
238 | |||
215 | this.actions.settings.update({ | 239 | this.actions.settings.update({ |
216 | settings: { | 240 | settings: { |
217 | isMuted, | 241 | isAppMuted: isMuted, |
218 | }, | 242 | }, |
219 | }); | 243 | }); |
220 | } | 244 | } |
221 | 245 | ||
222 | @action _toggleMuteApp() { | 246 | @action _toggleMuteApp() { |
223 | this._muteApp({ isMuted: !this.stores.settings.all.isMuted }); | 247 | this._muteApp({ isMuted: !this.stores.settings.all.isAppMuted }); |
224 | } | 248 | } |
225 | 249 | ||
226 | // Reactions | 250 | // Reactions |
@@ -239,8 +263,10 @@ export default class AppStore extends Store { | |||
239 | _setLocale() { | 263 | _setLocale() { |
240 | const locale = this.stores.settings.all.locale; | 264 | const locale = this.stores.settings.all.locale; |
241 | 265 | ||
242 | if (locale && locale !== this.locale) { | 266 | if (locale && Object.prototype.hasOwnProperty.call(locales, locale) && locale !== this.locale) { |
243 | this.locale = locale; | 267 | this.locale = locale; |
268 | } else if (!locale) { | ||
269 | this.locale = this._getDefaultLocale(); | ||
244 | } | 270 | } |
245 | } | 271 | } |
246 | 272 | ||
@@ -265,6 +291,10 @@ export default class AppStore extends Store { | |||
265 | locale = defaultLocale; | 291 | locale = defaultLocale; |
266 | } | 292 | } |
267 | 293 | ||
294 | if (!locale) { | ||
295 | locale = DEFAULT_APP_SETTINGS.fallbackLocale; | ||
296 | } | ||
297 | |||
268 | return locale; | 298 | return locale; |
269 | } | 299 | } |
270 | 300 | ||
@@ -290,6 +320,14 @@ export default class AppStore extends Store { | |||
290 | } | 320 | } |
291 | } | 321 | } |
292 | 322 | ||
323 | _muteAppHandler() { | ||
324 | const showMessageBadgesEvenWhenMuted = this.stores.ui.showMessageBadgesEvenWhenMuted; | ||
325 | |||
326 | if (!showMessageBadgesEvenWhenMuted) { | ||
327 | this.actions.app.setBadge({ unreadDirectMessageCount: 0, unreadIndirectMessageCount: 0 }); | ||
328 | } | ||
329 | } | ||
330 | |||
293 | // Helpers | 331 | // Helpers |
294 | async _appStartsCounter() { | 332 | async _appStartsCounter() { |
295 | // we need to wait until the settings request is resolved | 333 | // we need to wait until the settings request is resolved |
@@ -320,6 +358,12 @@ export default class AppStore extends Store { | |||
320 | } | 358 | } |
321 | 359 | ||
322 | _systemDND() { | 360 | _systemDND() { |
323 | this.isSystemMuted = getDoNotDisturb(); | 361 | const dnd = getDoNotDisturb(); |
362 | if (dnd === this.stores.settings.all.isAppMuted || !this.isSystemMuteOverriden) { | ||
363 | this.actions.app.muteApp({ | ||
364 | isMuted: dnd, | ||
365 | overrideSystemMute: false, | ||
366 | }); | ||
367 | } | ||
324 | } | 368 | } |
325 | } | 369 | } |
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 269cd1526..66f37af26 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js | |||
@@ -37,6 +37,7 @@ export default class ServicesStore extends Store { | |||
37 | this.actions.service.toggleService.listen(this._toggleService.bind(this)); | 37 | this.actions.service.toggleService.listen(this._toggleService.bind(this)); |
38 | this.actions.service.handleIPCMessage.listen(this._handleIPCMessage.bind(this)); | 38 | this.actions.service.handleIPCMessage.listen(this._handleIPCMessage.bind(this)); |
39 | this.actions.service.sendIPCMessage.listen(this._sendIPCMessage.bind(this)); | 39 | this.actions.service.sendIPCMessage.listen(this._sendIPCMessage.bind(this)); |
40 | this.actions.service.sendIPCMessageToAllServices.listen(this._sendIPCMessageToAllServices.bind(this)); | ||
40 | this.actions.service.setUnreadMessageCount.listen(this._setUnreadMessageCount.bind(this)); | 41 | this.actions.service.setUnreadMessageCount.listen(this._setUnreadMessageCount.bind(this)); |
41 | this.actions.service.openWindow.listen(this._openWindow.bind(this)); | 42 | this.actions.service.openWindow.listen(this._openWindow.bind(this)); |
42 | this.actions.service.filter.listen(this._filter.bind(this)); | 43 | this.actions.service.filter.listen(this._filter.bind(this)); |
@@ -58,6 +59,7 @@ export default class ServicesStore extends Store { | |||
58 | this._mapActiveServiceToServiceModelReaction.bind(this), | 59 | this._mapActiveServiceToServiceModelReaction.bind(this), |
59 | this._saveActiveService.bind(this), | 60 | this._saveActiveService.bind(this), |
60 | this._logoutReaction.bind(this), | 61 | this._logoutReaction.bind(this), |
62 | this._shareSettingsWithServiceProcess.bind(this), | ||
61 | ]); | 63 | ]); |
62 | 64 | ||
63 | // Just bind this | 65 | // Just bind this |
@@ -284,6 +286,7 @@ export default class ServicesStore extends Store { | |||
284 | if (channel === 'hello') { | 286 | if (channel === 'hello') { |
285 | this._initRecipePolling(service.id); | 287 | this._initRecipePolling(service.id); |
286 | this._initializeServiceRecipeInWebview(serviceId); | 288 | this._initializeServiceRecipeInWebview(serviceId); |
289 | this._shareSettingsWithServiceProcess(); | ||
287 | } else if (channel === 'messages') { | 290 | } else if (channel === 'messages') { |
288 | this.actions.service.setUnreadMessageCount({ | 291 | this.actions.service.setUnreadMessageCount({ |
289 | serviceId, | 292 | serviceId, |
@@ -294,7 +297,7 @@ export default class ServicesStore extends Store { | |||
294 | }); | 297 | }); |
295 | } else if (channel === 'notification') { | 298 | } else if (channel === 'notification') { |
296 | const options = args[0].options; | 299 | const options = args[0].options; |
297 | if (service.recipe.hasNotificationSound || service.isMuted) { | 300 | if (service.recipe.hasNotificationSound || service.isMuted || this.stores.settings.all.isAppMuted) { |
298 | Object.assign(options, { | 301 | Object.assign(options, { |
299 | silent: true, | 302 | silent: true, |
300 | }); | 303 | }); |
@@ -330,7 +333,17 @@ export default class ServicesStore extends Store { | |||
330 | @action _sendIPCMessage({ serviceId, channel, args }) { | 333 | @action _sendIPCMessage({ serviceId, channel, args }) { |
331 | const service = this.one(serviceId); | 334 | const service = this.one(serviceId); |
332 | 335 | ||
333 | service.webview.send(channel, args); | 336 | if (service.webview) { |
337 | service.webview.send(channel, args); | ||
338 | } | ||
339 | } | ||
340 | |||
341 | @action _sendIPCMessageToAllServices({ channel, args }) { | ||
342 | this.all.forEach(s => this.actions.service.sendIPCMessage({ | ||
343 | serviceId: s.id, | ||
344 | channel, | ||
345 | args, | ||
346 | })); | ||
334 | } | 347 | } |
335 | 348 | ||
336 | @action _openWindow({ event }) { | 349 | @action _openWindow({ event }) { |
@@ -457,8 +470,10 @@ export default class ServicesStore extends Store { | |||
457 | const service = this.active; | 470 | const service = this.active; |
458 | 471 | ||
459 | if (service) { | 472 | if (service) { |
460 | this.stores.settings.updateSettingsRequest.execute({ | 473 | this.actions.settings.update({ |
461 | activeService: service.id, | 474 | settings: { |
475 | activeService: service.id, | ||
476 | }, | ||
462 | }); | 477 | }); |
463 | } | 478 | } |
464 | } | 479 | } |
@@ -473,19 +488,26 @@ export default class ServicesStore extends Store { | |||
473 | } | 488 | } |
474 | 489 | ||
475 | _getUnreadMessageCountReaction() { | 490 | _getUnreadMessageCountReaction() { |
476 | const unreadDirectMessageCount = this.enabled | 491 | const showMessageBadgeWhenMuted = this.stores.settings.all.showMessageBadgeWhenMuted; |
492 | const showMessageBadgesEvenWhenMuted = this.stores.ui.showMessageBadgesEvenWhenMuted; | ||
493 | |||
494 | const unreadDirectMessageCount = this.allDisplayed | ||
495 | .filter(s => (showMessageBadgeWhenMuted || s.isNotificationEnabled) && showMessageBadgesEvenWhenMuted && s.isBadgeEnabled) | ||
477 | .map(s => s.unreadDirectMessageCount) | 496 | .map(s => s.unreadDirectMessageCount) |
478 | .reduce((a, b) => a + b, 0); | 497 | .reduce((a, b) => a + b, 0); |
479 | 498 | ||
480 | const unreadIndirectMessageCount = this.enabled | 499 | const unreadIndirectMessageCount = this.allDisplayed |
481 | .filter(s => s.isIndirectMessageBadgeEnabled) | 500 | .filter(s => (showMessageBadgeWhenMuted || s.isIndirectMessageBadgeEnabled) && showMessageBadgesEvenWhenMuted && s.isBadgeEnabled) |
482 | .map(s => s.unreadIndirectMessageCount) | 501 | .map(s => s.unreadIndirectMessageCount) |
483 | .reduce((a, b) => a + b, 0); | 502 | .reduce((a, b) => a + b, 0); |
484 | 503 | ||
485 | this.actions.app.setBadge({ | 504 | // We can't just block this earlier, otherwise the mobx reaction won't be aware of the vars to watch in some cases |
486 | unreadDirectMessageCount, | 505 | if (showMessageBadgesEvenWhenMuted) { |
487 | unreadIndirectMessageCount, | 506 | this.actions.app.setBadge({ |
488 | }); | 507 | unreadDirectMessageCount, |
508 | unreadIndirectMessageCount, | ||
509 | }); | ||
510 | } | ||
489 | } | 511 | } |
490 | 512 | ||
491 | _logoutReaction() { | 513 | _logoutReaction() { |
@@ -495,6 +517,13 @@ export default class ServicesStore extends Store { | |||
495 | } | 517 | } |
496 | } | 518 | } |
497 | 519 | ||
520 | _shareSettingsWithServiceProcess() { | ||
521 | this.actions.service.sendIPCMessageToAllServices({ | ||
522 | channel: 'settings-update', | ||
523 | args: this.stores.settings.all, | ||
524 | }); | ||
525 | } | ||
526 | |||
498 | _cleanUpTeamIdAndCustomUrl(recipeId, data) { | 527 | _cleanUpTeamIdAndCustomUrl(recipeId, data) { |
499 | const serviceData = data; | 528 | const serviceData = data; |
500 | const recipe = this.stores.recipes.one(recipeId); | 529 | const recipe = this.stores.recipes.one(recipeId); |
@@ -527,6 +556,8 @@ export default class ServicesStore extends Store { | |||
527 | 556 | ||
528 | if (service) { | 557 | if (service) { |
529 | const loop = () => { | 558 | const loop = () => { |
559 | if (!service.webview) return; | ||
560 | |||
530 | service.webview.send('poll'); | 561 | service.webview.send('poll'); |
531 | 562 | ||
532 | setTimeout(loop, delay); | 563 | setTimeout(loop, delay); |
diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index 331df5c15..da99a720f 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js | |||
@@ -1,11 +1,11 @@ | |||
1 | import { ipcRenderer } from 'electron'; | 1 | import { ipcRenderer } from 'electron'; |
2 | import { action, computed, observable } from 'mobx'; | 2 | import { action, computed, observable, extendObservable } from 'mobx'; |
3 | 3 | ||
4 | import Store from './lib/Store'; | 4 | import Store from './lib/Store'; |
5 | import Request from './lib/Request'; | 5 | import Request from './lib/Request'; |
6 | import CachedRequest from './lib/CachedRequest'; | 6 | import CachedRequest from './lib/CachedRequest'; |
7 | import { gaEvent } from '../lib/analytics'; | 7 | import { gaEvent } from '../lib/analytics'; |
8 | import { DEFAULT_APP_SETTINGS } from '../config'; | 8 | import SettingsModel from '../models/Settings'; |
9 | 9 | ||
10 | export default class SettingsStore extends Store { | 10 | export default class SettingsStore extends Store { |
11 | @observable allSettingsRequest = new CachedRequest(this.api.local, 'getSettings'); | 11 | @observable allSettingsRequest = new CachedRequest(this.api.local, 'getSettings'); |
@@ -18,10 +18,6 @@ export default class SettingsStore extends Store { | |||
18 | // Register action handlers | 18 | // Register action handlers |
19 | this.actions.settings.update.listen(this._update.bind(this)); | 19 | this.actions.settings.update.listen(this._update.bind(this)); |
20 | this.actions.settings.remove.listen(this._remove.bind(this)); | 20 | this.actions.settings.remove.listen(this._remove.bind(this)); |
21 | |||
22 | // this.registerReactions([ | ||
23 | // this._shareSettingsWithMainProcess.bind(this), | ||
24 | // ]); | ||
25 | } | 21 | } |
26 | 22 | ||
27 | setup() { | 23 | setup() { |
@@ -30,14 +26,18 @@ export default class SettingsStore extends Store { | |||
30 | } | 26 | } |
31 | 27 | ||
32 | @computed get all() { | 28 | @computed get all() { |
33 | return observable(Object.assign(DEFAULT_APP_SETTINGS, this.allSettingsRequest.result)); | 29 | return new SettingsModel(this.allSettingsRequest.result); |
34 | } | 30 | } |
35 | 31 | ||
36 | @action async _update({ settings }) { | 32 | @action async _update({ settings }) { |
37 | await this.updateSettingsRequest.execute(settings)._promise; | 33 | await this.updateSettingsRequest.execute(settings)._promise; |
38 | await this.allSettingsRequest.invalidate({ immediately: true }); | 34 | await this.allSettingsRequest.patch((result) => { |
35 | if (!result) return; | ||
36 | extendObservable(result, settings); | ||
37 | }); | ||
39 | 38 | ||
40 | this._shareSettingsWithMainProcess(); | 39 | // We need a little hack to wait until everything is patched |
40 | setTimeout(() => this._shareSettingsWithMainProcess(), 0); | ||
41 | 41 | ||
42 | gaEvent('Settings', 'update'); | 42 | gaEvent('Settings', 'update'); |
43 | } | 43 | } |
diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js index cb45b88b5..5e9cc9ba7 100644 --- a/src/stores/UIStore.js +++ b/src/stores/UIStore.js | |||
@@ -1,4 +1,4 @@ | |||
1 | import { action, observable } from 'mobx'; | 1 | import { action, observable, computed } from 'mobx'; |
2 | 2 | ||
3 | import Store from './lib/Store'; | 3 | import Store from './lib/Store'; |
4 | 4 | ||
@@ -14,6 +14,12 @@ export default class UIStore extends Store { | |||
14 | this.actions.ui.toggleServiceUpdatedInfoBar.listen(this._toggleServiceUpdatedInfoBar.bind(this)); | 14 | this.actions.ui.toggleServiceUpdatedInfoBar.listen(this._toggleServiceUpdatedInfoBar.bind(this)); |
15 | } | 15 | } |
16 | 16 | ||
17 | @computed get showMessageBadgesEvenWhenMuted() { | ||
18 | const settings = this.stores.settings.all; | ||
19 | |||
20 | return (settings.isAppMuted && settings.showMessageBadgeWhenMuted) || !settings.isAppMuted; | ||
21 | } | ||
22 | |||
17 | // Actions | 23 | // Actions |
18 | @action _openSettings({ path = '/settings' }) { | 24 | @action _openSettings({ path = '/settings' }) { |
19 | const settingsPath = path !== '/settings' ? `/settings/${path}` : path; | 25 | const settingsPath = path !== '/settings' ? `/settings/${path}` : path; |
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js index 1cb2ecac3..09000dcdb 100644 --- a/src/stores/UserStore.js +++ b/src/stores/UserStore.js | |||
@@ -26,6 +26,7 @@ export default class UserStore extends Store { | |||
26 | @observable getUserInfoRequest = new CachedRequest(this.api.user, 'getInfo'); | 26 | @observable getUserInfoRequest = new CachedRequest(this.api.user, 'getInfo'); |
27 | @observable updateUserInfoRequest = new Request(this.api.user, 'updateInfo'); | 27 | @observable updateUserInfoRequest = new Request(this.api.user, 'updateInfo'); |
28 | @observable getLegacyServicesRequest = new CachedRequest(this.api.user, 'getLegacyServices'); | 28 | @observable getLegacyServicesRequest = new CachedRequest(this.api.user, 'getLegacyServices'); |
29 | @observable deleteAccountRequest = new CachedRequest(this.api.user, 'delete'); | ||
29 | 30 | ||
30 | @observable isImportLegacyServicesExecuting = false; | 31 | @observable isImportLegacyServicesExecuting = false; |
31 | @observable isImportLegacyServicesCompleted = false; | 32 | @observable isImportLegacyServicesCompleted = false; |
@@ -57,6 +58,7 @@ export default class UserStore extends Store { | |||
57 | this.actions.user.update.listen(this._update.bind(this)); | 58 | this.actions.user.update.listen(this._update.bind(this)); |
58 | this.actions.user.resetStatus.listen(this._resetStatus.bind(this)); | 59 | this.actions.user.resetStatus.listen(this._resetStatus.bind(this)); |
59 | this.actions.user.importLegacyServices.listen(this._importLegacyServices.bind(this)); | 60 | this.actions.user.importLegacyServices.listen(this._importLegacyServices.bind(this)); |
61 | this.actions.user.delete.listen(this._delete.bind(this)); | ||
60 | 62 | ||
61 | // Reactions | 63 | // Reactions |
62 | this.registerReactions([ | 64 | this.registerReactions([ |
@@ -212,6 +214,10 @@ export default class UserStore extends Store { | |||
212 | this.isImportLegacyServicesCompleted = true; | 214 | this.isImportLegacyServicesCompleted = true; |
213 | } | 215 | } |
214 | 216 | ||
217 | @action async _delete() { | ||
218 | this.deleteAccountRequest.execute(); | ||
219 | } | ||
220 | |||
215 | // This is a mobx autorun which forces the user to login if not authenticated | 221 | // This is a mobx autorun which forces the user to login if not authenticated |
216 | _requireAuthenticatedUser = () => { | 222 | _requireAuthenticatedUser = () => { |
217 | if (this.isTokenExpired) { | 223 | if (this.isTokenExpired) { |