aboutsummaryrefslogtreecommitdiffstats
path: root/src/stores
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2018-04-04 21:23:38 +0200
committerLibravatar GitHub <noreply@github.com>2018-04-04 21:23:38 +0200
commit1790b795238c2abe832285197cb88c0833bd98ca (patch)
tree89d4bc3632efc05822c0bec53a883b2d092bfd69 /src/stores
parentFix typo [ci skip] (diff)
parentMerge branch 'master' into release/5.0.0-beta.18 (diff)
downloadferdium-app-1790b795238c2abe832285197cb88c0833bd98ca.tar.gz
ferdium-app-1790b795238c2abe832285197cb88c0833bd98ca.tar.zst
ferdium-app-1790b795238c2abe832285197cb88c0833bd98ca.zip
5.0.0 beta.18v5.0.0-beta.18
Diffstat (limited to 'src/stores')
-rw-r--r--src/stores/AppStore.js37
-rw-r--r--src/stores/ServicesStore.js36
-rw-r--r--src/stores/SettingsStore.js98
-rw-r--r--src/stores/UIStore.js2
-rw-r--r--src/stores/UserStore.js24
5 files changed, 151 insertions, 46 deletions
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js
index 4ac8325d4..38edff1b4 100644
--- a/src/stores/AppStore.js
+++ b/src/stores/AppStore.js
@@ -15,8 +15,12 @@ import { gaEvent } from '../lib/analytics';
15 15
16import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '../helpers/service-helpers.js'; 16import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '../helpers/service-helpers.js';
17 17
18const debug = require('debug')('AppStore');
19
18const { app } = remote; 20const { app } = remote;
19 21
22const mainWindow = remote.getCurrentWindow();
23
20const defaultLocale = DEFAULT_APP_SETTINGS.locale; 24const defaultLocale = DEFAULT_APP_SETTINGS.locale;
21const autoLauncher = new AutoLaunch({ 25const autoLauncher = new AutoLaunch({
22 name: 'Franz', 26 name: 'Franz',
@@ -48,6 +52,8 @@ export default class AppStore extends Store {
48 52
49 @observable isClearingAllCache = false; 53 @observable isClearingAllCache = false;
50 54
55 @observable isFullScreen = mainWindow.isFullScreen();
56
51 constructor(...args) { 57 constructor(...args) {
52 super(...args); 58 super(...args);
53 59
@@ -80,6 +86,10 @@ export default class AppStore extends Store {
80 window.addEventListener('online', () => { this.isOnline = true; }); 86 window.addEventListener('online', () => { this.isOnline = true; });
81 window.addEventListener('offline', () => { this.isOnline = false; }); 87 window.addEventListener('offline', () => { this.isOnline = false; });
82 88
89 mainWindow.on('enter-full-screen', () => { this.isFullScreen = true; });
90 mainWindow.on('leave-full-screen', () => { this.isFullScreen = false; });
91
92
83 this.isOnline = navigator.onLine; 93 this.isOnline = navigator.onLine;
84 94
85 // Check if Franz should launch on start 95 // Check if Franz should launch on start
@@ -157,7 +167,7 @@ export default class AppStore extends Store {
157 167
158 // Actions 168 // Actions
159 @action _notify({ title, options, notificationId, serviceId = null }) { 169 @action _notify({ title, options, notificationId, serviceId = null }) {
160 if (this.stores.settings.all.isAppMuted) return; 170 if (this.stores.settings.all.app.isAppMuted) return;
161 171
162 const notification = new window.Notification(title, options); 172 const notification = new window.Notification(title, options);
163 notification.onclick = (e) => { 173 notification.onclick = (e) => {
@@ -170,8 +180,6 @@ export default class AppStore extends Store {
170 180
171 this.actions.service.setActive({ serviceId }); 181 this.actions.service.setActive({ serviceId });
172 182
173 const mainWindow = remote.getCurrentWindow();
174
175 if (isWindows) { 183 if (isWindows) {
176 mainWindow.restore(); 184 mainWindow.restore();
177 } else if (isLinux) { 185 } else if (isLinux) {
@@ -238,14 +246,15 @@ export default class AppStore extends Store {
238 this.isSystemMuteOverridden = overrideSystemMute; 246 this.isSystemMuteOverridden = overrideSystemMute;
239 247
240 this.actions.settings.update({ 248 this.actions.settings.update({
241 settings: { 249 type: 'app',
250 data: {
242 isAppMuted: isMuted, 251 isAppMuted: isMuted,
243 }, 252 },
244 }); 253 });
245 } 254 }
246 255
247 @action _toggleMuteApp() { 256 @action _toggleMuteApp() {
248 this._muteApp({ isMuted: !this.stores.settings.all.isAppMuted }); 257 this._muteApp({ isMuted: !this.stores.settings.all.app.isAppMuted });
249 } 258 }
250 259
251 @action async _clearAllCache() { 260 @action async _clearAllCache() {
@@ -279,13 +288,19 @@ export default class AppStore extends Store {
279 } 288 }
280 289
281 _setLocale() { 290 _setLocale() {
282 const locale = this.stores.settings.all.locale; 291 let locale;
292 if (this.stores.user.isLoggedIn) {
293 locale = this.stores.user.data.locale;
294 }
295
283 296
284 if (locale && Object.prototype.hasOwnProperty.call(locales, locale) && locale !== this.locale) { 297 if (locale && Object.prototype.hasOwnProperty.call(locales, locale) && locale !== this.locale) {
285 this.locale = locale; 298 this.locale = locale;
286 } else if (!locale) { 299 } else if (!locale) {
287 this.locale = this._getDefaultLocale(); 300 this.locale = this._getDefaultLocale();
288 } 301 }
302
303 debug(`Set locale to "${this.locale}"`);
289 } 304 }
290 305
291 _getDefaultLocale() { 306 _getDefaultLocale() {
@@ -327,8 +342,9 @@ export default class AppStore extends Store {
327 // Helpers 342 // Helpers
328 _appStartsCounter() { 343 _appStartsCounter() {
329 this.actions.settings.update({ 344 this.actions.settings.update({
330 settings: { 345 type: 'stats',
331 appStarts: (this.stores.settings.all.appStarts || 0) + 1, 346 data: {
347 appStarts: (this.stores.settings.all.stats.appStarts || 0) + 1,
332 }, 348 },
333 }); 349 });
334 } 350 }
@@ -336,7 +352,8 @@ export default class AppStore extends Store {
336 async _autoStart() { 352 async _autoStart() {
337 this.autoLaunchOnStart = await this._checkAutoStart(); 353 this.autoLaunchOnStart = await this._checkAutoStart();
338 354
339 if (this.stores.settings.all.appStarts === 1) { 355 if (this.stores.settings.all.stats.appStarts === 1) {
356 debug('Set app to launch on start');
340 this.actions.app.launchOnStartup({ 357 this.actions.app.launchOnStartup({
341 enable: true, 358 enable: true,
342 }); 359 });
@@ -349,7 +366,7 @@ export default class AppStore extends Store {
349 366
350 _systemDND() { 367 _systemDND() {
351 const dnd = getDoNotDisturb(); 368 const dnd = getDoNotDisturb();
352 if (dnd !== this.stores.settings.all.isAppMuted && !this.isSystemMuteOverridden) { 369 if (dnd !== this.stores.settings.all.app.isAppMuted && !this.isSystemMuteOverridden) {
353 this.actions.app.muteApp({ 370 this.actions.app.muteApp({
354 isMuted: dnd, 371 isMuted: dnd,
355 overrideSystemMute: false, 372 overrideSystemMute: false,
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index f7d92b1ff..ccb85421a 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -1,8 +1,5 @@
1// import { remote } from 'electron'; 1import { action, reaction, computed, observable } from 'mobx';
2import { action, computed, observable } from 'mobx';
3import { debounce, remove } from 'lodash'; 2import { debounce, remove } from 'lodash';
4// import path from 'path';
5// import fs from 'fs-extra';
6 3
7import Store from './lib/Store'; 4import Store from './lib/Store';
8import Request from './lib/Request'; 5import Request from './lib/Request';
@@ -63,13 +60,20 @@ export default class ServicesStore extends Store {
63 this._mapActiveServiceToServiceModelReaction.bind(this), 60 this._mapActiveServiceToServiceModelReaction.bind(this),
64 this._saveActiveService.bind(this), 61 this._saveActiveService.bind(this),
65 this._logoutReaction.bind(this), 62 this._logoutReaction.bind(this),
66 this._shareSettingsWithServiceProcess.bind(this),
67 ]); 63 ]);
68 64
69 // Just bind this 65 // Just bind this
70 this._initializeServiceRecipeInWebview.bind(this); 66 this._initializeServiceRecipeInWebview.bind(this);
71 } 67 }
72 68
69 setup() {
70 // Single key reactions
71 reaction(
72 () => this.stores.settings.all.app.enableSpellchecking,
73 () => this._shareSettingsWithServiceProcess(),
74 );
75 }
76
73 @computed get all() { 77 @computed get all() {
74 if (this.stores.user.isLoggedIn) { 78 if (this.stores.user.isLoggedIn) {
75 const services = this.allServicesRequest.execute().result; 79 const services = this.allServicesRequest.execute().result;
@@ -86,13 +90,13 @@ export default class ServicesStore extends Store {
86 } 90 }
87 91
88 @computed get allDisplayed() { 92 @computed get allDisplayed() {
89 return this.stores.settings.all.showDisabledServices ? this.all : this.enabled; 93 return this.stores.settings.all.app.showDisabledServices ? this.all : this.enabled;
90 } 94 }
91 95
92 // This is just used to avoid unnecessary rerendering of resource-heavy webviews 96 // This is just used to avoid unnecessary rerendering of resource-heavy webviews
93 @computed get allDisplayedUnordered() { 97 @computed get allDisplayedUnordered() {
94 const services = this.allServicesRequest.execute().result || []; 98 const services = this.allServicesRequest.execute().result || [];
95 return this.stores.settings.all.showDisabledServices ? services : services.filter(service => service.isEnabled); 99 return this.stores.settings.all.app.showDisabledServices ? services : services.filter(service => service.isEnabled);
96 } 100 }
97 101
98 @computed get filtered() { 102 @computed get filtered() {
@@ -334,7 +338,7 @@ export default class ServicesStore extends Store {
334 }); 338 });
335 } else if (channel === 'notification') { 339 } else if (channel === 'notification') {
336 const options = args[0].options; 340 const options = args[0].options;
337 if (service.recipe.hasNotificationSound || service.isMuted || this.stores.settings.all.isAppMuted) { 341 if (service.recipe.hasNotificationSound || service.isMuted || this.stores.settings.all.app.isAppMuted) {
338 Object.assign(options, { 342 Object.assign(options, {
339 silent: true, 343 silent: true,
340 }); 344 });
@@ -434,7 +438,7 @@ export default class ServicesStore extends Store {
434 } 438 }
435 439
436 @action _reorder({ oldIndex, newIndex }) { 440 @action _reorder({ oldIndex, newIndex }) {
437 const showDisabledServices = this.stores.settings.all.showDisabledServices; 441 const showDisabledServices = this.stores.settings.all.app.showDisabledServices;
438 const oldEnabledSortIndex = showDisabledServices ? oldIndex : this.all.indexOf(this.enabled[oldIndex]); 442 const oldEnabledSortIndex = showDisabledServices ? oldIndex : this.all.indexOf(this.enabled[oldIndex]);
439 const newEnabledSortIndex = showDisabledServices ? newIndex : this.all.indexOf(this.enabled[newIndex]); 443 const newEnabledSortIndex = showDisabledServices ? newIndex : this.all.indexOf(this.enabled[newIndex]);
440 444
@@ -512,7 +516,8 @@ export default class ServicesStore extends Store {
512 516
513 if (service) { 517 if (service) {
514 this.actions.settings.update({ 518 this.actions.settings.update({
515 settings: { 519 type: 'service',
520 data: {
516 activeService: service.id, 521 activeService: service.id,
517 }, 522 },
518 }); 523 });
@@ -520,7 +525,7 @@ export default class ServicesStore extends Store {
520 } 525 }
521 526
522 _mapActiveServiceToServiceModelReaction() { 527 _mapActiveServiceToServiceModelReaction() {
523 const { activeService } = this.stores.settings.all; 528 const { activeService } = this.stores.settings.all.service;
524 if (this.allDisplayed.length) { 529 if (this.allDisplayed.length) {
525 this.allDisplayed.map(service => Object.assign(service, { 530 this.allDisplayed.map(service => Object.assign(service, {
526 isActive: activeService ? activeService === service.id : this.allDisplayed[0].id === service.id, 531 isActive: activeService ? activeService === service.id : this.allDisplayed[0].id === service.id,
@@ -529,7 +534,7 @@ export default class ServicesStore extends Store {
529 } 534 }
530 535
531 _getUnreadMessageCountReaction() { 536 _getUnreadMessageCountReaction() {
532 const showMessageBadgeWhenMuted = this.stores.settings.all.showMessageBadgeWhenMuted; 537 const showMessageBadgeWhenMuted = this.stores.settings.all.app.showMessageBadgeWhenMuted;
533 const showMessageBadgesEvenWhenMuted = this.stores.ui.showMessageBadgesEvenWhenMuted; 538 const showMessageBadgesEvenWhenMuted = this.stores.ui.showMessageBadgesEvenWhenMuted;
534 539
535 const unreadDirectMessageCount = this.allDisplayed 540 const unreadDirectMessageCount = this.allDisplayed
@@ -553,7 +558,10 @@ export default class ServicesStore extends Store {
553 558
554 _logoutReaction() { 559 _logoutReaction() {
555 if (!this.stores.user.isLoggedIn) { 560 if (!this.stores.user.isLoggedIn) {
556 this.actions.settings.remove({ key: 'activeService' }); 561 this.actions.settings.remove({
562 type: 'service',
563 key: 'activeService',
564 });
557 this.allServicesRequest.invalidate().reset(); 565 this.allServicesRequest.invalidate().reset();
558 } 566 }
559 } 567 }
@@ -561,7 +569,7 @@ export default class ServicesStore extends Store {
561 _shareSettingsWithServiceProcess() { 569 _shareSettingsWithServiceProcess() {
562 this.actions.service.sendIPCMessageToAllServices({ 570 this.actions.service.sendIPCMessageToAllServices({
563 channel: 'settings-update', 571 channel: 'settings-update',
564 args: this.stores.settings.all, 572 args: this.stores.settings.all.app,
565 }); 573 });
566 } 574 }
567 575
diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js
index b7d803398..d8519c609 100644
--- a/src/stores/SettingsStore.js
+++ b/src/stores/SettingsStore.js
@@ -1,12 +1,17 @@
1import { ipcRenderer } from 'electron'; 1import { action, computed, observable } from 'mobx';
2import { action, computed } from 'mobx';
3import localStorage from 'mobx-localstorage'; 2import localStorage from 'mobx-localstorage';
4 3
5import Store from './lib/Store'; 4import Store from './lib/Store';
6import { gaEvent } from '../lib/analytics';
7import SettingsModel from '../models/Settings'; 5import SettingsModel from '../models/Settings';
6import Request from './lib/Request';
7import CachedRequest from './lib/CachedRequest';
8
9const debug = require('debug')('SettingsStore');
8 10
9export default class SettingsStore extends Store { 11export default class SettingsStore extends Store {
12 @observable appSettingsRequest = new CachedRequest(this.api.local, 'getAppSettings');
13 @observable updateAppSettingsRequest = new Request(this.api.local, 'updateAppSettings');
14
10 constructor(...args) { 15 constructor(...args) {
11 super(...args); 16 super(...args);
12 17
@@ -15,36 +20,89 @@ export default class SettingsStore extends Store {
15 this.actions.settings.remove.listen(this._remove.bind(this)); 20 this.actions.settings.remove.listen(this._remove.bind(this));
16 } 21 }
17 22
18 setup() { 23 async setup() {
19 this._shareSettingsWithMainProcess(); 24 // We need to wait until `appSettingsRequest` has been executed once, otherwise we can't patch the result. If we don't wait we'd run into an issue with mobx not reacting to changes of previously not existing keys
25 await this.appSettingsRequest._promise;
26 this._migrate();
20 } 27 }
21 28
22 @computed get all() { 29 @computed get all() {
23 return new SettingsModel(localStorage.getItem('app') || {}); 30 return new SettingsModel({
31 app: this.appSettingsRequest.execute().result || {},
32 service: localStorage.getItem('service') || {},
33 group: localStorage.getItem('group') || {},
34 stats: localStorage.getItem('stats') || {},
35 migration: localStorage.getItem('migration') || {},
36 });
24 } 37 }
25 38
26 @action async _update({ settings }) { 39 @action async _update({ type, data }) {
27 const appSettings = this.all; 40 const appSettings = this.all;
28 localStorage.setItem('app', Object.assign(appSettings, settings)); 41 if (type !== 'app') {
42 debug('Update settings', type, data, this.all);
43 localStorage.setItem(type, Object.assign(appSettings[type], data));
44 } else {
45 debug('Update settings on file system', type, data);
46 this.updateAppSettingsRequest.execute(data);
29 47
30 // We need a little hack to wait until everything is patched 48 this.appSettingsRequest.patch((result) => {
31 setTimeout(() => this._shareSettingsWithMainProcess(), 0); 49 if (!result) return;
32 50 Object.assign(result, data);
33 gaEvent('Settings', 'update'); 51 });
52 }
34 } 53 }
35 54
36 @action async _remove({ key }) { 55 @action async _remove({ type, key }) {
37 const appSettings = this.all; 56 if (type === 'app') return; // app keys can't be deleted
57
58 const appSettings = this.all[type];
38 if (Object.hasOwnProperty.call(appSettings, key)) { 59 if (Object.hasOwnProperty.call(appSettings, key)) {
39 delete appSettings[key]; 60 delete appSettings[key];
40 localStorage.setItem('app', appSettings);
41 }
42 61
43 this._shareSettingsWithMainProcess(); 62 this.actions.settings.update({
63 type,
64 data: appSettings,
65 });
66 }
44 } 67 }
45 68
46 // Reactions 69 // Helper
47 _shareSettingsWithMainProcess() { 70 _migrate() {
48 ipcRenderer.send('settings', this.all); 71 const legacySettings = localStorage.getItem('app');
72
73 if (!this.all.migration['5.0.0-beta.17-settings']) {
74 this.actions.settings.update({
75 type: 'app',
76 data: {
77 autoLaunchInBackground: legacySettings.autoLaunchInBackground,
78 runInBackground: legacySettings.runInBackground,
79 enableSystemTray: legacySettings.enableSystemTray,
80 minimizeToSystemTray: legacySettings.minimizeToSystemTray,
81 isAppMuted: legacySettings.isAppMuted,
82 enableGPUAcceleration: legacySettings.enableGPUAcceleration,
83 showMessageBadgeWhenMuted: legacySettings.showMessageBadgeWhenMuted,
84 showDisabledServices: legacySettings.showDisabledServices,
85 enableSpellchecking: legacySettings.enableSpellchecking,
86 },
87 });
88
89 this.actions.settings.update({
90 type: 'service',
91 data: {
92 activeService: legacySettings.activeService,
93 },
94 });
95
96 this.actions.settings.update({
97 type: 'migration',
98 data: {
99 '5.0.0-beta.17-settings': true,
100 },
101 });
102
103 localStorage.removeItem('app');
104
105 debug('Migrated settings to split stores');
106 }
49 } 107 }
50} 108}
diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js
index 5e9cc9ba7..b391bdcae 100644
--- a/src/stores/UIStore.js
+++ b/src/stores/UIStore.js
@@ -17,7 +17,7 @@ export default class UIStore extends Store {
17 @computed get showMessageBadgesEvenWhenMuted() { 17 @computed get showMessageBadgesEvenWhenMuted() {
18 const settings = this.stores.settings.all; 18 const settings = this.stores.settings.all;
19 19
20 return (settings.isAppMuted && settings.showMessageBadgeWhenMuted) || !settings.isAppMuted; 20 return (settings.app.isAppMuted && settings.app.showMessageBadgeWhenMuted) || !settings.isAppMuted;
21 } 21 }
22 22
23 // Actions 23 // Actions
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js
index 7dbbd955b..574616925 100644
--- a/src/stores/UserStore.js
+++ b/src/stores/UserStore.js
@@ -9,6 +9,8 @@ import Request from './lib/Request';
9import CachedRequest from './lib/CachedRequest'; 9import CachedRequest from './lib/CachedRequest';
10import { gaEvent } from '../lib/analytics'; 10import { gaEvent } from '../lib/analytics';
11 11
12const debug = require('debug')('UserStore');
13
12// TODO: split stores into UserStore and AuthStore 14// TODO: split stores into UserStore and AuthStore
13export default class UserStore extends Store { 15export default class UserStore extends Store {
14 BASE_ROUTE = '/auth'; 16 BASE_ROUTE = '/auth';
@@ -69,6 +71,11 @@ export default class UserStore extends Store {
69 ]); 71 ]);
70 } 72 }
71 73
74 setup() {
75 // Data migration
76 this._migrateUserLocale();
77 }
78
72 // Routes 79 // Routes
73 get loginRoute() { 80 get loginRoute() {
74 return this.LOGIN_ROUTE; 81 return this.LOGIN_ROUTE;
@@ -256,8 +263,10 @@ export default class UserStore extends Store {
256 263
257 // We need to set the beta flag for the SettingsStore 264 // We need to set the beta flag for the SettingsStore
258 this.actions.settings.update({ 265 this.actions.settings.update({
259 settings: { 266 type: 'app',
267 data: {
260 beta: data.beta, 268 beta: data.beta,
269 locale: data.locale,
261 }, 270 },
262 }); 271 });
263 } 272 }
@@ -292,4 +301,17 @@ export default class UserStore extends Store {
292 this.id = null; 301 this.id = null;
293 } 302 }
294 } 303 }
304
305 async _migrateUserLocale() {
306 await this.getUserInfoRequest._promise;
307
308 if (!this.data.locale) {
309 debug('Migrate "locale" to user data');
310 this.actions.user.update({
311 userData: {
312 locale: this.stores.app.locale,
313 },
314 });
315 }
316 }
295} 317}