diff options
author | vantezzen <hello@vantezzen.io> | 2020-04-17 18:07:20 +0200 |
---|---|---|
committer | vantezzen <hello@vantezzen.io> | 2020-04-17 18:07:20 +0200 |
commit | d3bea9800073f864cf407bf0c42ef7c299a91852 (patch) | |
tree | c0781876d677f51293333c18cbb637dafab203c2 /src/stores | |
parent | Merge branch 'develop' (diff) | |
parent | Prepare code (diff) | |
download | ferdium-app-d3bea9800073f864cf407bf0c42ef7c299a91852.tar.gz ferdium-app-d3bea9800073f864cf407bf0c42ef7c299a91852.tar.zst ferdium-app-d3bea9800073f864cf407bf0c42ef7c299a91852.zip |
Merge branch 'develop'v5.5.0-gm
Diffstat (limited to 'src/stores')
-rw-r--r-- | src/stores/AppStore.js | 28 | ||||
-rw-r--r-- | src/stores/ServicesStore.js | 80 | ||||
-rw-r--r-- | src/stores/SettingsStore.js | 38 | ||||
-rw-r--r-- | src/stores/UIStore.js | 23 | ||||
-rw-r--r-- | src/stores/UserStore.js | 8 |
5 files changed, 156 insertions, 21 deletions
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 593bf341e..da6055e5f 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js | |||
@@ -52,7 +52,7 @@ export default class AppStore extends Store { | |||
52 | 52 | ||
53 | @observable getAppCacheSizeRequest = new Request(this.api.local, 'getAppCacheSize'); | 53 | @observable getAppCacheSizeRequest = new Request(this.api.local, 'getAppCacheSize'); |
54 | 54 | ||
55 | @observable clearAppCacheRequest = new Request(this.api.local, 'clearAppCache'); | 55 | @observable clearAppCacheRequest = new Request(this.api.local, 'clearCache'); |
56 | 56 | ||
57 | @observable autoLaunchOnStart = true; | 57 | @observable autoLaunchOnStart = true; |
58 | 58 | ||
@@ -179,6 +179,10 @@ export default class AppStore extends Store { | |||
179 | this.stores.router.push(url); | 179 | this.stores.router.push(url); |
180 | }); | 180 | }); |
181 | 181 | ||
182 | ipcRenderer.on('muteApp', () => { | ||
183 | this._toggleMuteApp(); | ||
184 | }); | ||
185 | |||
182 | this.locale = this._getDefaultLocale(); | 186 | this.locale = this._getDefaultLocale(); |
183 | 187 | ||
184 | setTimeout(() => { | 188 | setTimeout(() => { |
@@ -214,13 +218,16 @@ export default class AppStore extends Store { | |||
214 | // macOS catalina notifications hack | 218 | // macOS catalina notifications hack |
215 | // notifications got stuck after upgrade but forcing a notification | 219 | // notifications got stuck after upgrade but forcing a notification |
216 | // via `new Notification` triggered the permission request | 220 | // via `new Notification` triggered the permission request |
217 | if (isMac && !localStorage.getItem(CATALINA_NOTIFICATION_HACK_KEY)) { | 221 | if (isMac) { |
218 | // eslint-disable-next-line no-new | 222 | if (!localStorage.getItem(CATALINA_NOTIFICATION_HACK_KEY)) { |
219 | new window.Notification('Welcome to Franz 5', { | 223 | debug('Triggering macOS Catalina notification permission trigger'); |
220 | body: 'Have a wonderful day & happy messaging.', | 224 | // eslint-disable-next-line no-new |
221 | }); | 225 | new window.Notification('Welcome to Franz 5', { |
226 | body: 'Have a wonderful day & happy messaging.', | ||
227 | }); | ||
222 | 228 | ||
223 | localStorage.setItem(CATALINA_NOTIFICATION_HACK_KEY, true); | 229 | localStorage.setItem(CATALINA_NOTIFICATION_HACK_KEY, true); |
230 | } | ||
224 | } | 231 | } |
225 | } | 232 | } |
226 | 233 | ||
@@ -374,8 +381,11 @@ export default class AppStore extends Store { | |||
374 | const allServiceIds = await getServiceIdsFromPartitions(); | 381 | const allServiceIds = await getServiceIdsFromPartitions(); |
375 | const allOrphanedServiceIds = allServiceIds.filter(id => !this.stores.services.all.find(s => id.replace('service-', '') === s.id)); | 382 | const allOrphanedServiceIds = allServiceIds.filter(id => !this.stores.services.all.find(s => id.replace('service-', '') === s.id)); |
376 | 383 | ||
377 | await Promise.all(allOrphanedServiceIds.map(id => removeServicePartitionDirectory(id))); | 384 | try { |
378 | 385 | await Promise.all(allOrphanedServiceIds.map(id => removeServicePartitionDirectory(id))); | |
386 | } catch (ex) { | ||
387 | console.log('Error while deleting service partition directory - ', ex); | ||
388 | } | ||
379 | await Promise.all(this.stores.services.all.map(s => this.actions.service.clearCache({ serviceId: s.id }))); | 389 | await Promise.all(this.stores.services.all.map(s => this.actions.service.clearCache({ serviceId: s.id }))); |
380 | 390 | ||
381 | await clearAppCache._promise; | 391 | await clearAppCache._promise; |
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 985887d2d..80c7d7e81 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js | |||
@@ -5,7 +5,7 @@ import { | |||
5 | computed, | 5 | computed, |
6 | observable, | 6 | observable, |
7 | } from 'mobx'; | 7 | } from 'mobx'; |
8 | import { remove } from 'lodash'; | 8 | import { debounce, remove } from 'lodash'; |
9 | import ms from 'ms'; | 9 | import ms from 'ms'; |
10 | import fs from 'fs-extra'; | 10 | import fs from 'fs-extra'; |
11 | import path from 'path'; | 11 | import path from 'path'; |
@@ -127,6 +127,60 @@ export default class ServicesStore extends Store { | |||
127 | ); | 127 | ); |
128 | } | 128 | } |
129 | 129 | ||
130 | initialize() { | ||
131 | super.initialize(); | ||
132 | |||
133 | // Check services to become hibernated | ||
134 | this.serviceMaintenanceTick(); | ||
135 | } | ||
136 | |||
137 | teardown() { | ||
138 | super.teardown(); | ||
139 | |||
140 | // Stop checking services for hibernation | ||
141 | this.serviceMaintenanceTick.cancel(); | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * Сheck for services to become hibernated. | ||
146 | */ | ||
147 | serviceMaintenanceTick = debounce(() => { | ||
148 | this._serviceMaintenance(); | ||
149 | this.serviceMaintenanceTick(); | ||
150 | debug('Service maintenance tick'); | ||
151 | }, ms('10s')); | ||
152 | |||
153 | /** | ||
154 | * Run various maintenance tasks on services | ||
155 | */ | ||
156 | _serviceMaintenance() { | ||
157 | this.all.forEach((service) => { | ||
158 | // Defines which services should be hibernated. | ||
159 | if (!service.isActive && (Date.now() - service.lastUsed > ms('5m'))) { | ||
160 | // If service is stale for 5 min, hibernate it. | ||
161 | this._hibernate({ serviceId: service.id }); | ||
162 | } | ||
163 | |||
164 | if (service.lastPoll && (service.lastPoll) - service.lastPollAnswer > ms('30s')) { | ||
165 | // If service did not reply for more than 30s try to reload. | ||
166 | if (!service.isActive) { | ||
167 | if (this.stores.app.isOnline && service.lostRecipeReloadAttempt < 3) { | ||
168 | service.webview.reload(); | ||
169 | service.lostRecipeReloadAttempt += 1; | ||
170 | |||
171 | service.lostRecipeConnection = false; | ||
172 | } | ||
173 | } else { | ||
174 | service.lostRecipeConnection = true; | ||
175 | } | ||
176 | } else { | ||
177 | service.lostRecipeConnection = false; | ||
178 | service.lostRecipeReloadAttempt = 0; | ||
179 | } | ||
180 | }); | ||
181 | } | ||
182 | |||
183 | // Computed props | ||
130 | @computed get all() { | 184 | @computed get all() { |
131 | if (this.stores.user.isLoggedIn) { | 185 | if (this.stores.user.isLoggedIn) { |
132 | const services = this.allServicesRequest.execute().result; | 186 | const services = this.allServicesRequest.execute().result; |
@@ -351,7 +405,17 @@ export default class ServicesStore extends Store { | |||
351 | 405 | ||
352 | // Create and open file | 406 | // Create and open file |
353 | const filePath = path.join(directory, file); | 407 | const filePath = path.join(directory, file); |
354 | await fs.ensureFile(filePath); | 408 | if (file === 'user.js') { |
409 | if (!await fs.exists(filePath)) { | ||
410 | await fs.writeFile(filePath, `module.exports = (config, Ferdi) => { | ||
411 | // Write your scripts here | ||
412 | console.log("Hello, World!", config); | ||
413 | } | ||
414 | `); | ||
415 | } | ||
416 | } else { | ||
417 | await fs.ensureFile(filePath); | ||
418 | } | ||
355 | shell.showItemInFolder(filePath); | 419 | shell.showItemInFolder(filePath); |
356 | } | 420 | } |
357 | 421 | ||
@@ -369,6 +433,7 @@ export default class ServicesStore extends Store { | |||
369 | this.all[index].isActive = false; | 433 | this.all[index].isActive = false; |
370 | }); | 434 | }); |
371 | service.isActive = true; | 435 | service.isActive = true; |
436 | service.lastUsed = Date.now(); | ||
372 | 437 | ||
373 | // Update list of last used services | 438 | // Update list of last used services |
374 | this.lastUsedServices = this.lastUsedServices.filter(id => id !== serviceId); | 439 | this.lastUsedServices = this.lastUsedServices.filter(id => id !== serviceId); |
@@ -465,10 +530,16 @@ export default class ServicesStore extends Store { | |||
465 | const service = this.one(serviceId); | 530 | const service = this.one(serviceId); |
466 | 531 | ||
467 | if (channel === 'hello') { | 532 | if (channel === 'hello') { |
533 | debug('Received hello event from', serviceId); | ||
534 | |||
468 | this._initRecipePolling(service.id); | 535 | this._initRecipePolling(service.id); |
469 | this._initializeServiceRecipeInWebview(serviceId); | 536 | this._initializeServiceRecipeInWebview(serviceId); |
470 | this._shareSettingsWithServiceProcess(); | 537 | this._shareSettingsWithServiceProcess(); |
538 | } else if (channel === 'alive') { | ||
539 | service.lastPollAnswer = Date.now(); | ||
471 | } else if (channel === 'messages') { | 540 | } else if (channel === 'messages') { |
541 | debug(`Received unread message info from '${serviceId}'`, args[0]); | ||
542 | |||
472 | this.actions.service.setUnreadMessageCount({ | 543 | this.actions.service.setUnreadMessageCount({ |
473 | serviceId, | 544 | serviceId, |
474 | count: { | 545 | count: { |
@@ -590,6 +661,7 @@ export default class ServicesStore extends Store { | |||
590 | if (!service.isEnabled) return; | 661 | if (!service.isEnabled) return; |
591 | 662 | ||
592 | service.resetMessageCount(); | 663 | service.resetMessageCount(); |
664 | service.lostRecipeConnection = false; | ||
593 | 665 | ||
594 | // service.webview.loadURL(service.url); | 666 | // service.webview.loadURL(service.url); |
595 | service.webview.reload(); | 667 | service.webview.reload(); |
@@ -699,6 +771,7 @@ export default class ServicesStore extends Store { | |||
699 | const service = this.active; | 771 | const service = this.active; |
700 | if (service) { | 772 | if (service) { |
701 | this.actions.service.focusService({ serviceId: service.id }); | 773 | this.actions.service.focusService({ serviceId: service.id }); |
774 | document.title = `Ferdi - ${service.name}`; | ||
702 | } | 775 | } |
703 | } | 776 | } |
704 | 777 | ||
@@ -766,7 +839,7 @@ export default class ServicesStore extends Store { | |||
766 | const isMuted = isAppMuted || service.isMuted; | 839 | const isMuted = isAppMuted || service.isMuted; |
767 | 840 | ||
768 | if (isAttached) { | 841 | if (isAttached) { |
769 | service.webview.setAudioMuted(isMuted); | 842 | service.webview.audioMuted = isMuted; |
770 | } | 843 | } |
771 | }); | 844 | }); |
772 | } | 845 | } |
@@ -852,6 +925,7 @@ export default class ServicesStore extends Store { | |||
852 | service.webview.send('poll'); | 925 | service.webview.send('poll'); |
853 | 926 | ||
854 | service.timer = setTimeout(loop, delay); | 927 | service.timer = setTimeout(loop, delay); |
928 | service.lastPoll = Date.now(); | ||
855 | }; | 929 | }; |
856 | 930 | ||
857 | loop(); | 931 | loop(); |
diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index 71d4e1702..227eb2145 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js | |||
@@ -110,6 +110,7 @@ export default class SettingsStore extends Store { | |||
110 | } | 110 | } |
111 | debug('Get appSettings resolves', resp.type, resp.data); | 111 | debug('Get appSettings resolves', resp.type, resp.data); |
112 | Object.assign(this._fileSystemSettingsCache[resp.type], resp.data); | 112 | Object.assign(this._fileSystemSettingsCache[resp.type], resp.data); |
113 | ipcRenderer.send('initialAppSettings', resp); | ||
113 | }); | 114 | }); |
114 | 115 | ||
115 | this.fileSystemSettingsTypes.forEach((type) => { | 116 | this.fileSystemSettingsTypes.forEach((type) => { |
@@ -263,5 +264,42 @@ export default class SettingsStore extends Store { | |||
263 | }, | 264 | }, |
264 | }); | 265 | }); |
265 | } | 266 | } |
267 | |||
268 | if (!this.all.migration['5.4.4-beta.4-settings']) { | ||
269 | this.actions.settings.update({ | ||
270 | type: 'app', | ||
271 | data: { | ||
272 | todoServer: 'isUsingCustomTodoService', | ||
273 | customTodoServer: legacySettings.todoServer, | ||
274 | }, | ||
275 | }); | ||
276 | |||
277 | this.actions.settings.update({ | ||
278 | type: 'migration', | ||
279 | data: { | ||
280 | '5.4.4-beta.4-settings': true, | ||
281 | }, | ||
282 | }); | ||
283 | |||
284 | debug('Migrated old todo setting to new custom todo setting'); | ||
285 | } | ||
286 | |||
287 | if (!this.all.migration['5.4.4-beta.4-settings']) { | ||
288 | this.actions.settings.update({ | ||
289 | type: 'app', | ||
290 | data: { | ||
291 | automaticUpdates: !(legacySettings.noUpdates), | ||
292 | }, | ||
293 | }); | ||
294 | |||
295 | this.actions.settings.update({ | ||
296 | type: 'migration', | ||
297 | data: { | ||
298 | '5.4.4-beta.4-settings': true, | ||
299 | }, | ||
300 | }); | ||
301 | |||
302 | debug('Migrated updates settings'); | ||
303 | } | ||
266 | } | 304 | } |
267 | } | 305 | } |
diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js index 6941cf086..f6e059bfb 100644 --- a/src/stores/UIStore.js +++ b/src/stores/UIStore.js | |||
@@ -5,14 +5,14 @@ import { theme } from '@meetfranz/theme'; | |||
5 | import { remote } from 'electron'; | 5 | import { remote } from 'electron'; |
6 | 6 | ||
7 | import Store from './lib/Store'; | 7 | import Store from './lib/Store'; |
8 | import { isMac } from '../environment'; | 8 | import { isMac, isWindows } from '../environment'; |
9 | 9 | ||
10 | const { nativeTheme, systemPreferences } = remote; | 10 | const { nativeTheme, systemPreferences } = remote; |
11 | 11 | ||
12 | export default class UIStore extends Store { | 12 | export default class UIStore extends Store { |
13 | @observable showServicesUpdatedInfoBar = false; | 13 | @observable showServicesUpdatedInfoBar = false; |
14 | 14 | ||
15 | @observable isOsDarkThemeActive = isMac | 15 | @observable isOsDarkThemeActive = (isMac || isWindows) |
16 | ? nativeTheme.shouldUseDarkColors | 16 | ? nativeTheme.shouldUseDarkColors |
17 | : false; | 17 | : false; |
18 | 18 | ||
@@ -36,6 +36,13 @@ export default class UIStore extends Store { | |||
36 | }, | 36 | }, |
37 | ); | 37 | ); |
38 | } | 38 | } |
39 | |||
40 | if (isWindows) { | ||
41 | nativeTheme.on('updated', () => { | ||
42 | this.isOsDarkThemeActive = nativeTheme.shouldUseDarkColors; | ||
43 | this.actions.service.shareSettingsWithServiceProcess(); | ||
44 | }); | ||
45 | } | ||
39 | } | 46 | } |
40 | 47 | ||
41 | setup() { | 48 | setup() { |
@@ -56,16 +63,16 @@ export default class UIStore extends Store { | |||
56 | } | 63 | } |
57 | 64 | ||
58 | @computed get isDarkThemeActive() { | 65 | @computed get isDarkThemeActive() { |
59 | const isMacWithAdaptableInDarkMode = isMac | 66 | const isMacOrWindowsWithAdaptableInDarkMode = (isMac || isWindows) |
60 | && this.stores.settings.all.app.adaptableDarkMode | 67 | && this.stores.settings.all.app.adaptableDarkMode |
61 | && this.isOsDarkThemeActive; | 68 | && this.isOsDarkThemeActive; |
62 | const isMacWithoutAdaptableInDarkMode = isMac | 69 | const isMacOrWindowsWithoutAdaptableInDarkMode = (isMac || isWindows) |
63 | && this.stores.settings.all.app.darkMode | 70 | && this.stores.settings.all.app.darkMode |
64 | && !this.stores.settings.all.app.adaptableDarkMode; | 71 | && !this.stores.settings.all.app.adaptableDarkMode; |
65 | const isNotMacInDarkMode = !isMac && this.stores.settings.all.app.darkMode; | 72 | const isMacOrWindowsNotInDarkMode = !(isMac || isWindows) && this.stores.settings.all.app.darkMode; |
66 | return !!(isMacWithAdaptableInDarkMode | 73 | return !!(isMacOrWindowsWithAdaptableInDarkMode |
67 | || isMacWithoutAdaptableInDarkMode | 74 | || isMacOrWindowsWithoutAdaptableInDarkMode |
68 | || isNotMacInDarkMode); | 75 | || isMacOrWindowsNotInDarkMode); |
69 | } | 76 | } |
70 | 77 | ||
71 | @computed get theme() { | 78 | @computed get theme() { |
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js index ec0b0cf8d..3a53d150d 100644 --- a/src/stores/UserStore.js +++ b/src/stores/UserStore.js | |||
@@ -34,6 +34,8 @@ export default class UserStore extends Store { | |||
34 | 34 | ||
35 | PASSWORD_ROUTE = `${this.BASE_ROUTE}/password`; | 35 | PASSWORD_ROUTE = `${this.BASE_ROUTE}/password`; |
36 | 36 | ||
37 | CHANGE_SERVER_ROUTE = `${this.BASE_ROUTE}/server`; | ||
38 | |||
37 | @observable loginRequest = new Request(this.api.user, 'login'); | 39 | @observable loginRequest = new Request(this.api.user, 'login'); |
38 | 40 | ||
39 | @observable signupRequest = new Request(this.api.user, 'signup'); | 41 | @observable signupRequest = new Request(this.api.user, 'signup'); |
@@ -97,7 +99,7 @@ export default class UserStore extends Store { | |||
97 | 99 | ||
98 | // Reactions | 100 | // Reactions |
99 | this.registerReactions([ | 101 | this.registerReactions([ |
100 | // this._requireAuthenticatedUser, | 102 | this._requireAuthenticatedUser, |
101 | this._getUserData.bind(this), | 103 | this._getUserData.bind(this), |
102 | this._resetTrialActivationState.bind(this), | 104 | this._resetTrialActivationState.bind(this), |
103 | ]); | 105 | ]); |
@@ -137,6 +139,10 @@ export default class UserStore extends Store { | |||
137 | return this.PASSWORD_ROUTE; | 139 | return this.PASSWORD_ROUTE; |
138 | } | 140 | } |
139 | 141 | ||
142 | get changeServerRoute() { | ||
143 | return this.CHANGE_SERVER_ROUTE; | ||
144 | } | ||
145 | |||
140 | // Data | 146 | // Data |
141 | @computed get isLoggedIn() { | 147 | @computed get isLoggedIn() { |
142 | return Boolean(localStorage.getItem('authToken')); | 148 | return Boolean(localStorage.getItem('authToken')); |