aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package-lock.json5
-rw-r--r--package.json2
-rw-r--r--src/stores/AppStore.js62
-rw-r--r--src/stores/UserStore.js66
4 files changed, 80 insertions, 55 deletions
diff --git a/package-lock.json b/package-lock.json
index 7ae62ffd1..8f302a8fe 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11614,6 +11614,11 @@
11614 "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", 11614 "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==",
11615 "dev": true 11615 "dev": true
11616 }, 11616 },
11617 "dayjs": {
11618 "version": "1.10.6",
11619 "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.6.tgz",
11620 "integrity": "sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw=="
11621 },
11617 "dbus-next": { 11622 "dbus-next": {
11618 "version": "0.9.2", 11623 "version": "0.9.2",
11619 "resolved": "https://registry.npmjs.org/dbus-next/-/dbus-next-0.9.2.tgz", 11624 "resolved": "https://registry.npmjs.org/dbus-next/-/dbus-next-0.9.2.tgz",
diff --git a/package.json b/package.json
index 19b1c504a..7aa100668 100644
--- a/package.json
+++ b/package.json
@@ -75,6 +75,7 @@
75 "css": "2.2.4", 75 "css": "2.2.4",
76 "csstype": "3.0.8", 76 "csstype": "3.0.8",
77 "darkreader": "4.9.34", 77 "darkreader": "4.9.34",
78 "dayjs": "1.10.6",
78 "dbus-next": "0.9.2", 79 "dbus-next": "0.9.2",
79 "debug": "4.3.2", 80 "debug": "4.3.2",
80 "du": "1.0.0", 81 "du": "1.0.0",
@@ -99,7 +100,6 @@
99 "mobx-react": "5.4.2", 100 "mobx-react": "5.4.2",
100 "mobx-react-form": "1.35.1", 101 "mobx-react-form": "1.35.1",
101 "mobx-react-router": "3.1.2", 102 "mobx-react-router": "3.1.2",
102 "moment": "2.29.1",
103 "ms": "2.1.3", 103 "ms": "2.1.3",
104 "node-fetch": "2.6.1", 104 "node-fetch": "2.6.1",
105 "node-mac-permissions": "2.2.0", 105 "node-mac-permissions": "2.2.0",
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js
index 9c8cce679..71213774d 100644
--- a/src/stores/AppStore.js
+++ b/src/stores/AppStore.js
@@ -8,7 +8,7 @@ import {
8 process as remoteProcess, 8 process as remoteProcess,
9} from '@electron/remote'; 9} from '@electron/remote';
10import { action, computed, observable } from 'mobx'; 10import { action, computed, observable } from 'mobx';
11import moment from 'moment'; 11import dayjs from 'dayjs';
12import AutoLaunch from 'auto-launch'; 12import AutoLaunch from 'auto-launch';
13import ms from 'ms'; 13import ms from 'ms';
14import { URL } from 'url'; 14import { URL } from 'url';
@@ -48,7 +48,8 @@ const autoLauncher = new AutoLaunch({
48 path: executablePath, 48 path: executablePath,
49}); 49});
50 50
51const CATALINA_NOTIFICATION_HACK_KEY = '_temp_askedForCatalinaNotificationPermissions'; 51const CATALINA_NOTIFICATION_HACK_KEY =
52 '_temp_askedForCatalinaNotificationPermissions';
52 53
53export default class AppStore extends Store { 54export default class AppStore extends Store {
54 updateStatusTypes = { 55 updateStatusTypes = {
@@ -74,7 +75,7 @@ export default class AppStore extends Store {
74 75
75 @observable authRequestFailed = false; 76 @observable authRequestFailed = false;
76 77
77 @observable timeSuspensionStart = moment(); 78 @observable timeSuspensionStart = dayjs();
78 79
79 @observable timeOfflineStart; 80 @observable timeOfflineStart;
80 81
@@ -228,7 +229,7 @@ export default class AppStore extends Store {
228 powerMonitor.on('suspend', () => { 229 powerMonitor.on('suspend', () => {
229 debug('System suspended starting timer'); 230 debug('System suspended starting timer');
230 231
231 this.timeSuspensionStart = moment(); 232 this.timeSuspensionStart = dayjs();
232 }); 233 });
233 234
234 powerMonitor.on('resume', () => { 235 powerMonitor.on('resume', () => {
@@ -236,8 +237,8 @@ export default class AppStore extends Store {
236 this.actions.service.resetLastPollTimer(); 237 this.actions.service.resetLastPollTimer();
237 238
238 if ( 239 if (
239 this.timeSuspensionStart.add(10, 'm').isBefore(moment()) 240 this.timeSuspensionStart.add(10, 'm').isBefore(dayjs()) &&
240 && this.stores.settings.app.get('reloadAfterResume') 241 this.stores.settings.app.get('reloadAfterResume')
241 ) { 242 ) {
242 debug('Reloading services, user info and features'); 243 debug('Reloading services, user info and features');
243 244
@@ -283,15 +284,15 @@ export default class AppStore extends Store {
283 ferdi: { 284 ferdi: {
284 version: ferdiVersion, 285 version: ferdiVersion,
285 electron: electronVersion, 286 electron: electronVersion,
286 installedRecipes: this.stores.recipes.all.map((recipe) => ({ 287 installedRecipes: this.stores.recipes.all.map(recipe => ({
287 id: recipe.id, 288 id: recipe.id,
288 version: recipe.version, 289 version: recipe.version,
289 })), 290 })),
290 devRecipes: this.stores.recipePreviews.dev.map((recipe) => ({ 291 devRecipes: this.stores.recipePreviews.dev.map(recipe => ({
291 id: recipe.id, 292 id: recipe.id,
292 version: recipe.version, 293 version: recipe.version,
293 })), 294 })),
294 services: this.stores.services.all.map((service) => ({ 295 services: this.stores.services.all.map(service => ({
295 id: service.id, 296 id: service.id,
296 recipe: service.recipe.id, 297 recipe: service.recipe.id,
297 isAttached: service.isAttached, 298 isAttached: service.isAttached,
@@ -302,7 +303,7 @@ export default class AppStore extends Store {
302 isDarkModeEnabled: service.isDarkModeEnabled, 303 isDarkModeEnabled: service.isDarkModeEnabled,
303 })), 304 })),
304 messages: this.stores.globalError.messages, 305 messages: this.stores.globalError.messages,
305 workspaces: this.stores.workspaces.workspaces.map((workspace) => ({ 306 workspaces: this.stores.workspaces.workspaces.map(workspace => ({
306 id: workspace.id, 307 id: workspace.id,
307 services: workspace.services, 308 services: workspace.services,
308 })), 309 })),
@@ -315,9 +316,7 @@ export default class AppStore extends Store {
315 } 316 }
316 317
317 // Actions 318 // Actions
318 @action _notify({ 319 @action _notify({ title, options, notificationId, serviceId = null }) {
319 title, options, notificationId, serviceId = null,
320 }) {
321 if (this.stores.settings.all.app.isAppMuted) return; 320 if (this.stores.settings.all.app.isAppMuted) return;
322 321
323 // TODO: is there a simple way to use blobs for notifications without storing them on disk? 322 // TODO: is there a simple way to use blobs for notifications without storing them on disk?
@@ -359,8 +358,8 @@ export default class AppStore extends Store {
359 if (indicator === 0 && unreadIndirectMessageCount !== 0) { 358 if (indicator === 0 && unreadIndirectMessageCount !== 0) {
360 indicator = '•'; 359 indicator = '•';
361 } else if ( 360 } else if (
362 unreadDirectMessageCount === 0 361 unreadDirectMessageCount === 0 &&
363 && unreadIndirectMessageCount === 0 362 unreadIndirectMessageCount === 0
364 ) { 363 ) {
365 indicator = 0; 364 indicator = 0;
366 } else { 365 } else {
@@ -441,22 +440,25 @@ export default class AppStore extends Store {
441 const clearAppCache = this.clearAppCacheRequest.execute(); 440 const clearAppCache = this.clearAppCacheRequest.execute();
442 const allServiceIds = await getServiceIdsFromPartitions(); 441 const allServiceIds = await getServiceIdsFromPartitions();
443 const allOrphanedServiceIds = allServiceIds.filter( 442 const allOrphanedServiceIds = allServiceIds.filter(
444 (id) => !this.stores.services.all.find( 443 id =>
445 (s) => id.replace('service-', '') === s.id, 444 !this.stores.services.all.find(
446 ), 445 s => id.replace('service-', '') === s.id,
446 ),
447 ); 447 );
448 448
449 try { 449 try {
450 await Promise.all( 450 await Promise.all(
451 allOrphanedServiceIds.map((id) => removeServicePartitionDirectory(id)), 451 allOrphanedServiceIds.map(id => removeServicePartitionDirectory(id)),
452 ); 452 );
453 } catch (ex) { 453 } catch (ex) {
454 console.log('Error while deleting service partition directory - ', ex); 454 console.log('Error while deleting service partition directory - ', ex);
455 } 455 }
456 await Promise.all( 456 await Promise.all(
457 this.stores.services.all.map((s) => this.actions.service.clearCache({ 457 this.stores.services.all.map(s =>
458 serviceId: s.id, 458 this.actions.service.clearCache({
459 })), 459 serviceId: s.id,
460 }),
461 ),
460 ); 462 );
461 463
462 await clearAppCache._promise; 464 await clearAppCache._promise;
@@ -471,9 +473,9 @@ export default class AppStore extends Store {
471 // Reactions 473 // Reactions
472 _offlineCheck() { 474 _offlineCheck() {
473 if (!this.isOnline) { 475 if (!this.isOnline) {
474 this.timeOfflineStart = moment(); 476 this.timeOfflineStart = dayjs();
475 } else { 477 } else {
476 const deltaTime = moment().diff(this.timeOfflineStart); 478 const deltaTime = dayjs().diff(this.timeOfflineStart);
477 479
478 if (deltaTime > ms('30m')) { 480 if (deltaTime > ms('30m')) {
479 this.actions.service.reloadAll(); 481 this.actions.service.reloadAll();
@@ -488,16 +490,16 @@ export default class AppStore extends Store {
488 } 490 }
489 491
490 if ( 492 if (
491 locale 493 locale &&
492 && Object.prototype.hasOwnProperty.call(locales, locale) 494 Object.prototype.hasOwnProperty.call(locales, locale) &&
493 && locale !== this.locale 495 locale !== this.locale
494 ) { 496 ) {
495 this.locale = locale; 497 this.locale = locale;
496 } else if (!locale) { 498 } else if (!locale) {
497 this.locale = this._getDefaultLocale(); 499 this.locale = this._getDefaultLocale();
498 } 500 }
499 501
500 moment.locale(this.locale); 502 dayjs.locale(this.locale);
501 503
502 debug(`Set locale to "${this.locale}"`); 504 debug(`Set locale to "${this.locale}"`);
503 } 505 }
@@ -569,8 +571,8 @@ export default class AppStore extends Store {
569 debug('Do not disturb mode is', dnd); 571 debug('Do not disturb mode is', dnd);
570 // ipcRenderer.on('autoUpdate', (event, data) => { 572 // ipcRenderer.on('autoUpdate', (event, data) => {
571 if ( 573 if (
572 dnd !== this.stores.settings.all.app.isAppMuted 574 dnd !== this.stores.settings.all.app.isAppMuted &&
573 && !this.isSystemMuteOverridden 575 !this.isSystemMuteOverridden
574 ) { 576 ) {
575 this.actions.app.muteApp({ 577 this.actions.app.muteApp({
576 isMuted: dnd, 578 isMuted: dnd,
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js
index 2e009893a..066638613 100644
--- a/src/stores/UserStore.js
+++ b/src/stores/UserStore.js
@@ -1,5 +1,5 @@
1import { observable, computed, action } from 'mobx'; 1import { observable, computed, action } from 'mobx';
2import moment from 'moment'; 2import dayjs from 'dayjs';
3import jwt from 'jsonwebtoken'; 3import jwt from 'jsonwebtoken';
4import localStorage from 'mobx-localstorage'; 4import localStorage from 'mobx-localstorage';
5import { session } from '@electron/remote'; 5import { session } from '@electron/remote';
@@ -46,7 +46,10 @@ export default class UserStore extends Store {
46 46
47 @observable updateUserInfoRequest = new Request(this.api.user, 'updateInfo'); 47 @observable updateUserInfoRequest = new Request(this.api.user, 'updateInfo');
48 48
49 @observable getLegacyServicesRequest = new CachedRequest(this.api.user, 'getLegacyServices'); 49 @observable getLegacyServicesRequest = new CachedRequest(
50 this.api.user,
51 'getLegacyServices',
52 );
50 53
51 @observable deleteAccountRequest = new CachedRequest(this.api.user, 'delete'); 54 @observable deleteAccountRequest = new CachedRequest(this.api.user, 'delete');
52 55
@@ -81,13 +84,17 @@ export default class UserStore extends Store {
81 84
82 // Register action handlers 85 // Register action handlers
83 this.actions.user.login.listen(this._login.bind(this)); 86 this.actions.user.login.listen(this._login.bind(this));
84 this.actions.user.retrievePassword.listen(this._retrievePassword.bind(this)); 87 this.actions.user.retrievePassword.listen(
88 this._retrievePassword.bind(this),
89 );
85 this.actions.user.logout.listen(this._logout.bind(this)); 90 this.actions.user.logout.listen(this._logout.bind(this));
86 this.actions.user.signup.listen(this._signup.bind(this)); 91 this.actions.user.signup.listen(this._signup.bind(this));
87 this.actions.user.invite.listen(this._invite.bind(this)); 92 this.actions.user.invite.listen(this._invite.bind(this));
88 this.actions.user.update.listen(this._update.bind(this)); 93 this.actions.user.update.listen(this._update.bind(this));
89 this.actions.user.resetStatus.listen(this._resetStatus.bind(this)); 94 this.actions.user.resetStatus.listen(this._resetStatus.bind(this));
90 this.actions.user.importLegacyServices.listen(this._importLegacyServices.bind(this)); 95 this.actions.user.importLegacyServices.listen(
96 this._importLegacyServices.bind(this),
97 );
91 this.actions.user.delete.listen(this._delete.bind(this)); 98 this.actions.user.delete.listen(this._delete.bind(this));
92 99
93 // Reactions 100 // Reactions
@@ -144,7 +151,7 @@ export default class UserStore extends Store {
144 if (!this.authToken) return false; 151 if (!this.authToken) return false;
145 152
146 const { tokenExpiry } = this._parseToken(this.authToken); 153 const { tokenExpiry } = this._parseToken(this.authToken);
147 return this.authToken !== null && moment(tokenExpiry).isBefore(moment()); 154 return this.authToken !== null && dayjs(tokenExpiry).isBefore(dayjs());
148 } 155 }
149 156
150 @computed get data() { 157 @computed get data() {
@@ -176,7 +183,14 @@ export default class UserStore extends Store {
176 } 183 }
177 184
178 @action async _signup({ 185 @action async _signup({
179 firstname, lastname, email, password, accountType, company, plan, currency, 186 firstname,
187 lastname,
188 email,
189 password,
190 accountType,
191 company,
192 plan,
193 currency,
180 }) { 194 }) {
181 const authToken = await this.signupRequest.execute({ 195 const authToken = await this.signupRequest.execute({
182 firstname, 196 firstname,
@@ -205,7 +219,7 @@ export default class UserStore extends Store {
205 } 219 }
206 220
207 @action async _invite({ invites }) { 221 @action async _invite({ invites }) {
208 const data = invites.filter((invite) => invite.email !== ''); 222 const data = invites.filter(invite => invite.email !== '');
209 223
210 const response = await this.inviteRequest.execute(data)._promise; 224 const response = await this.inviteRequest.execute(data)._promise;
211 225
@@ -220,7 +234,8 @@ export default class UserStore extends Store {
220 @action async _update({ userData }) { 234 @action async _update({ userData }) {
221 if (!this.isLoggedIn) return; 235 if (!this.isLoggedIn) return;
222 236
223 const response = await this.updateUserInfoRequest.execute(userData)._promise; 237 const response = await this.updateUserInfoRequest.execute(userData)
238 ._promise;
224 239
225 this.getUserInfoRequest.patch(() => response.data); 240 this.getUserInfoRequest.patch(() => response.data);
226 this.actionStatus = response.status || []; 241 this.actionStatus = response.status || [];
@@ -250,15 +265,20 @@ export default class UserStore extends Store {
250 this.isImportLegacyServicesExecuting = true; 265 this.isImportLegacyServicesExecuting = true;
251 266
252 // Reduces recipe duplicates 267 // Reduces recipe duplicates
253 const recipes = services.filter((obj, pos, arr) => arr.map((mapObj) => mapObj.recipe.id).indexOf(obj.recipe.id) === pos).map((s) => s.recipe.id); 268 const recipes = services
269 .filter(
270 (obj, pos, arr) =>
271 arr.map(mapObj => mapObj.recipe.id).indexOf(obj.recipe.id) === pos,
272 )
273 .map(s => s.recipe.id);
254 274
255 // Install recipes 275 // Install recipes
256 for (const recipe of recipes) { // eslint-disable-line no-unused-vars 276 for (const recipe of recipes) {
257 // eslint-disable-next-line 277 // eslint-disable-next-line
258 await this.stores.recipes._install({ recipeId: recipe }); 278 await this.stores.recipes._install({ recipeId: recipe });
259 } 279 }
260 280
261 for (const service of services) { // eslint-disable-line no-unused-vars 281 for (const service of services) {
262 this.actions.service.createFromLegacyService({ 282 this.actions.service.createFromLegacyService({
263 data: service, 283 data: service,
264 }); 284 });
@@ -281,8 +301,7 @@ export default class UserStore extends Store {
281 301
282 const { router } = this.stores; 302 const { router } = this.stores;
283 const currentRoute = window.location.hash; 303 const currentRoute = window.location.hash;
284 if (!this.isLoggedIn 304 if (!this.isLoggedIn && currentRoute.includes('token=')) {
285 && currentRoute.includes('token=')) {
286 router.push(this.WELCOME_ROUTE); 305 router.push(this.WELCOME_ROUTE);
287 const token = currentRoute.split('=')[1]; 306 const token = currentRoute.split('=')[1];
288 307
@@ -293,17 +312,16 @@ export default class UserStore extends Store {
293 this._tokenLogin(token); 312 this._tokenLogin(token);
294 }, 1000); 313 }, 1000);
295 } 314 }
296 } else if (!this.isLoggedIn 315 } else if (!this.isLoggedIn && !currentRoute.includes(this.BASE_ROUTE)) {
297 && !currentRoute.includes(this.BASE_ROUTE)) {
298 router.push(this.WELCOME_ROUTE); 316 router.push(this.WELCOME_ROUTE);
299 } else if (this.isLoggedIn 317 } else if (this.isLoggedIn && currentRoute === this.LOGOUT_ROUTE) {
300 && currentRoute === this.LOGOUT_ROUTE) {
301 this.actions.user.logout(); 318 this.actions.user.logout();
302 router.push(this.LOGIN_ROUTE); 319 router.push(this.LOGIN_ROUTE);
303 } else if (this.isLoggedIn 320 } else if (
304 && currentRoute.includes(this.BASE_ROUTE) 321 this.isLoggedIn &&
305 && (this.hasCompletedSignup 322 currentRoute.includes(this.BASE_ROUTE) &&
306 || this.hasCompletedSignup === null)) { 323 (this.hasCompletedSignup || this.hasCompletedSignup === null)
324 ) {
307 if (!isDevMode) { 325 if (!isDevMode) {
308 this.stores.router.push('/'); 326 this.stores.router.push('/');
309 } 327 }
@@ -336,11 +354,11 @@ export default class UserStore extends Store {
336 try { 354 try {
337 const decoded = jwt.decode(authToken); 355 const decoded = jwt.decode(authToken);
338 356
339 return ({ 357 return {
340 id: decoded.userId, 358 id: decoded.userId,
341 tokenExpiry: moment.unix(decoded.exp).toISOString(), 359 tokenExpiry: dayjs.unix(decoded.exp).toISOString(),
342 authToken, 360 authToken,
343 }); 361 };
344 } catch (err) { 362 } catch (err) {
345 this._logout(); 363 this._logout();
346 return false; 364 return false;