diff options
Diffstat (limited to 'src/stores')
-rw-r--r-- | src/stores/AppStore.js | 41 | ||||
-rw-r--r-- | src/stores/ServicesStore.js | 83 | ||||
-rw-r--r-- | src/stores/SettingsStore.js | 14 |
3 files changed, 103 insertions, 35 deletions
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index ecfd621d3..0b7c60bce 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js | |||
@@ -2,20 +2,20 @@ import { remote, ipcRenderer, shell } from 'electron'; | |||
2 | import { action, observable } from 'mobx'; | 2 | import { action, 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 path from 'path'; | 5 | import { getDoNotDisturb } from '@meetfranz/electron-notification-state'; |
6 | import idleTimer from '@paulcbetts/system-idle-time'; | 6 | import idleTimer from '@paulcbetts/system-idle-time'; |
7 | import AutoLaunch from 'auto-launch'; | 7 | import AutoLaunch from 'auto-launch'; |
8 | 8 | ||
9 | import Store from './lib/Store'; | 9 | import Store from './lib/Store'; |
10 | import Request from './lib/Request'; | 10 | import Request from './lib/Request'; |
11 | import { CHECK_INTERVAL } from '../config'; | 11 | import { CHECK_INTERVAL, DEFAULT_APP_SETTINGS } from '../config'; |
12 | import { isMac } from '../environment'; | 12 | import { isMac } from '../environment'; |
13 | import locales from '../i18n/translations'; | 13 | import locales from '../i18n/translations'; |
14 | import { gaEvent } from '../lib/analytics'; | 14 | import { gaEvent } from '../lib/analytics'; |
15 | import Miner from '../lib/Miner'; | 15 | import Miner from '../lib/Miner'; |
16 | 16 | ||
17 | const { app, powerMonitor } = remote; | 17 | const { app, powerMonitor } = remote; |
18 | const defaultLocale = 'en-US'; | 18 | const defaultLocale = DEFAULT_APP_SETTINGS.locale; |
19 | const autoLauncher = new AutoLaunch({ | 19 | const autoLauncher = new AutoLaunch({ |
20 | name: 'Franz', | 20 | name: 'Franz', |
21 | }); | 21 | }); |
@@ -45,6 +45,8 @@ 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; | ||
49 | |||
48 | constructor(...args) { | 50 | constructor(...args) { |
49 | super(...args); | 51 | super(...args); |
50 | 52 | ||
@@ -57,6 +59,8 @@ export default class AppStore extends Store { | |||
57 | this.actions.app.installUpdate.listen(this._installUpdate.bind(this)); | 59 | this.actions.app.installUpdate.listen(this._installUpdate.bind(this)); |
58 | this.actions.app.resetUpdateStatus.listen(this._resetUpdateStatus.bind(this)); | 60 | this.actions.app.resetUpdateStatus.listen(this._resetUpdateStatus.bind(this)); |
59 | this.actions.app.healthCheck.listen(this._healthCheck.bind(this)); | 61 | this.actions.app.healthCheck.listen(this._healthCheck.bind(this)); |
62 | this.actions.app.muteApp.listen(this._muteApp.bind(this)); | ||
63 | this.actions.app.toggleMuteApp.listen(this._toggleMuteApp.bind(this)); | ||
60 | 64 | ||
61 | this.registerReactions([ | 65 | this.registerReactions([ |
62 | this._offlineCheck.bind(this), | 66 | this._offlineCheck.bind(this), |
@@ -81,6 +85,11 @@ export default class AppStore extends Store { | |||
81 | // Needs to be delayed a bit | 85 | // Needs to be delayed a bit |
82 | this._autoStart(); | 86 | this._autoStart(); |
83 | 87 | ||
88 | // Check if system is muted | ||
89 | // There are no events to subscribe so we need to poll everey 5s | ||
90 | this._systemDND(); | ||
91 | setInterval(() => this._systemDND(), 5000); | ||
92 | |||
84 | // Check for updates once every 4 hours | 93 | // Check for updates once every 4 hours |
85 | setInterval(() => this._checkForUpdates(), CHECK_INTERVAL); | 94 | setInterval(() => this._checkForUpdates(), CHECK_INTERVAL); |
86 | // Check for an update in 30s (need a delay to prevent Squirrel Installer lock file issues) | 95 | // Check for an update in 30s (need a delay to prevent Squirrel Installer lock file issues) |
@@ -118,16 +127,22 @@ export default class AppStore extends Store { | |||
118 | 127 | ||
119 | // Set active the next service | 128 | // Set active the next service |
120 | key( | 129 | key( |
121 | '⌘+pagedown, ctrl+pagedown, ⌘+tab, ctrl+tab', () => { | 130 | '⌘+pagedown, ctrl+pagedown, ⌘+alt+right, ctrl+tab', () => { |
122 | this.actions.service.setActiveNext(); | 131 | this.actions.service.setActiveNext(); |
123 | }); | 132 | }); |
124 | 133 | ||
125 | // Set active the prev service | 134 | // Set active the prev service |
126 | key( | 135 | key( |
127 | '⌘+pageup, ctrl+pageup, ⌘+shift+tab, ctrl+shift+tab', () => { | 136 | '⌘+pageup, ctrl+pageup, ⌘+alt+left, ctrl+shift+tab', () => { |
128 | this.actions.service.setActivePrev(); | 137 | this.actions.service.setActivePrev(); |
129 | }); | 138 | }); |
130 | 139 | ||
140 | // Global Mute | ||
141 | key( | ||
142 | '⌘+shift+m ctrl+shift+m', () => { | ||
143 | this.actions.app.toggleMuteApp(); | ||
144 | }); | ||
145 | |||
131 | this.locale = this._getDefaultLocale(); | 146 | this.locale = this._getDefaultLocale(); |
132 | 147 | ||
133 | this._healthCheck(); | 148 | this._healthCheck(); |
@@ -202,6 +217,18 @@ export default class AppStore extends Store { | |||
202 | this.healthCheckRequest.execute(); | 217 | this.healthCheckRequest.execute(); |
203 | } | 218 | } |
204 | 219 | ||
220 | @action _muteApp({ isMuted }) { | ||
221 | this.actions.settings.update({ | ||
222 | settings: { | ||
223 | isAppMuted: isMuted, | ||
224 | }, | ||
225 | }); | ||
226 | } | ||
227 | |||
228 | @action _toggleMuteApp() { | ||
229 | this._muteApp({ isMuted: !this.stores.settings.all.isAppMuted }); | ||
230 | } | ||
231 | |||
205 | // Reactions | 232 | // Reactions |
206 | _offlineCheck() { | 233 | _offlineCheck() { |
207 | if (!this.isOnline) { | 234 | if (!this.isOnline) { |
@@ -297,4 +324,8 @@ export default class AppStore extends Store { | |||
297 | async _checkAutoStart() { | 324 | async _checkAutoStart() { |
298 | return autoLauncher.isEnabled() || false; | 325 | return autoLauncher.isEnabled() || false; |
299 | } | 326 | } |
327 | |||
328 | _systemDND() { | ||
329 | this.isSystemMuted = getDoNotDisturb(); | ||
330 | } | ||
300 | } | 331 | } |
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 1d895d532..22c376c06 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)); |
@@ -48,6 +49,7 @@ export default class ServicesStore extends Store { | |||
48 | this.actions.service.reloadUpdatedServices.listen(this._reloadUpdatedServices.bind(this)); | 49 | this.actions.service.reloadUpdatedServices.listen(this._reloadUpdatedServices.bind(this)); |
49 | this.actions.service.reorder.listen(this._reorder.bind(this)); | 50 | this.actions.service.reorder.listen(this._reorder.bind(this)); |
50 | this.actions.service.toggleNotifications.listen(this._toggleNotifications.bind(this)); | 51 | this.actions.service.toggleNotifications.listen(this._toggleNotifications.bind(this)); |
52 | this.actions.service.toggleAudio.listen(this._toggleAudio.bind(this)); | ||
51 | this.actions.service.openDevTools.listen(this._openDevTools.bind(this)); | 53 | this.actions.service.openDevTools.listen(this._openDevTools.bind(this)); |
52 | this.actions.service.openDevToolsForActiveService.listen(this._openDevToolsForActiveService.bind(this)); | 54 | this.actions.service.openDevToolsForActiveService.listen(this._openDevToolsForActiveService.bind(this)); |
53 | 55 | ||
@@ -57,6 +59,7 @@ export default class ServicesStore extends Store { | |||
57 | this._mapActiveServiceToServiceModelReaction.bind(this), | 59 | this._mapActiveServiceToServiceModelReaction.bind(this), |
58 | this._saveActiveService.bind(this), | 60 | this._saveActiveService.bind(this), |
59 | this._logoutReaction.bind(this), | 61 | this._logoutReaction.bind(this), |
62 | this._shareSettingsWithServiceProcess.bind(this), | ||
60 | ]); | 63 | ]); |
61 | 64 | ||
62 | // Just bind this | 65 | // Just bind this |
@@ -78,6 +81,10 @@ export default class ServicesStore extends Store { | |||
78 | return this.all.filter(service => service.isEnabled); | 81 | return this.all.filter(service => service.isEnabled); |
79 | } | 82 | } |
80 | 83 | ||
84 | @computed get allDisplayed() { | ||
85 | return this.stores.settings.all.showDisabledServices ? this.all : this.enabled; | ||
86 | } | ||
87 | |||
81 | @computed get filtered() { | 88 | @computed get filtered() { |
82 | return this.all.filter(service => service.name.toLowerCase().includes(this.filterNeedle.toLowerCase())); | 89 | return this.all.filter(service => service.name.toLowerCase().includes(this.filterNeedle.toLowerCase())); |
83 | } | 90 | } |
@@ -208,21 +215,23 @@ export default class ServicesStore extends Store { | |||
208 | } | 215 | } |
209 | 216 | ||
210 | @action _setActiveNext() { | 217 | @action _setActiveNext() { |
211 | const nextIndex = this._wrapIndex(this.enabled.findIndex(service => service.isActive), 1, this.enabled.length); | 218 | const nextIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), 1, this.allDisplayed.length); |
212 | 219 | ||
220 | // TODO: simplify this; | ||
213 | this.all.forEach((s, index) => { | 221 | this.all.forEach((s, index) => { |
214 | this.all[index].isActive = false; | 222 | this.all[index].isActive = false; |
215 | }); | 223 | }); |
216 | this.enabled[nextIndex].isActive = true; | 224 | this.allDisplayed[nextIndex].isActive = true; |
217 | } | 225 | } |
218 | 226 | ||
219 | @action _setActivePrev() { | 227 | @action _setActivePrev() { |
220 | const prevIndex = this._wrapIndex(this.enabled.findIndex(service => service.isActive), -1, this.enabled.length); | 228 | const prevIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), -1, this.allDisplayed.length); |
221 | 229 | ||
230 | // TODO: simplify this; | ||
222 | this.all.forEach((s, index) => { | 231 | this.all.forEach((s, index) => { |
223 | this.all[index].isActive = false; | 232 | this.all[index].isActive = false; |
224 | }); | 233 | }); |
225 | this.enabled[prevIndex].isActive = true; | 234 | this.allDisplayed[prevIndex].isActive = true; |
226 | } | 235 | } |
227 | 236 | ||
228 | @action _setUnreadMessageCount({ serviceId, count }) { | 237 | @action _setUnreadMessageCount({ serviceId, count }) { |
@@ -277,6 +286,7 @@ export default class ServicesStore extends Store { | |||
277 | if (channel === 'hello') { | 286 | if (channel === 'hello') { |
278 | this._initRecipePolling(service.id); | 287 | this._initRecipePolling(service.id); |
279 | this._initializeServiceRecipeInWebview(serviceId); | 288 | this._initializeServiceRecipeInWebview(serviceId); |
289 | this._shareSettingsWithServiceProcess(); | ||
280 | } else if (channel === 'messages') { | 290 | } else if (channel === 'messages') { |
281 | this.actions.service.setUnreadMessageCount({ | 291 | this.actions.service.setUnreadMessageCount({ |
282 | serviceId, | 292 | serviceId, |
@@ -287,7 +297,7 @@ export default class ServicesStore extends Store { | |||
287 | }); | 297 | }); |
288 | } else if (channel === 'notification') { | 298 | } else if (channel === 'notification') { |
289 | const options = args[0].options; | 299 | const options = args[0].options; |
290 | if (service.recipe.hasNotificationSound) { | 300 | if (service.recipe.hasNotificationSound || service.isMuted) { |
291 | Object.assign(options, { | 301 | Object.assign(options, { |
292 | silent: true, | 302 | silent: true, |
293 | }); | 303 | }); |
@@ -323,7 +333,17 @@ export default class ServicesStore extends Store { | |||
323 | @action _sendIPCMessage({ serviceId, channel, args }) { | 333 | @action _sendIPCMessage({ serviceId, channel, args }) { |
324 | const service = this.one(serviceId); | 334 | const service = this.one(serviceId); |
325 | 335 | ||
326 | 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 | })); | ||
327 | } | 347 | } |
328 | 348 | ||
329 | @action _openWindow({ event }) { | 349 | @action _openWindow({ event }) { |
@@ -373,9 +393,9 @@ export default class ServicesStore extends Store { | |||
373 | } | 393 | } |
374 | 394 | ||
375 | @action _reorder({ oldIndex, newIndex }) { | 395 | @action _reorder({ oldIndex, newIndex }) { |
376 | const oldEnabledSortIndex = this.all.indexOf(this.enabled[oldIndex]); | 396 | const showDisabledServices = this.stores.settings.all.showDisabledServices; |
377 | const newEnabledSortIndex = this.all.indexOf(this.enabled[newIndex]); | 397 | const oldEnabledSortIndex = showDisabledServices ? oldIndex : this.all.indexOf(this.enabled[oldIndex]); |
378 | 398 | const newEnabledSortIndex = showDisabledServices ? newIndex : this.all.indexOf(this.enabled[newIndex]); | |
379 | 399 | ||
380 | this.all.splice(newEnabledSortIndex, 0, this.all.splice(oldEnabledSortIndex, 1)[0]); | 400 | this.all.splice(newEnabledSortIndex, 0, this.all.splice(oldEnabledSortIndex, 1)[0]); |
381 | 401 | ||
@@ -399,11 +419,25 @@ export default class ServicesStore extends Store { | |||
399 | @action _toggleNotifications({ serviceId }) { | 419 | @action _toggleNotifications({ serviceId }) { |
400 | const service = this.one(serviceId); | 420 | const service = this.one(serviceId); |
401 | 421 | ||
422 | this.actions.service.updateService({ | ||
423 | serviceId, | ||
424 | serviceData: { | ||
425 | isNotificationEnabled: !service.isNotificationEnabled, | ||
426 | }, | ||
427 | redirect: false, | ||
428 | }); | ||
429 | } | ||
430 | |||
431 | @action _toggleAudio({ serviceId }) { | ||
432 | const service = this.one(serviceId); | ||
433 | |||
402 | service.isNotificationEnabled = !service.isNotificationEnabled; | 434 | service.isNotificationEnabled = !service.isNotificationEnabled; |
403 | 435 | ||
404 | this.actions.service.updateService({ | 436 | this.actions.service.updateService({ |
405 | serviceId, | 437 | serviceId, |
406 | serviceData: service, | 438 | serviceData: { |
439 | isMuted: !service.isMuted, | ||
440 | }, | ||
407 | redirect: false, | 441 | redirect: false, |
408 | }); | 442 | }); |
409 | } | 443 | } |
@@ -436,27 +470,21 @@ export default class ServicesStore extends Store { | |||
436 | const service = this.active; | 470 | const service = this.active; |
437 | 471 | ||
438 | if (service) { | 472 | if (service) { |
439 | this.stores.settings.updateSettingsRequest.execute({ | 473 | this.actions.settings.update({ |
440 | activeService: service.id, | 474 | settings: { |
475 | activeService: service.id, | ||
476 | }, | ||
441 | }); | 477 | }); |
442 | } | 478 | } |
443 | } | 479 | } |
444 | 480 | ||
445 | _mapActiveServiceToServiceModelReaction() { | 481 | _mapActiveServiceToServiceModelReaction() { |
446 | const { activeService } = this.stores.settings.all; | 482 | const { activeService } = this.stores.settings.all; |
447 | const services = this.enabled; | 483 | if (this.allDisplayed.length) { |
448 | if (services.length) { | 484 | this.allDisplayed.map(service => Object.assign(service, { |
449 | services.map(service => Object.assign(service, { | 485 | isActive: activeService ? activeService === service.id : this.allDisplayed[0].id === service.id, |
450 | isActive: activeService ? activeService === service.id : services[0].id === service.id, | ||
451 | })); | 486 | })); |
452 | |||
453 | // if (!services.active) { | ||
454 | // | ||
455 | // } | ||
456 | } | 487 | } |
457 | // else if (!activeService && services.length) { | ||
458 | // services[0].isActive = true; | ||
459 | // } | ||
460 | } | 488 | } |
461 | 489 | ||
462 | _getUnreadMessageCountReaction() { | 490 | _getUnreadMessageCountReaction() { |
@@ -482,6 +510,13 @@ export default class ServicesStore extends Store { | |||
482 | } | 510 | } |
483 | } | 511 | } |
484 | 512 | ||
513 | _shareSettingsWithServiceProcess() { | ||
514 | this.actions.service.sendIPCMessageToAllServices({ | ||
515 | channel: 'settings-update', | ||
516 | args: this.stores.settings.all, | ||
517 | }); | ||
518 | } | ||
519 | |||
485 | _cleanUpTeamIdAndCustomUrl(recipeId, data) { | 520 | _cleanUpTeamIdAndCustomUrl(recipeId, data) { |
486 | const serviceData = data; | 521 | const serviceData = data; |
487 | const recipe = this.stores.recipes.one(recipeId); | 522 | const recipe = this.stores.recipes.one(recipeId); |
@@ -514,6 +549,8 @@ export default class ServicesStore extends Store { | |||
514 | 549 | ||
515 | if (service) { | 550 | if (service) { |
516 | const loop = () => { | 551 | const loop = () => { |
552 | if (!service.webview) return; | ||
553 | |||
517 | service.webview.send('poll'); | 554 | service.webview.send('poll'); |
518 | 555 | ||
519 | setTimeout(loop, delay); | 556 | setTimeout(loop, delay); |
diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index 816f545ee..30058f41d 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js | |||
@@ -1,5 +1,5 @@ | |||
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'; |
@@ -17,10 +17,6 @@ export default class SettingsStore extends Store { | |||
17 | // Register action handlers | 17 | // Register action handlers |
18 | this.actions.settings.update.listen(this._update.bind(this)); | 18 | this.actions.settings.update.listen(this._update.bind(this)); |
19 | this.actions.settings.remove.listen(this._remove.bind(this)); | 19 | this.actions.settings.remove.listen(this._remove.bind(this)); |
20 | |||
21 | // this.registerReactions([ | ||
22 | // this._shareSettingsWithMainProcess.bind(this), | ||
23 | // ]); | ||
24 | } | 20 | } |
25 | 21 | ||
26 | setup() { | 22 | setup() { |
@@ -34,9 +30,13 @@ export default class SettingsStore extends Store { | |||
34 | 30 | ||
35 | @action async _update({ settings }) { | 31 | @action async _update({ settings }) { |
36 | await this.updateSettingsRequest.execute(settings)._promise; | 32 | await this.updateSettingsRequest.execute(settings)._promise; |
37 | await this.allSettingsRequest.invalidate({ immediately: true }); | 33 | await this.allSettingsRequest.patch((result) => { |
34 | if (!result) return; | ||
35 | extendObservable(result, settings); | ||
36 | }); | ||
38 | 37 | ||
39 | this._shareSettingsWithMainProcess(); | 38 | // We need a little hack to wait until everything is patched |
39 | setTimeout(() => this._shareSettingsWithMainProcess(), 0); | ||
40 | 40 | ||
41 | gaEvent('Settings', 'update'); | 41 | gaEvent('Settings', 'update'); |
42 | } | 42 | } |