aboutsummaryrefslogtreecommitdiffstats
path: root/src/stores
diff options
context:
space:
mode:
Diffstat (limited to 'src/stores')
-rw-r--r--src/stores/AppStore.js24
-rw-r--r--src/stores/FeaturesStore.js2
-rw-r--r--src/stores/GlobalErrorStore.js5
-rw-r--r--src/stores/PaymentStore.js3
-rw-r--r--src/stores/RecipePreviewsStore.js10
-rw-r--r--src/stores/RecipesStore.js2
-rw-r--r--src/stores/RequestStore.js2
-rw-r--r--src/stores/ServicesStore.js90
-rw-r--r--src/stores/SettingsStore.js52
-rw-r--r--src/stores/UserStore.js39
10 files changed, 141 insertions, 88 deletions
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js
index 0398b7533..40d98cf42 100644
--- a/src/stores/AppStore.js
+++ b/src/stores/AppStore.js
@@ -1,6 +1,6 @@
1import { remote, ipcRenderer, shell } from 'electron'; 1import { remote, ipcRenderer, shell } from 'electron';
2import { 2import {
3 action, computed, observable, reaction, 3 action, computed, observable,
4} from 'mobx'; 4} from 'mobx';
5import moment from 'moment'; 5import moment from 'moment';
6import { getDoNotDisturb } from '@meetfranz/electron-notification-state'; 6import { getDoNotDisturb } from '@meetfranz/electron-notification-state';
@@ -17,7 +17,6 @@ import Request from './lib/Request';
17import { CHECK_INTERVAL, DEFAULT_APP_SETTINGS } from '../config'; 17import { CHECK_INTERVAL, DEFAULT_APP_SETTINGS } from '../config';
18import { isMac } from '../environment'; 18import { isMac } from '../environment';
19import locales from '../i18n/translations'; 19import locales from '../i18n/translations';
20import { gaEvent, gaPage, statsEvent } from '../lib/analytics';
21import { onVisibilityChange } from '../helpers/visibility-helper'; 20import { onVisibilityChange } from '../helpers/visibility-helper';
22import { getLocale } from '../helpers/i18n-helpers'; 21import { getLocale } from '../helpers/i18n-helpers';
23 22
@@ -25,7 +24,7 @@ import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '..
25import { isValidExternalURL } from '../helpers/url-helpers'; 24import { isValidExternalURL } from '../helpers/url-helpers';
26import { sleep } from '../helpers/async-helpers'; 25import { sleep } from '../helpers/async-helpers';
27 26
28const debug = require('debug')('Franz:AppStore'); 27const debug = require('debug')('Ferdi:AppStore');
29 28
30const { app, systemPreferences, screen } = remote; 29const { app, systemPreferences, screen } = remote;
31 30
@@ -33,7 +32,7 @@ const mainWindow = remote.getCurrentWindow();
33 32
34const defaultLocale = DEFAULT_APP_SETTINGS.locale; 33const defaultLocale = DEFAULT_APP_SETTINGS.locale;
35const autoLauncher = new AutoLaunch({ 34const autoLauncher = new AutoLaunch({
36 name: 'Franz', 35 name: 'Ferdi',
37}); 36});
38 37
39export default class AppStore extends Store { 38export default class AppStore extends Store {
@@ -55,6 +54,8 @@ export default class AppStore extends Store {
55 54
56 @observable isOnline = navigator.onLine; 55 @observable isOnline = navigator.onLine;
57 56
57 @observable authRequestFailed = false;
58
58 @observable timeOfflineStart; 59 @observable timeOfflineStart;
59 60
60 @observable updateStatus = null; 61 @observable updateStatus = null;
@@ -114,7 +115,7 @@ export default class AppStore extends Store {
114 115
115 this.isOnline = navigator.onLine; 116 this.isOnline = navigator.onLine;
116 117
117 // Check if Franz should launch on start 118 // Check if Ferdi should launch on start
118 // Needs to be delayed a bit 119 // Needs to be delayed a bit
119 this._autoStart(); 120 this._autoStart();
120 121
@@ -174,13 +175,6 @@ export default class AppStore extends Store {
174 175
175 debug('Window is visible/focused', isVisible); 176 debug('Window is visible/focused', isVisible);
176 }); 177 });
177
178 // analytics autorun
179 reaction(() => this.stores.router.location.pathname, (pathname) => {
180 gaPage(pathname);
181 });
182
183 statsEvent('app-start');
184 } 178 }
185 179
186 @computed get cacheSize() { 180 @computed get cacheSize() {
@@ -268,8 +262,6 @@ export default class AppStore extends Store {
268 } catch (err) { 262 } catch (err) {
269 console.warn(err); 263 console.warn(err);
270 } 264 }
271
272 gaEvent('App', enable ? 'enable autostart' : 'disable autostart');
273 } 265 }
274 266
275 @action _openExternalUrl({ url }) { 267 @action _openExternalUrl({ url }) {
@@ -279,8 +271,6 @@ export default class AppStore extends Store {
279 if (isValidExternalURL(url)) { 271 if (isValidExternalURL(url)) {
280 shell.openExternal(url); 272 shell.openExternal(url);
281 } 273 }
282
283 gaEvent('External URL', 'open', parsedUrl.host);
284 } 274 }
285 275
286 @action _checkForUpdates() { 276 @action _checkForUpdates() {
@@ -376,7 +366,7 @@ export default class AppStore extends Store {
376 } 366 }
377 367
378 _muteAppHandler() { 368 _muteAppHandler() {
379 const showMessageBadgesEvenWhenMuted = this.stores.ui.showMessageBadgesEvenWhenMuted; 369 const { showMessageBadgesEvenWhenMuted } = this.stores.ui;
380 370
381 if (!showMessageBadgesEvenWhenMuted) { 371 if (!showMessageBadgesEvenWhenMuted) {
382 this.actions.app.setBadge({ unreadDirectMessageCount: 0, unreadIndirectMessageCount: 0 }); 372 this.actions.app.setBadge({ unreadDirectMessageCount: 0, unreadIndirectMessageCount: 0 });
diff --git a/src/stores/FeaturesStore.js b/src/stores/FeaturesStore.js
index cf28b6bec..c39b6d7f3 100644
--- a/src/stores/FeaturesStore.js
+++ b/src/stores/FeaturesStore.js
@@ -13,6 +13,7 @@ import spellchecker from '../features/spellchecker';
13import serviceProxy from '../features/serviceProxy'; 13import serviceProxy from '../features/serviceProxy';
14import basicAuth from '../features/basicAuth'; 14import basicAuth from '../features/basicAuth';
15import workspaces from '../features/workspaces'; 15import workspaces from '../features/workspaces';
16import quickSwitch from '../features/quickSwitch';
16import shareFranz from '../features/shareFranz'; 17import shareFranz from '../features/shareFranz';
17import announcements from '../features/announcements'; 18import announcements from '../features/announcements';
18import settingsWS from '../features/settingsWS'; 19import settingsWS from '../features/settingsWS';
@@ -75,6 +76,7 @@ export default class FeaturesStore extends Store {
75 serviceProxy(this.stores, this.actions); 76 serviceProxy(this.stores, this.actions);
76 basicAuth(this.stores, this.actions); 77 basicAuth(this.stores, this.actions);
77 workspaces(this.stores, this.actions); 78 workspaces(this.stores, this.actions);
79 quickSwitch(this.stores, this.actions);
78 shareFranz(this.stores, this.actions); 80 shareFranz(this.stores, this.actions);
79 announcements(this.stores, this.actions); 81 announcements(this.stores, this.actions);
80 settingsWS(this.stores, this.actions); 82 settingsWS(this.stores, this.actions);
diff --git a/src/stores/GlobalErrorStore.js b/src/stores/GlobalErrorStore.js
index 7a85c2daa..8bdafb68c 100644
--- a/src/stores/GlobalErrorStore.js
+++ b/src/stores/GlobalErrorStore.js
@@ -24,9 +24,12 @@ export default class GlobalErrorStore extends Store {
24 this.response = {}; 24 this.response = {};
25 } 25 }
26 if (this.error.status === 401) { 26 if (this.error.status === 401) {
27 this.actions.user.logout({ serverLogout: true }); 27 window.ferdi.stores.app.authRequestFailed = true;
28 // this.actions.user.logout({ serverLogout: true });
28 } 29 }
29 } 30 }
31 } else {
32 window.ferdi.stores.app.authRequestFailed = false;
30 } 33 }
31 }); 34 });
32} 35}
diff --git a/src/stores/PaymentStore.js b/src/stores/PaymentStore.js
index d4de476c8..8579812ad 100644
--- a/src/stores/PaymentStore.js
+++ b/src/stores/PaymentStore.js
@@ -3,7 +3,6 @@ import { action, observable, computed } from 'mobx';
3import Store from './lib/Store'; 3import Store from './lib/Store';
4import CachedRequest from './lib/CachedRequest'; 4import CachedRequest from './lib/CachedRequest';
5import Request from './lib/Request'; 5import Request from './lib/Request';
6import { gaEvent } from '../lib/analytics';
7 6
8export default class PaymentStore extends Store { 7export default class PaymentStore extends Store {
9 @observable plansRequest = new CachedRequest(this.api.payment, 'plans'); 8 @observable plansRequest = new CachedRequest(this.api.payment, 'plans');
@@ -26,8 +25,6 @@ export default class PaymentStore extends Store {
26 @action _createHostedPage({ planId }) { 25 @action _createHostedPage({ planId }) {
27 const request = this.createHostedPageRequest.execute(planId); 26 const request = this.createHostedPageRequest.execute(planId);
28 27
29 gaEvent('Payment', 'createHostedPage', planId);
30
31 return request; 28 return request;
32 } 29 }
33} 30}
diff --git a/src/stores/RecipePreviewsStore.js b/src/stores/RecipePreviewsStore.js
index 382820d58..989e1124a 100644
--- a/src/stores/RecipePreviewsStore.js
+++ b/src/stores/RecipePreviewsStore.js
@@ -1,11 +1,8 @@
1import { action, computed, observable } from 'mobx'; 1import { action, computed, observable } from 'mobx';
2import { debounce } from 'lodash';
3import ms from 'ms';
4 2
5import Store from './lib/Store'; 3import Store from './lib/Store';
6import CachedRequest from './lib/CachedRequest'; 4import CachedRequest from './lib/CachedRequest';
7import Request from './lib/Request'; 5import Request from './lib/Request';
8import { gaEvent } from '../lib/analytics';
9 6
10export default class RecipePreviewsStore extends Store { 7export default class RecipePreviewsStore extends Store {
11 @observable allRecipePreviewsRequest = new CachedRequest(this.api.recipePreviews, 'all'); 8 @observable allRecipePreviewsRequest = new CachedRequest(this.api.recipePreviews, 'all');
@@ -41,13 +38,6 @@ export default class RecipePreviewsStore extends Store {
41 @action _search({ needle }) { 38 @action _search({ needle }) {
42 if (needle !== '') { 39 if (needle !== '') {
43 this.searchRecipePreviewsRequest.execute(needle); 40 this.searchRecipePreviewsRequest.execute(needle);
44
45 this._analyticsSearch(needle);
46 } 41 }
47 } 42 }
48
49 // Helper
50 _analyticsSearch = debounce((needle) => {
51 gaEvent('Recipe', 'search', needle);
52 }, ms('3s'));
53} 43}
diff --git a/src/stores/RecipesStore.js b/src/stores/RecipesStore.js
index d51192078..7f91049df 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')('Franz:RecipeStore'); 8const debug = require('debug')('Ferdi: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 9254e3223..2587d4eef 100644
--- a/src/stores/RequestStore.js
+++ b/src/stores/RequestStore.js
@@ -3,7 +3,7 @@ import ms from 'ms';
3 3
4import Store from './lib/Store'; 4import Store from './lib/Store';
5 5
6const debug = require('debug')('Franz:RequestsStore'); 6const debug = require('debug')('Ferdi:RequestsStore');
7 7
8export default class RequestStore extends Store { 8export default class RequestStore extends Store {
9 @observable userInfoRequest; 9 @observable userInfoRequest;
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index 70b775503..076ecc204 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -4,19 +4,20 @@ import {
4 computed, 4 computed,
5 observable, 5 observable,
6} from 'mobx'; 6} from 'mobx';
7import { debounce, remove } from 'lodash'; 7import { remove } from 'lodash';
8import ms from 'ms'; 8import ms from 'ms';
9 9
10import Store from './lib/Store'; 10import Store from './lib/Store';
11import Request from './lib/Request'; 11import Request from './lib/Request';
12import CachedRequest from './lib/CachedRequest'; 12import CachedRequest from './lib/CachedRequest';
13import { matchRoute } from '../helpers/routing-helpers'; 13import { matchRoute } from '../helpers/routing-helpers';
14import { gaEvent, statsEvent } from '../lib/analytics'; 14import { isInTimeframe } from '../helpers/schedule-helpers';
15import { workspaceStore } from '../features/workspaces'; 15import { workspaceStore } from '../features/workspaces';
16import { serviceLimitStore } from '../features/serviceLimit'; 16import { serviceLimitStore } from '../features/serviceLimit';
17import { RESTRICTION_TYPES } from '../models/Service'; 17import { RESTRICTION_TYPES } from '../models/Service';
18import { KEEP_WS_LOADED_USID } from '../config';
18 19
19const debug = require('debug')('Franz:ServiceStore'); 20const debug = require('debug')('Ferdi:ServiceStore');
20 21
21export default class ServicesStore extends Store { 22export default class ServicesStore extends Store {
22 @observable allServicesRequest = new CachedRequest(this.api.services, 'all'); 23 @observable allServicesRequest = new CachedRequest(this.api.services, 'all');
@@ -95,6 +96,11 @@ export default class ServicesStore extends Store {
95 () => this.stores.settings.app.spellcheckerLanguage, 96 () => this.stores.settings.app.spellcheckerLanguage,
96 () => this._shareSettingsWithServiceProcess(), 97 () => this._shareSettingsWithServiceProcess(),
97 ); 98 );
99
100 reaction(
101 () => this.stores.settings.app.darkMode,
102 () => this._shareSettingsWithServiceProcess(),
103 );
98 } 104 }
99 105
100 @computed get all() { 106 @computed get all() {
@@ -125,7 +131,35 @@ export default class ServicesStore extends Store {
125 const { keepAllWorkspacesLoaded } = this.stores.workspaces.settings; 131 const { keepAllWorkspacesLoaded } = this.stores.workspaces.settings;
126 const services = this.allServicesRequest.execute().result || []; 132 const services = this.allServicesRequest.execute().result || [];
127 const filteredServices = showDisabledServices ? services : services.filter(service => service.isEnabled); 133 const filteredServices = showDisabledServices ? services : services.filter(service => service.isEnabled);
128 return keepAllWorkspacesLoaded ? filteredServices : workspaceStore.filterServicesByActiveWorkspace(filteredServices); 134
135 let displayedServices;
136 if (keepAllWorkspacesLoaded) {
137 // Keep all enabled services loaded
138 displayedServices = filteredServices;
139 } else {
140 // Keep all services in current workspace loaded
141 displayedServices = workspaceStore.filterServicesByActiveWorkspace(filteredServices);
142
143 // Keep all services active in workspaces that should be kept loaded
144 for (const workspace of this.stores.workspaces.workspaces) {
145 // Check if workspace needs to be kept loaded
146 if (workspace.services.includes(KEEP_WS_LOADED_USID)) {
147 // Get services for workspace
148 const serviceIDs = workspace.services.filter(i => i !== KEEP_WS_LOADED_USID);
149 const wsServices = filteredServices.filter(service => serviceIDs.includes(service.id));
150
151 displayedServices = [
152 ...displayedServices,
153 ...wsServices,
154 ];
155 }
156 }
157
158 // Make sure every service is in the list only once
159 displayedServices = displayedServices.filter((v, i, a) => a.indexOf(v) === i);
160 }
161
162 return displayedServices;
129 } 163 }
130 164
131 @computed get filtered() { 165 @computed get filtered() {
@@ -182,7 +216,6 @@ export default class ServicesStore extends Store {
182 216
183 if (redirect) { 217 if (redirect) {
184 this.stores.router.push('/settings/recipes'); 218 this.stores.router.push('/settings/recipes');
185 gaEvent('Service', 'create', recipeId);
186 } 219 }
187 } 220 }
188 221
@@ -259,7 +292,6 @@ export default class ServicesStore extends Store {
259 292
260 if (redirect) { 293 if (redirect) {
261 this.stores.router.push('/settings/services'); 294 this.stores.router.push('/settings/services');
262 gaEvent('Service', 'update', service.recipe.id);
263 } 295 }
264 } 296 }
265 297
@@ -274,19 +306,14 @@ export default class ServicesStore extends Store {
274 remove(result, c => c.id === serviceId); 306 remove(result, c => c.id === serviceId);
275 }); 307 });
276 308
277 const service = this.one(serviceId);
278
279 await request._promise; 309 await request._promise;
280 this.actionStatus = request.result.status; 310 this.actionStatus = request.result.status;
281
282 gaEvent('Service', 'delete', service.recipe.id);
283 } 311 }
284 312
285 @action async _clearCache({ serviceId }) { 313 @action async _clearCache({ serviceId }) {
286 this.clearCacheRequest.reset(); 314 this.clearCacheRequest.reset();
287 const request = this.clearCacheRequest.execute(serviceId); 315 const request = this.clearCacheRequest.execute(serviceId);
288 await request._promise; 316 await request._promise;
289 gaEvent('Service', 'clear cache');
290 } 317 }
291 318
292 @action _setActive({ serviceId, keepActiveRoute }) { 319 @action _setActive({ serviceId, keepActiveRoute }) {
@@ -298,8 +325,6 @@ export default class ServicesStore extends Store {
298 }); 325 });
299 service.isActive = true; 326 service.isActive = true;
300 327
301 statsEvent('activate-service', service.recipe.id);
302
303 this._focusActiveService(); 328 this._focusActiveService();
304 } 329 }
305 330
@@ -403,7 +428,19 @@ export default class ServicesStore extends Store {
403 }, 428 },
404 }); 429 });
405 } else if (channel === 'notification') { 430 } else if (channel === 'notification') {
406 const options = args[0].options; 431 const { options } = args[0];
432
433 // Check if we are in scheduled Do-not-Disturb time
434 const {
435 scheduledDNDEnabled,
436 scheduledDNDStart,
437 scheduledDNDEnd,
438 } = this.stores.settings.all.app;
439
440 if (scheduledDNDEnabled && isInTimeframe(scheduledDNDStart, scheduledDNDEnd)) {
441 return;
442 }
443
407 if (service.recipe.hasNotificationSound || service.isMuted || this.stores.settings.all.app.isAppMuted) { 444 if (service.recipe.hasNotificationSound || service.isMuted || this.stores.settings.all.app.isAppMuted) {
408 Object.assign(options, { 445 Object.assign(options, {
409 silent: true, 446 silent: true,
@@ -411,8 +448,17 @@ export default class ServicesStore extends Store {
411 } 448 }
412 449
413 if (service.isNotificationEnabled) { 450 if (service.isNotificationEnabled) {
414 const title = typeof args[0].title === 'string' ? args[0].title : service.name; 451 let title = `Notification from ${service.name}`;
415 options.body = typeof options.body === 'string' ? options.body : ''; 452 if (!this.stores.settings.all.app.privateNotifications) {
453 options.body = typeof options.body === 'string' ? options.body : '';
454 title = typeof args[0].title === 'string' ? args[0].title : service.name;
455 } else {
456 // Remove message data from notification in private mode
457 options.body = '';
458 options.icon = '/assets/img/notification-badge.gif';
459 }
460
461 console.log(title, options);
416 462
417 this.actions.app.notify({ 463 this.actions.app.notify({
418 notificationId: args[0].notificationId, 464 notificationId: args[0].notificationId,
@@ -530,7 +576,7 @@ export default class ServicesStore extends Store {
530 } 576 }
531 577
532 @action _reorderService({ oldIndex, newIndex }) { 578 @action _reorderService({ oldIndex, newIndex }) {
533 const showDisabledServices = this.stores.settings.all.app.showDisabledServices; 579 const { showDisabledServices } = this.stores.settings.all.app;
534 const oldEnabledSortIndex = showDisabledServices ? oldIndex : this.all.indexOf(this.enabled[oldIndex]); 580 const oldEnabledSortIndex = showDisabledServices ? oldIndex : this.all.indexOf(this.enabled[oldIndex]);
535 const newEnabledSortIndex = showDisabledServices ? newIndex : this.all.indexOf(this.enabled[newIndex]); 581 const newEnabledSortIndex = showDisabledServices ? newIndex : this.all.indexOf(this.enabled[newIndex]);
536 582
@@ -549,8 +595,6 @@ export default class ServicesStore extends Store {
549 service.order = services[s.id]; 595 service.order = services[s.id];
550 }); 596 });
551 }); 597 });
552
553 this._reorderAnalytics();
554 } 598 }
555 599
556 @action _toggleNotifications({ serviceId }) { 600 @action _toggleNotifications({ serviceId }) {
@@ -626,8 +670,8 @@ export default class ServicesStore extends Store {
626 } 670 }
627 671
628 _getUnreadMessageCountReaction() { 672 _getUnreadMessageCountReaction() {
629 const showMessageBadgeWhenMuted = this.stores.settings.all.app.showMessageBadgeWhenMuted; 673 const { showMessageBadgeWhenMuted } = this.stores.settings.all.app;
630 const showMessageBadgesEvenWhenMuted = this.stores.ui.showMessageBadgesEvenWhenMuted; 674 const { showMessageBadgesEvenWhenMuted } = this.stores.ui;
631 675
632 const unreadDirectMessageCount = this.allDisplayed 676 const unreadDirectMessageCount = this.allDisplayed
633 .filter(s => (showMessageBadgeWhenMuted || s.isNotificationEnabled) && showMessageBadgesEvenWhenMuted && s.isBadgeEnabled) 677 .filter(s => (showMessageBadgeWhenMuted || s.isNotificationEnabled) && showMessageBadgesEvenWhenMuted && s.isBadgeEnabled)
@@ -754,10 +798,6 @@ export default class ServicesStore extends Store {
754 } 798 }
755 } 799 }
756 800
757 _reorderAnalytics = debounce(() => {
758 gaEvent('Service', 'order');
759 }, ms('5s'));
760
761 _wrapIndex(index, delta, size) { 801 _wrapIndex(index, delta, size) {
762 return (((index + delta) % size) + size) % size; 802 return (((index + delta) % size) + size) % size;
763 } 803 }
diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js
index 75bb38fe0..8c4cd47eb 100644
--- a/src/stores/SettingsStore.js
+++ b/src/stores/SettingsStore.js
@@ -1,17 +1,18 @@
1import { ipcRenderer } from 'electron'; 1import { ipcRenderer, remote } from 'electron';
2import { 2import {
3 action, computed, observable, 3 action, computed, observable, reaction,
4} from 'mobx'; 4} from 'mobx';
5import localStorage from 'mobx-localstorage'; 5import localStorage from 'mobx-localstorage';
6 6
7import Store from './lib/Store'; 7import Store from './lib/Store';
8import Request from './lib/Request'; 8import Request from './lib/Request';
9import { getLocale } from '../helpers/i18n-helpers'; 9import { getLocale } from '../helpers/i18n-helpers';
10import { API } from '../environment';
10 11
11import { DEFAULT_APP_SETTINGS, FILE_SYSTEM_SETTINGS_TYPES } from '../config'; 12import { DEFAULT_APP_SETTINGS, FILE_SYSTEM_SETTINGS_TYPES } from '../config';
12import { SPELLCHECKER_LOCALES } from '../i18n/languages'; 13import { SPELLCHECKER_LOCALES } from '../i18n/languages';
13 14
14const debug = require('debug')('Franz:SettingsStore'); 15const debug = require('debug')('Ferdi:SettingsStore');
15 16
16export default class SettingsStore extends Store { 17export default class SettingsStore extends Store {
17 @observable updateAppSettingsRequest = new Request(this.api.local, 'updateAppSettings'); 18 @observable updateAppSettingsRequest = new Request(this.api.local, 'updateAppSettings');
@@ -43,6 +44,50 @@ export default class SettingsStore extends Store {
43 44
44 async setup() { 45 async setup() {
45 await this._migrate(); 46 await this._migrate();
47
48 reaction(
49 () => this.all.app.autohideMenuBar,
50 () => remote.getCurrentWindow().setAutoHideMenuBar(
51 this.all.app.autohideMenuBar,
52 ),
53 );
54
55 reaction(
56 () => this.all.app.locked,
57 () => {
58 const { router } = window.ferdi.stores;
59
60 if (this.all.app.locked && this.all.app.lockingFeatureEnabled) {
61 // App just got locked, redirect to unlock screen
62 router.push('/auth/locked');
63 } else if (router.location.pathname.includes('/auth/locked')) {
64 // App is unlocked but user is still on locked screen
65 // Redirect to homepage
66 router.push('/');
67 }
68 },
69 );
70
71 // Make sure to lock app on launch if locking feature is enabled
72 setTimeout(() => {
73 if (this.all.app.lockingFeatureEnabled) {
74 // Disable lock first - otherwise the lock might not get activated corrently
75 this.actions.settings.update({
76 type: 'app',
77 data: {
78 locked: false,
79 },
80 });
81 setTimeout(() => {
82 this.actions.settings.update({
83 type: 'app',
84 data: {
85 locked: true,
86 },
87 });
88 }, 0);
89 }
90 }, 1000);
46 } 91 }
47 92
48 @computed get app() { 93 @computed get app() {
@@ -121,6 +166,7 @@ export default class SettingsStore extends Store {
121 runInBackground: legacySettings.runInBackground, 166 runInBackground: legacySettings.runInBackground,
122 enableSystemTray: legacySettings.enableSystemTray, 167 enableSystemTray: legacySettings.enableSystemTray,
123 minimizeToSystemTray: legacySettings.minimizeToSystemTray, 168 minimizeToSystemTray: legacySettings.minimizeToSystemTray,
169 server: API,
124 isAppMuted: legacySettings.isAppMuted, 170 isAppMuted: legacySettings.isAppMuted,
125 enableGPUAcceleration: legacySettings.enableGPUAcceleration, 171 enableGPUAcceleration: legacySettings.enableGPUAcceleration,
126 showMessageBadgeWhenMuted: legacySettings.showMessageBadgeWhenMuted, 172 showMessageBadgeWhenMuted: legacySettings.showMessageBadgeWhenMuted,
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js
index b652098f9..61b7d4adf 100644
--- a/src/stores/UserStore.js
+++ b/src/stores/UserStore.js
@@ -8,12 +8,11 @@ import { isDevMode } from '../environment';
8import Store from './lib/Store'; 8import Store from './lib/Store';
9import Request from './lib/Request'; 9import Request from './lib/Request';
10import CachedRequest from './lib/CachedRequest'; 10import CachedRequest from './lib/CachedRequest';
11import { gaEvent } from '../lib/analytics';
12import { sleep } from '../helpers/async-helpers'; 11import { sleep } from '../helpers/async-helpers';
13import { getPlan } from '../helpers/plan-helpers'; 12import { getPlan } from '../helpers/plan-helpers';
14import { PLANS } from '../config'; 13import { PLANS } from '../config';
15 14
16const debug = require('debug')('Franz:UserStore'); 15const debug = require('debug')('Ferdi:UserStore');
17 16
18// TODO: split stores into UserStore and AuthStore 17// TODO: split stores into UserStore and AuthStore
19export default class UserStore extends Store { 18export default class UserStore extends Store {
@@ -94,7 +93,7 @@ export default class UserStore extends Store {
94 93
95 // Reactions 94 // Reactions
96 this.registerReactions([ 95 this.registerReactions([
97 this._requireAuthenticatedUser, 96 // this._requireAuthenticatedUser,
98 this._getUserData.bind(this), 97 this._getUserData.bind(this),
99 this._resetTrialActivationState.bind(this), 98 this._resetTrialActivationState.bind(this),
100 ]); 99 ]);
@@ -157,7 +156,7 @@ export default class UserStore extends Store {
157 } 156 }
158 157
159 @computed get isPremium() { 158 @computed get isPremium() {
160 return !!this.data.isPremium; 159 return true;
161 } 160 }
162 161
163 @computed get isPremiumOverride() { 162 @computed get isPremiumOverride() {
@@ -172,12 +171,13 @@ export default class UserStore extends Store {
172 } 171 }
173 172
174 @computed get isPro() { 173 @computed get isPro() {
175 if (this.isPremiumOverride) return true; 174 return true;
175 // if (this.isPremiumOverride) return true;
176 176
177 if (!this.team || (!this.team.plan || this.team.state === 'expired')) return false; 177 // if (!this.team || (!this.team.plan || this.team.state === 'expired')) return false;
178 const plan = getPlan(this.team.plan); 178 // const plan = getPlan(this.team.plan);
179 179
180 return plan === PLANS.PRO || plan === PLANS.LEGACY; 180 // return plan === PLANS.PRO || plan === PLANS.LEGACY;
181 } 181 }
182 182
183 @computed get legacyServices() { 183 @computed get legacyServices() {
@@ -190,16 +190,12 @@ export default class UserStore extends Store {
190 this._setUserData(authToken); 190 this._setUserData(authToken);
191 191
192 this.stores.router.push('/'); 192 this.stores.router.push('/');
193
194 gaEvent('User', 'login');
195 } 193 }
196 194
197 @action _tokenLogin(authToken) { 195 @action _tokenLogin(authToken) {
198 this._setUserData(authToken); 196 this._setUserData(authToken);
199 197
200 this.stores.router.push('/'); 198 this.stores.router.push('/');
201
202 gaEvent('User', 'tokenLogin');
203 } 199 }
204 200
205 @action async _signup({ 201 @action async _signup({
@@ -215,13 +211,11 @@ export default class UserStore extends Store {
215 locale: this.stores.app.locale, 211 locale: this.stores.app.locale,
216 }); 212 });
217 213
218 this.hasCompletedSignup = false; 214 this.hasCompletedSignup = true;
219 215
220 this._setUserData(authToken); 216 this._setUserData(authToken);
221 217
222 this.stores.router.push(this.PRICING_ROUTE); 218 this.stores.router.push('/');
223
224 gaEvent('User', 'signup');
225 } 219 }
226 220
227 @action async _retrievePassword({ email }) { 221 @action async _retrievePassword({ email }) {
@@ -229,8 +223,6 @@ export default class UserStore extends Store {
229 223
230 await request._promise; 224 await request._promise;
231 this.actionStatus = request.result.status || []; 225 this.actionStatus = request.result.status || [];
232
233 gaEvent('User', 'retrievePassword');
234 } 226 }
235 227
236 @action async _activateTrial({ planId }) { 228 @action async _activateTrial({ planId }) {
@@ -246,9 +238,6 @@ export default class UserStore extends Store {
246 238
247 this.stores.features.featuresRequest.invalidate({ immediately: true }); 239 this.stores.features.featuresRequest.invalidate({ immediately: true });
248 this.stores.user.getUserInfoRequest.invalidate({ immediately: true }); 240 this.stores.user.getUserInfoRequest.invalidate({ immediately: true });
249
250
251 gaEvent('User', 'activateTrial');
252 } 241 }
253 242
254 @action async _invite({ invites }) { 243 @action async _invite({ invites }) {
@@ -262,8 +251,6 @@ export default class UserStore extends Store {
262 if (this.stores.router.location.pathname.includes(this.INVITE_ROUTE)) { 251 if (this.stores.router.location.pathname.includes(this.INVITE_ROUTE)) {
263 this.stores.router.push('/'); 252 this.stores.router.push('/');
264 } 253 }
265
266 gaEvent('User', 'inviteUsers');
267 } 254 }
268 255
269 @action async _update({ userData }) { 256 @action async _update({ userData }) {
@@ -273,8 +260,6 @@ export default class UserStore extends Store {
273 260
274 this.getUserInfoRequest.patch(() => response.data); 261 this.getUserInfoRequest.patch(() => response.data);
275 this.actionStatus = response.status || []; 262 this.actionStatus = response.status || [];
276
277 gaEvent('User', 'update');
278 } 263 }
279 264
280 @action _resetStatus() { 265 @action _resetStatus() {
@@ -297,12 +282,12 @@ export default class UserStore extends Store {
297 const recipes = services.filter((obj, pos, arr) => arr.map(mapObj => mapObj.recipe.id).indexOf(obj.recipe.id) === pos).map(s => s.recipe.id); 282 const recipes = services.filter((obj, pos, arr) => arr.map(mapObj => mapObj.recipe.id).indexOf(obj.recipe.id) === pos).map(s => s.recipe.id);
298 283
299 // Install recipes 284 // Install recipes
300 for (const recipe of recipes) { 285 for (const recipe of recipes) { // eslint-disable-line no-unused-vars
301 // eslint-disable-next-line 286 // eslint-disable-next-line
302 await this.stores.recipes._install({ recipeId: recipe }); 287 await this.stores.recipes._install({ recipeId: recipe });
303 } 288 }
304 289
305 for (const service of services) { 290 for (const service of services) { // eslint-disable-line no-unused-vars
306 this.actions.service.createFromLegacyService({ 291 this.actions.service.createFromLegacyService({
307 data: service, 292 data: service,
308 }); 293 });