aboutsummaryrefslogtreecommitdiffstats
path: root/src/stores
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2018-12-02 15:08:07 +0100
committerLibravatar Stefan Malzner <stefan@adlk.io>2018-12-02 15:08:07 +0100
commita5aa5e1380a0847eb33be3315d164fb9e0e23255 (patch)
treea1ea4b0f635cabb54d9cf028809d2f079727b9a1 /src/stores
parentAdd instruction to install Franz with homebrew (#1134) (diff)
parentMerge branch 'develop' into release/5.0.0-beta.19 (diff)
downloadferdium-app-a5aa5e1380a0847eb33be3315d164fb9e0e23255.tar.gz
ferdium-app-a5aa5e1380a0847eb33be3315d164fb9e0e23255.tar.zst
ferdium-app-a5aa5e1380a0847eb33be3315d164fb9e0e23255.zip
Merge branch 'release/5.0.0-beta.19'
Diffstat (limited to 'src/stores')
-rw-r--r--src/stores/AppStore.js53
-rw-r--r--src/stores/DictionaryStore.js45
-rw-r--r--src/stores/FeaturesStore.js50
-rw-r--r--src/stores/RecipesStore.js2
-rw-r--r--src/stores/RequestStore.js2
-rw-r--r--src/stores/ServicesStore.js41
-rw-r--r--src/stores/SettingsStore.js116
-rw-r--r--src/stores/UIStore.js12
-rw-r--r--src/stores/UserStore.js10
-rw-r--r--src/stores/index.js4
10 files changed, 276 insertions, 59 deletions
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js
index 38edff1b4..6f156a96d 100644
--- a/src/stores/AppStore.js
+++ b/src/stores/AppStore.js
@@ -12,12 +12,14 @@ import { CHECK_INTERVAL, DEFAULT_APP_SETTINGS } from '../config';
12import { isMac, isLinux, isWindows } from '../environment'; 12import { isMac, isLinux, isWindows } from '../environment';
13import locales from '../i18n/translations'; 13import locales from '../i18n/translations';
14import { gaEvent } from '../lib/analytics'; 14import { gaEvent } from '../lib/analytics';
15import { onVisibilityChange } from '../helpers/visibility-helper';
16import { getLocale } from '../helpers/i18n-helpers';
15 17
16import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '../helpers/service-helpers.js'; 18import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '../helpers/service-helpers.js';
17 19
18const debug = require('debug')('AppStore'); 20const debug = require('debug')('Franz:AppStore');
19 21
20const { app } = remote; 22const { app, systemPreferences } = remote;
21 23
22const mainWindow = remote.getCurrentWindow(); 24const mainWindow = remote.getCurrentWindow();
23 25
@@ -50,10 +52,16 @@ export default class AppStore extends Store {
50 52
51 @observable isSystemMuteOverridden = false; 53 @observable isSystemMuteOverridden = false;
52 54
55 @observable isSystemDarkModeEnabled = false;
56
53 @observable isClearingAllCache = false; 57 @observable isClearingAllCache = false;
54 58
55 @observable isFullScreen = mainWindow.isFullScreen(); 59 @observable isFullScreen = mainWindow.isFullScreen();
56 60
61 @observable isFocused = true;
62
63 dictionaries = [];
64
57 constructor(...args) { 65 constructor(...args) {
58 super(...args); 66 super(...args);
59 67
@@ -77,7 +85,7 @@ export default class AppStore extends Store {
77 ]); 85 ]);
78 } 86 }
79 87
80 setup() { 88 async setup() {
81 this._appStartsCounter(); 89 this._appStartsCounter();
82 // Focus the active service 90 // Focus the active service
83 window.addEventListener('focus', this.actions.service.focusActiveService); 91 window.addEventListener('focus', this.actions.service.focusActiveService);
@@ -159,6 +167,14 @@ export default class AppStore extends Store {
159 this.locale = this._getDefaultLocale(); 167 this.locale = this._getDefaultLocale();
160 168
161 this._healthCheck(); 169 this._healthCheck();
170
171 this.isSystemDarkModeEnabled = systemPreferences.isDarkMode();
172
173 onVisibilityChange((isVisible) => {
174 this.isFocused = isVisible;
175
176 debug('Window is visible/focused', isVisible);
177 });
162 } 178 }
163 179
164 @computed get cacheSize() { 180 @computed get cacheSize() {
@@ -304,31 +320,12 @@ export default class AppStore extends Store {
304 } 320 }
305 321
306 _getDefaultLocale() { 322 _getDefaultLocale() {
307 let locale = app.getLocale(); 323 return getLocale({
308 if (locales[locale] === undefined) { 324 locale: app.getLocale(),
309 let localeFuzzy; 325 locales,
310 Object.keys(locales).forEach((localStr) => { 326 defaultLocale,
311 if (locales && Object.hasOwnProperty.call(locales, localStr)) { 327 fallbackLocale: DEFAULT_APP_SETTINGS.fallbackLocale,
312 if (locale.substring(0, 2) === localStr.substring(0, 2)) { 328 });
313 localeFuzzy = localStr;
314 }
315 }
316 });
317
318 if (localeFuzzy !== undefined) {
319 locale = localeFuzzy;
320 }
321 }
322
323 if (locales[locale] === undefined) {
324 locale = defaultLocale;
325 }
326
327 if (!locale) {
328 locale = DEFAULT_APP_SETTINGS.fallbackLocale;
329 }
330
331 return locale;
332 } 329 }
333 330
334 _muteAppHandler() { 331 _muteAppHandler() {
diff --git a/src/stores/DictionaryStore.js b/src/stores/DictionaryStore.js
new file mode 100644
index 000000000..b9c5f2abf
--- /dev/null
+++ b/src/stores/DictionaryStore.js
@@ -0,0 +1,45 @@
1import { observable } from 'mobx';
2import { createDownloader } from 'hunspell-dict-downloader';
3
4import Store from './lib/Store';
5
6import { DICTIONARY_PATH } from '../config';
7
8const debug = require('debug')('Franz:DictionaryStore');
9
10export default class DictionaryStore extends Store {
11 @observable available = []
12 @observable installed = []
13
14 _dictDownloader = null
15
16 constructor(...args) {
17 super(...args);
18
19 this.registerReactions([
20 this._downloadDictForUserLocale.bind(this),
21 ]);
22 }
23
24 async setup() {
25 this._dictDownloader = await createDownloader(DICTIONARY_PATH);
26 debug('dicts', this._dictDownloader);
27
28 this.available = this._dictDownloader.availableDictionaries;
29 this.installed = this._dictDownloader.installedDictionaries;
30
31 if (!this.installed.includes('en-us')) {
32 this._dictDownloader.installDictionary('en-us');
33 }
34 }
35
36 _downloadDictForUserLocale() {
37 const spellcheckerLanguage = this.stores.settings.app.spellcheckerLanguage;
38
39 debug('trying to Downloading dict for', spellcheckerLanguage);
40 if (!this.installed.includes(spellcheckerLanguage) && this.available.includes(spellcheckerLanguage) && spellcheckerLanguage !== 'en-us') {
41 debug('Downloading dict for', spellcheckerLanguage);
42 this._dictDownloader.installDictionary(spellcheckerLanguage);
43 }
44 }
45}
diff --git a/src/stores/FeaturesStore.js b/src/stores/FeaturesStore.js
new file mode 100644
index 000000000..10c893d3f
--- /dev/null
+++ b/src/stores/FeaturesStore.js
@@ -0,0 +1,50 @@
1import { computed, observable } from 'mobx';
2
3import Store from './lib/Store';
4import CachedRequest from './lib/CachedRequest';
5
6import delayApp from '../features/delayApp';
7import spellchecker from '../features/spellchecker';
8import serviceProxy from '../features/serviceProxy';
9
10import { DEFAULT_FEATURES_CONFIG } from '../config';
11
12export default class FeaturesStore extends Store {
13 @observable defaultFeaturesRequest = new CachedRequest(this.api.features, 'default');
14 @observable featuresRequest = new CachedRequest(this.api.features, 'features');
15
16 async setup() {
17 this.registerReactions([
18 this._monitorLoginStatus.bind(this),
19 ]);
20
21 await this.featuresRequest._promise;
22 setTimeout(this._enableFeatures.bind(this), 1);
23 }
24
25 @computed get anonymousFeatures() {
26 return this.defaultFeaturesRequest.execute().result || DEFAULT_FEATURES_CONFIG;
27 }
28
29 @computed get features() {
30 if (this.stores.user.isLoggedIn) {
31 return this.featuresRequest.execute().result || DEFAULT_FEATURES_CONFIG;
32 }
33
34 return DEFAULT_FEATURES_CONFIG;
35 }
36
37 _monitorLoginStatus() {
38 if (this.stores.user.isLoggedIn) {
39 this.featuresRequest.invalidate({ immediately: true });
40 } else {
41 this.defaultFeaturesRequest.invalidate({ immediately: true });
42 }
43 }
44
45 _enableFeatures() {
46 delayApp(this.stores, this.actions);
47 spellchecker(this.stores, this.actions);
48 serviceProxy(this.stores, this.actions);
49 }
50}
diff --git a/src/stores/RecipesStore.js b/src/stores/RecipesStore.js
index a24308f6a..f2480bc8e 100644
--- a/src/stores/RecipesStore.js
+++ b/src/stores/RecipesStore.js
@@ -5,7 +5,7 @@ import CachedRequest from './lib/CachedRequest';
5import Request from './lib/Request'; 5import Request from './lib/Request';
6import { matchRoute } from '../helpers/routing-helpers'; 6import { matchRoute } from '../helpers/routing-helpers';
7 7
8const debug = require('debug')('RecipeStore'); 8const debug = require('debug')('Franz:RecipeStore');
9 9
10export default class RecipesStore extends Store { 10export default class RecipesStore extends Store {
11 @observable allRecipesRequest = new CachedRequest(this.api.recipes, 'all'); 11 @observable allRecipesRequest = new CachedRequest(this.api.recipes, 'all');
diff --git a/src/stores/RequestStore.js b/src/stores/RequestStore.js
index 595852583..bbfe6f6df 100644
--- a/src/stores/RequestStore.js
+++ b/src/stores/RequestStore.js
@@ -2,7 +2,7 @@ import { action, computed, observable } from 'mobx';
2 2
3import Store from './lib/Store'; 3import Store from './lib/Store';
4 4
5const debug = require('debug')('RequestsStore'); 5const debug = require('debug')('Franz:RequestsStore');
6 6
7export default class RequestStore extends Store { 7export default class RequestStore extends Store {
8 @observable userInfoRequest; 8 @observable userInfoRequest;
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index ccb85421a..99b091589 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -7,7 +7,7 @@ import CachedRequest from './lib/CachedRequest';
7import { matchRoute } from '../helpers/routing-helpers'; 7import { matchRoute } from '../helpers/routing-helpers';
8import { gaEvent } from '../lib/analytics'; 8import { gaEvent } from '../lib/analytics';
9 9
10const debug = require('debug')('ServiceStore'); 10const debug = require('debug')('Franz:ServiceStore');
11 11
12export default class ServicesStore extends Store { 12export default class ServicesStore extends Store {
13 @observable allServicesRequest = new CachedRequest(this.api.services, 'all'); 13 @observable allServicesRequest = new CachedRequest(this.api.services, 'all');
@@ -67,9 +67,14 @@ export default class ServicesStore extends Store {
67 } 67 }
68 68
69 setup() { 69 setup() {
70 // Single key reactions 70 // Single key reactions for the sake of your CPU
71 reaction( 71 reaction(
72 () => this.stores.settings.all.app.enableSpellchecking, 72 () => this.stores.settings.app.enableSpellchecking,
73 () => this._shareSettingsWithServiceProcess(),
74 );
75
76 reaction(
77 () => this.stores.settings.app.spellcheckerLanguage,
73 () => this._shareSettingsWithServiceProcess(), 78 () => this._shareSettingsWithServiceProcess(),
74 ); 79 );
75 } 80 }
@@ -93,7 +98,7 @@ export default class ServicesStore extends Store {
93 return this.stores.settings.all.app.showDisabledServices ? this.all : this.enabled; 98 return this.stores.settings.all.app.showDisabledServices ? this.all : this.enabled;
94 } 99 }
95 100
96 // This is just used to avoid unnecessary rerendering of resource-heavy webviews 101 // This is just used to avoid unnecessary rerendering of resource-heavy webviews
97 @computed get allDisplayedUnordered() { 102 @computed get allDisplayedUnordered() {
98 const services = this.allServicesRequest.execute().result || []; 103 const services = this.allServicesRequest.execute().result || [];
99 return this.stores.settings.all.app.showDisabledServices ? services : services.filter(service => service.isEnabled); 104 return this.stores.settings.all.app.showDisabledServices ? services : services.filter(service => service.isEnabled);
@@ -143,6 +148,7 @@ export default class ServicesStore extends Store {
143 // Actions 148 // Actions
144 @action async _createService({ recipeId, serviceData, redirect = true }) { 149 @action async _createService({ recipeId, serviceData, redirect = true }) {
145 const data = this._cleanUpTeamIdAndCustomUrl(recipeId, serviceData); 150 const data = this._cleanUpTeamIdAndCustomUrl(recipeId, serviceData);
151
146 const response = await this.createServiceRequest.execute(recipeId, data)._promise; 152 const response = await this.createServiceRequest.execute(recipeId, data)._promise;
147 153
148 this.allServicesRequest.patch((result) => { 154 this.allServicesRequest.patch((result) => {
@@ -150,6 +156,13 @@ export default class ServicesStore extends Store {
150 result.push(response.data); 156 result.push(response.data);
151 }); 157 });
152 158
159 this.actions.settings.update({
160 type: 'proxy',
161 data: {
162 [`${response.data.id}`]: data.proxy,
163 },
164 });
165
153 this.actionStatus = response.status || []; 166 this.actionStatus = response.status || [];
154 167
155 if (redirect) { 168 if (redirect) {
@@ -214,6 +227,21 @@ export default class ServicesStore extends Store {
214 await request._promise; 227 await request._promise;
215 this.actionStatus = request.result.status; 228 this.actionStatus = request.result.status;
216 229
230 if (service.isEnabled) {
231 this._sendIPCMessage({
232 serviceId,
233 channel: 'service-settings-update',
234 args: newData,
235 });
236 }
237
238 this.actions.settings.update({
239 type: 'proxy',
240 data: {
241 [`${serviceId}`]: data.proxy,
242 },
243 });
244
217 if (redirect) { 245 if (redirect) {
218 this.stores.router.push('/settings/services'); 246 this.stores.router.push('/settings/services');
219 gaEvent('Service', 'update', service.recipe.id); 247 gaEvent('Service', 'update', service.recipe.id);
@@ -411,6 +439,8 @@ export default class ServicesStore extends Store {
411 439
412 @action _reload({ serviceId }) { 440 @action _reload({ serviceId }) {
413 const service = this.one(serviceId); 441 const service = this.one(serviceId);
442 if (!service.isEnabled) return;
443
414 service.resetMessageCount(); 444 service.resetMessageCount();
415 445
416 service.webview.loadURL(service.url); 446 service.webview.loadURL(service.url);
@@ -567,9 +597,10 @@ export default class ServicesStore extends Store {
567 } 597 }
568 598
569 _shareSettingsWithServiceProcess() { 599 _shareSettingsWithServiceProcess() {
600 const settings = this.stores.settings.app;
570 this.actions.service.sendIPCMessageToAllServices({ 601 this.actions.service.sendIPCMessageToAllServices({
571 channel: 'settings-update', 602 channel: 'settings-update',
572 args: this.stores.settings.all.app, 603 args: settings,
573 }); 604 });
574 } 605 }
575 606
diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js
index d8519c609..9ea14a911 100644
--- a/src/stores/SettingsStore.js
+++ b/src/stores/SettingsStore.js
@@ -1,54 +1,105 @@
1import { remote, ipcRenderer } from 'electron';
1import { action, computed, observable } from 'mobx'; 2import { action, computed, observable } from 'mobx';
2import localStorage from 'mobx-localstorage'; 3import localStorage from 'mobx-localstorage';
3 4
4import Store from './lib/Store'; 5import Store from './lib/Store';
5import SettingsModel from '../models/Settings';
6import Request from './lib/Request'; 6import Request from './lib/Request';
7import CachedRequest from './lib/CachedRequest'; 7import CachedRequest from './lib/CachedRequest';
8import { getLocale } from '../helpers/i18n-helpers';
8 9
9const debug = require('debug')('SettingsStore'); 10import { DEFAULT_APP_SETTINGS, FILE_SYSTEM_SETTINGS_TYPES } from '../config';
11import { SPELLCHECKER_LOCALES } from '../i18n/languages';
12
13const { systemPreferences } = remote;
14const debug = require('debug')('Franz:SettingsStore');
10 15
11export default class SettingsStore extends Store { 16export default class SettingsStore extends Store {
12 @observable appSettingsRequest = new CachedRequest(this.api.local, 'getAppSettings'); 17 @observable appSettingsRequest = new CachedRequest(this.api.local, 'getAppSettings');
13 @observable updateAppSettingsRequest = new Request(this.api.local, 'updateAppSettings'); 18 @observable updateAppSettingsRequest = new Request(this.api.local, 'updateAppSettings');
14 19
20 @observable fileSystemSettingsRequests = [];
21
22 fileSystemSettingsTypes = FILE_SYSTEM_SETTINGS_TYPES;
23 @observable _fileSystemSettingsCache = {
24 app: DEFAULT_APP_SETTINGS,
25 proxy: {},
26 };
27
15 constructor(...args) { 28 constructor(...args) {
16 super(...args); 29 super(...args);
17 30
18 // Register action handlers 31 // Register action handlers
19 this.actions.settings.update.listen(this._update.bind(this)); 32 this.actions.settings.update.listen(this._update.bind(this));
20 this.actions.settings.remove.listen(this._remove.bind(this)); 33 this.actions.settings.remove.listen(this._remove.bind(this));
34
35 this.fileSystemSettingsTypes.forEach((type) => {
36 this.fileSystemSettingsRequests[type] = new CachedRequest(this.api.local, 'getAppSettings');
37 });
38
39 ipcRenderer.on('appSettings', (event, resp) => {
40 debug('Get appSettings resolves', resp, resp.type, resp.data);
41
42 this._fileSystemSettingsCache[resp.type] = resp.data;
43 });
44
45 this.fileSystemSettingsTypes.forEach((type) => {
46 ipcRenderer.send('getAppSettings', type);
47 });
21 } 48 }
22 49
23 async setup() { 50 async setup() {
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 51 // 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; 52 await this.appSettingsRequest._promise;
26 this._migrate(); 53 await this._migrate();
54 }
55
56 @computed get app() {
57 return this._fileSystemSettingsCache.app || DEFAULT_APP_SETTINGS;
58 }
59
60 @computed get proxy() {
61 return this._fileSystemSettingsCache.proxy || {};
62 }
63
64 @computed get service() {
65 return localStorage.getItem('service') || {
66 activeService: '',
67 };
68 }
69
70 @computed get stats() {
71 return localStorage.getItem('stats') || {
72 activeService: '',
73 };
74 }
75
76 @computed get migration() {
77 return localStorage.getItem('migration') || {};
27 } 78 }
28 79
29 @computed get all() { 80 @computed get all() {
30 return new SettingsModel({ 81 return {
31 app: this.appSettingsRequest.execute().result || {}, 82 app: this.app,
32 service: localStorage.getItem('service') || {}, 83 proxy: this.proxy,
33 group: localStorage.getItem('group') || {}, 84 service: this.service,
34 stats: localStorage.getItem('stats') || {}, 85 stats: this.stats,
35 migration: localStorage.getItem('migration') || {}, 86 migration: this.migration,
36 }); 87 };
37 } 88 }
38 89
39 @action async _update({ type, data }) { 90 @action async _update({ type, data }) {
40 const appSettings = this.all; 91 const appSettings = this.all;
41 if (type !== 'app') { 92 if (!this.fileSystemSettingsTypes.includes(type)) {
42 debug('Update settings', type, data, this.all); 93 debug('Update settings', type, data, this.all);
43 localStorage.setItem(type, Object.assign(appSettings[type], data)); 94 localStorage.setItem(type, Object.assign(appSettings[type], data));
44 } else { 95 } else {
45 debug('Update settings on file system', type, data); 96 debug('Update settings on file system', type, data);
46 this.updateAppSettingsRequest.execute(data); 97 ipcRenderer.send('updateAppSettings', {
47 98 type,
48 this.appSettingsRequest.patch((result) => { 99 data,
49 if (!result) return;
50 Object.assign(result, data);
51 }); 100 });
101
102 Object.assign(this._fileSystemSettingsCache[type], data);
52 } 103 }
53 } 104 }
54 105
@@ -67,8 +118,8 @@ export default class SettingsStore extends Store {
67 } 118 }
68 119
69 // Helper 120 // Helper
70 _migrate() { 121 async _migrate() {
71 const legacySettings = localStorage.getItem('app'); 122 const legacySettings = localStorage.getItem('app') || {};
72 123
73 if (!this.all.migration['5.0.0-beta.17-settings']) { 124 if (!this.all.migration['5.0.0-beta.17-settings']) {
74 this.actions.settings.update({ 125 this.actions.settings.update({
@@ -104,5 +155,34 @@ export default class SettingsStore extends Store {
104 155
105 debug('Migrated settings to split stores'); 156 debug('Migrated settings to split stores');
106 } 157 }
158
159 // Enable dark mode once
160 if (!this.all.migration['5.0.0-beta.19-settings']) {
161 const spellcheckerLanguage = getLocale({
162 locale: this.stores.settings.app.locale,
163 locales: SPELLCHECKER_LOCALES,
164 defaultLocale: DEFAULT_APP_SETTINGS.spellcheckerLanguage,
165 fallbackLocale: DEFAULT_APP_SETTINGS.spellcheckerLanguage,
166 });
167
168 this.actions.settings.update({
169 type: 'app',
170 data: {
171 darkMode: systemPreferences.isDarkMode(),
172 spellcheckerLanguage,
173 },
174 });
175
176 this.actions.settings.update({
177 type: 'migration',
178 data: {
179 '5.0.0-beta.19-settings': true,
180 },
181 });
182 }
183 }
184
185 _getFileBasedSettings(type) {
186 ipcRenderer.send('getAppSettings', type);
107 } 187 }
108} 188}
diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js
index b391bdcae..d37ebe4c7 100644
--- a/src/stores/UIStore.js
+++ b/src/stores/UIStore.js
@@ -1,6 +1,8 @@
1import { action, observable, computed } from 'mobx'; 1import { action, observable, computed } from 'mobx';
2 2
3import Store from './lib/Store'; 3import Store from './lib/Store';
4import * as themeDefault from '../theme/default';
5import * as themeDark from '../theme/dark';
4 6
5export default class UIStore extends Store { 7export default class UIStore extends Store {
6 @observable showServicesUpdatedInfoBar = false; 8 @observable showServicesUpdatedInfoBar = false;
@@ -20,13 +22,21 @@ export default class UIStore extends Store {
20 return (settings.app.isAppMuted && settings.app.showMessageBadgeWhenMuted) || !settings.isAppMuted; 22 return (settings.app.isAppMuted && settings.app.showMessageBadgeWhenMuted) || !settings.isAppMuted;
21 } 23 }
22 24
25 @computed get theme() {
26 if (this.stores.settings.all.app.darkMode) {
27 return Object.assign({}, themeDefault, themeDark);
28 }
29
30 return themeDefault;
31 }
32
23 // Actions 33 // Actions
24 @action _openSettings({ path = '/settings' }) { 34 @action _openSettings({ path = '/settings' }) {
25 const settingsPath = path !== '/settings' ? `/settings/${path}` : path; 35 const settingsPath = path !== '/settings' ? `/settings/${path}` : path;
26 this.stores.router.push(settingsPath); 36 this.stores.router.push(settingsPath);
27 } 37 }
28 38
29 @action _closeSettings(): void { 39 @action _closeSettings() {
30 this.stores.router.push('/'); 40 this.stores.router.push('/');
31 } 41 }
32 42
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js
index 574616925..26ac2c60e 100644
--- a/src/stores/UserStore.js
+++ b/src/stores/UserStore.js
@@ -9,7 +9,7 @@ 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'); 12const debug = require('debug')('Franz:UserStore');
13 13
14// TODO: split stores into UserStore and AuthStore 14// TODO: split stores into UserStore and AuthStore
15export default class UserStore extends Store { 15export default class UserStore extends Store {
@@ -122,13 +122,13 @@ export default class UserStore extends Store {
122 } 122 }
123 123
124 @computed get data() { 124 @computed get data() {
125 this.getUserInfoRequest.execute(); 125 if (!this.isLoggedIn) return {};
126 return this.getUserInfoRequest.result || {}; 126
127 return this.getUserInfoRequest.execute().result || {};
127 } 128 }
128 129
129 @computed get legacyServices() { 130 @computed get legacyServices() {
130 this.getLegacyServicesRequest.execute(); 131 return this.getLegacyServicesRequest.execute() || {};
131 return this.getLegacyServicesRequest.result || [];
132 } 132 }
133 133
134 // Actions 134 // Actions
diff --git a/src/stores/index.js b/src/stores/index.js
index 2d99e3952..f547d0a7a 100644
--- a/src/stores/index.js
+++ b/src/stores/index.js
@@ -1,5 +1,6 @@
1import AppStore from './AppStore'; 1import AppStore from './AppStore';
2import UserStore from './UserStore'; 2import UserStore from './UserStore';
3import FeaturesStore from './FeaturesStore';
3import SettingsStore from './SettingsStore'; 4import SettingsStore from './SettingsStore';
4import ServicesStore from './ServicesStore'; 5import ServicesStore from './ServicesStore';
5import RecipesStore from './RecipesStore'; 6import RecipesStore from './RecipesStore';
@@ -8,6 +9,7 @@ import UIStore from './UIStore';
8import PaymentStore from './PaymentStore'; 9import PaymentStore from './PaymentStore';
9import NewsStore from './NewsStore'; 10import NewsStore from './NewsStore';
10import RequestStore from './RequestStore'; 11import RequestStore from './RequestStore';
12import DictionaryStore from './DictionaryStore';
11import GlobalErrorStore from './GlobalErrorStore'; 13import GlobalErrorStore from './GlobalErrorStore';
12 14
13export default (api, actions, router) => { 15export default (api, actions, router) => {
@@ -16,6 +18,7 @@ export default (api, actions, router) => {
16 router, 18 router,
17 app: new AppStore(stores, api, actions), 19 app: new AppStore(stores, api, actions),
18 user: new UserStore(stores, api, actions), 20 user: new UserStore(stores, api, actions),
21 features: new FeaturesStore(stores, api, actions),
19 settings: new SettingsStore(stores, api, actions), 22 settings: new SettingsStore(stores, api, actions),
20 services: new ServicesStore(stores, api, actions), 23 services: new ServicesStore(stores, api, actions),
21 recipes: new RecipesStore(stores, api, actions), 24 recipes: new RecipesStore(stores, api, actions),
@@ -24,6 +27,7 @@ export default (api, actions, router) => {
24 payment: new PaymentStore(stores, api, actions), 27 payment: new PaymentStore(stores, api, actions),
25 news: new NewsStore(stores, api, actions), 28 news: new NewsStore(stores, api, actions),
26 requests: new RequestStore(stores, api, actions), 29 requests: new RequestStore(stores, api, actions),
30 dictionary: new DictionaryStore(stores, api, actions),
27 globalError: new GlobalErrorStore(stores, api, actions), 31 globalError: new GlobalErrorStore(stores, api, actions),
28 }); 32 });
29 // Initialize all stores 33 // Initialize all stores