diff options
author | Ricardo Cino <ricardo@cino.io> | 2022-06-22 00:32:18 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-21 22:32:18 +0000 |
commit | 73ba955e344c8ccedd43235495ef8b72b5a2b6fd (patch) | |
tree | 03766ab32fefe7e83026a14393527f1dcbaed849 /src/stores | |
parent | docs: add cino as a contributor for infra [skip ci] (#330) (diff) | |
download | ferdium-app-73ba955e344c8ccedd43235495ef8b72b5a2b6fd.tar.gz ferdium-app-73ba955e344c8ccedd43235495ef8b72b5a2b6fd.tar.zst ferdium-app-73ba955e344c8ccedd43235495ef8b72b5a2b6fd.zip |
chore: Transform AppStore.js into Typescript (#329)
* turn actions into typescript
* correct tsconfig
* added TypedStore
Diffstat (limited to 'src/stores')
-rw-r--r-- | src/stores/AppStore.ts (renamed from src/stores/AppStore.js) | 40 | ||||
-rw-r--r-- | src/stores/index.ts | 13 | ||||
-rw-r--r-- | src/stores/lib/Reaction.ts | 14 | ||||
-rw-r--r-- | src/stores/lib/Store.js | 13 | ||||
-rw-r--r-- | src/stores/lib/TypedStore.ts | 46 |
5 files changed, 100 insertions, 26 deletions
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.ts index a8e1ce247..5659460c6 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.ts | |||
@@ -14,12 +14,19 @@ import ms from 'ms'; | |||
14 | import { URL } from 'url'; | 14 | import { URL } from 'url'; |
15 | import { readJsonSync } from 'fs-extra'; | 15 | import { readJsonSync } from 'fs-extra'; |
16 | 16 | ||
17 | import Store from './lib/Store'; | 17 | import { Stores } from 'src/stores.types'; |
18 | import { ApiInterface } from 'src/api'; | ||
19 | import { Actions } from 'src/actions/lib/actions'; | ||
20 | import TypedStore from './lib/TypedStore'; | ||
18 | import Request from './lib/Request'; | 21 | import Request from './lib/Request'; |
19 | import { CHECK_INTERVAL, DEFAULT_APP_SETTINGS } from '../config'; | 22 | import { CHECK_INTERVAL, DEFAULT_APP_SETTINGS } from '../config'; |
20 | import { cleanseJSObject } from '../jsUtils'; | 23 | import { cleanseJSObject } from '../jsUtils'; |
21 | import { isMac, isWindows, electronVersion, osRelease } from '../environment'; | 24 | import { isMac, isWindows, electronVersion, osRelease } from '../environment'; |
22 | import { ferdiumVersion, userDataPath, ferdiumLocale } from '../environment-remote'; | 25 | import { |
26 | ferdiumVersion, | ||
27 | userDataPath, | ||
28 | ferdiumLocale, | ||
29 | } from '../environment-remote'; | ||
23 | import { generatedTranslations } from '../i18n/translations'; | 30 | import { generatedTranslations } from '../i18n/translations'; |
24 | import { getLocale } from '../helpers/i18n-helpers'; | 31 | import { getLocale } from '../helpers/i18n-helpers'; |
25 | 32 | ||
@@ -45,7 +52,7 @@ const CATALINA_NOTIFICATION_HACK_KEY = | |||
45 | 52 | ||
46 | const locales = generatedTranslations(); | 53 | const locales = generatedTranslations(); |
47 | 54 | ||
48 | export default class AppStore extends Store { | 55 | export default class AppStore extends TypedStore { |
49 | updateStatusTypes = { | 56 | updateStatusTypes = { |
50 | CHECKING: 'CHECKING', | 57 | CHECKING: 'CHECKING', |
51 | AVAILABLE: 'AVAILABLE', | 58 | AVAILABLE: 'AVAILABLE', |
@@ -89,10 +96,10 @@ export default class AppStore extends Store { | |||
89 | 96 | ||
90 | dictionaries = []; | 97 | dictionaries = []; |
91 | 98 | ||
92 | fetchDataInterval = null; | 99 | fetchDataInterval: null | NodeJS.Timer = null; |
93 | 100 | ||
94 | constructor(...args) { | 101 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { |
95 | super(...args); | 102 | super(stores, api, actions); |
96 | 103 | ||
97 | // Register action handlers | 104 | // Register action handlers |
98 | this.actions.app.notify.listen(this._notify.bind(this)); | 105 | this.actions.app.notify.listen(this._notify.bind(this)); |
@@ -118,7 +125,7 @@ export default class AppStore extends Store { | |||
118 | ]); | 125 | ]); |
119 | } | 126 | } |
120 | 127 | ||
121 | async setup() { | 128 | async setup(): Promise<void> { |
122 | this._appStartsCounter(); | 129 | this._appStartsCounter(); |
123 | // Focus the active service | 130 | // Focus the active service |
124 | window.addEventListener('focus', this.actions.service.focusActiveService); | 131 | window.addEventListener('focus', this.actions.service.focusActiveService); |
@@ -162,7 +169,7 @@ export default class AppStore extends Store { | |||
162 | setInterval(() => this._checkForUpdates(), CHECK_INTERVAL); | 169 | setInterval(() => this._checkForUpdates(), CHECK_INTERVAL); |
163 | // Check for an update in 30s (need a delay to prevent Squirrel Installer lock file issues) | 170 | // Check for an update in 30s (need a delay to prevent Squirrel Installer lock file issues) |
164 | setTimeout(() => this._checkForUpdates(), ms('30s')); | 171 | setTimeout(() => this._checkForUpdates(), ms('30s')); |
165 | ipcRenderer.on('autoUpdate', (event, data) => { | 172 | ipcRenderer.on('autoUpdate', (_, data) => { |
166 | if (this.updateStatus !== this.updateStatusTypes.FAILED) { | 173 | if (this.updateStatus !== this.updateStatusTypes.FAILED) { |
167 | if (data.available) { | 174 | if (data.available) { |
168 | this.updateStatus = this.updateStatusTypes.AVAILABLE; | 175 | this.updateStatus = this.updateStatusTypes.AVAILABLE; |
@@ -185,7 +192,10 @@ export default class AppStore extends Store { | |||
185 | if (data.error) { | 192 | if (data.error) { |
186 | if (data.error.message && data.error.message.startsWith('404')) { | 193 | if (data.error.message && data.error.message.startsWith('404')) { |
187 | this.updateStatus = this.updateStatusTypes.NOT_AVAILABLE; | 194 | this.updateStatus = this.updateStatusTypes.NOT_AVAILABLE; |
188 | console.warn('Updater warning: there seems to be unpublished pre-release(s) available on GitHub', data.error); | 195 | console.warn( |
196 | 'Updater warning: there seems to be unpublished pre-release(s) available on GitHub', | ||
197 | data.error, | ||
198 | ); | ||
189 | } else { | 199 | } else { |
190 | console.error('Updater error:', data.error); | 200 | console.error('Updater error:', data.error); |
191 | this.updateStatus = this.updateStatusTypes.FAILED; | 201 | this.updateStatus = this.updateStatusTypes.FAILED; |
@@ -195,7 +205,7 @@ export default class AppStore extends Store { | |||
195 | }); | 205 | }); |
196 | 206 | ||
197 | // Handle deep linking (ferdium://) | 207 | // Handle deep linking (ferdium://) |
198 | ipcRenderer.on('navigateFromDeepLink', (event, data) => { | 208 | ipcRenderer.on('navigateFromDeepLink', (_, data) => { |
199 | debug('Navigate from deep link', data); | 209 | debug('Navigate from deep link', data); |
200 | let { url } = data; | 210 | let { url } = data; |
201 | if (!url) return; | 211 | if (!url) return; |
@@ -217,7 +227,7 @@ export default class AppStore extends Store { | |||
217 | 227 | ||
218 | this.isSystemDarkModeEnabled = nativeTheme.shouldUseDarkColors; | 228 | this.isSystemDarkModeEnabled = nativeTheme.shouldUseDarkColors; |
219 | 229 | ||
220 | ipcRenderer.on('isWindowFocused', (event, isFocused) => { | 230 | ipcRenderer.on('isWindowFocused', (_, isFocused) => { |
221 | debug('Setting is focused to', isFocused); | 231 | debug('Setting is focused to', isFocused); |
222 | this.isFocused = isFocused; | 232 | this.isFocused = isFocused; |
223 | }); | 233 | }); |
@@ -391,7 +401,11 @@ export default class AppStore extends Store { | |||
391 | } | 401 | } |
392 | 402 | ||
393 | @action _checkForUpdates() { | 403 | @action _checkForUpdates() { |
394 | if (this.isOnline && this.stores.settings.app.automaticUpdates && (isMac || isWindows || process.env.APPIMAGE)) { | 404 | if ( |
405 | this.isOnline && | ||
406 | this.stores.settings.app.automaticUpdates && | ||
407 | (isMac || isWindows || process.env.APPIMAGE) | ||
408 | ) { | ||
395 | debug('_checkForUpdates: sending event to autoUpdate:check'); | 409 | debug('_checkForUpdates: sending event to autoUpdate:check'); |
396 | this.updateStatus = this.updateStatusTypes.CHECKING; | 410 | this.updateStatus = this.updateStatusTypes.CHECKING; |
397 | ipcRenderer.send('autoUpdate', { | 411 | ipcRenderer.send('autoUpdate', { |
@@ -526,7 +540,7 @@ export default class AppStore extends Store { | |||
526 | } | 540 | } |
527 | 541 | ||
528 | _handleLogout() { | 542 | _handleLogout() { |
529 | if (!this.stores.user.isLoggedIn) { | 543 | if (!this.stores.user.isLoggedIn && this.fetchDataInterval !== null) { |
530 | clearInterval(this.fetchDataInterval); | 544 | clearInterval(this.fetchDataInterval); |
531 | } | 545 | } |
532 | } | 546 | } |
diff --git a/src/stores/index.ts b/src/stores/index.ts index 6ad898d85..a5b1a7452 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts | |||
@@ -1,3 +1,7 @@ | |||
1 | import { Stores } from 'src/stores.types'; | ||
2 | import { RouterStore } from 'mobx-react-router'; | ||
3 | import { ApiInterface } from 'src/api'; | ||
4 | import { Actions } from 'src/actions/lib/actions'; | ||
1 | import AppStore from './AppStore'; | 5 | import AppStore from './AppStore'; |
2 | import UserStore from './UserStore'; | 6 | import UserStore from './UserStore'; |
3 | import FeaturesStore from './FeaturesStore'; | 7 | import FeaturesStore from './FeaturesStore'; |
@@ -12,8 +16,12 @@ import { workspaceStore } from '../features/workspaces'; | |||
12 | import { communityRecipesStore } from '../features/communityRecipes'; | 16 | import { communityRecipesStore } from '../features/communityRecipes'; |
13 | import { todosStore } from '../features/todos'; | 17 | import { todosStore } from '../features/todos'; |
14 | 18 | ||
15 | export default (api, actions, router) => { | 19 | export default ( |
16 | const stores = {}; | 20 | api: ApiInterface, |
21 | actions: Actions, | ||
22 | router: RouterStore, | ||
23 | ): Stores => { | ||
24 | const stores: Stores | any = {}; | ||
17 | Object.assign(stores, { | 25 | Object.assign(stores, { |
18 | router, | 26 | router, |
19 | app: new AppStore(stores, api, actions), | 27 | app: new AppStore(stores, api, actions), |
@@ -37,5 +45,6 @@ export default (api, actions, router) => { | |||
37 | stores[name].initialize(); | 45 | stores[name].initialize(); |
38 | } | 46 | } |
39 | } | 47 | } |
48 | |||
40 | return stores; | 49 | return stores; |
41 | }; | 50 | }; |
diff --git a/src/stores/lib/Reaction.ts b/src/stores/lib/Reaction.ts index 0ca24a6fa..3966c8073 100644 --- a/src/stores/lib/Reaction.ts +++ b/src/stores/lib/Reaction.ts | |||
@@ -1,24 +1,24 @@ | |||
1 | import { autorun } from 'mobx'; | 1 | import { autorun, IReactionDisposer, IReactionPublic } from 'mobx'; |
2 | 2 | ||
3 | export default class Reaction { | 3 | export default class Reaction { |
4 | reaction; | 4 | public reaction: (r: IReactionPublic) => any; |
5 | 5 | ||
6 | isRunning = false; | 6 | private isRunning: boolean = false; |
7 | 7 | ||
8 | dispose; | 8 | public dispose?: IReactionDisposer; |
9 | 9 | ||
10 | constructor(reaction) { | 10 | constructor(reaction: any) { |
11 | this.reaction = reaction; | 11 | this.reaction = reaction; |
12 | } | 12 | } |
13 | 13 | ||
14 | start() { | 14 | start(): void { |
15 | if (!this.isRunning) { | 15 | if (!this.isRunning) { |
16 | this.dispose = autorun(this.reaction); | 16 | this.dispose = autorun(this.reaction); |
17 | this.isRunning = true; | 17 | this.isRunning = true; |
18 | } | 18 | } |
19 | } | 19 | } |
20 | 20 | ||
21 | stop() { | 21 | stop(): void { |
22 | if (this.isRunning) { | 22 | if (this.isRunning) { |
23 | this.dispose?.(); | 23 | this.dispose?.(); |
24 | this.isRunning = false; | 24 | this.isRunning = false; |
diff --git a/src/stores/lib/Store.js b/src/stores/lib/Store.js index a867c3a46..739a47729 100644 --- a/src/stores/lib/Store.js +++ b/src/stores/lib/Store.js | |||
@@ -2,12 +2,16 @@ import { computed, observable } from 'mobx'; | |||
2 | import Reaction from './Reaction'; | 2 | import Reaction from './Reaction'; |
3 | 3 | ||
4 | export default class Store { | 4 | export default class Store { |
5 | stores = {}; | 5 | /** @type Stores */ |
6 | stores; | ||
6 | 7 | ||
7 | api = {}; | 8 | /** @type ApiInterface */ |
9 | api; | ||
8 | 10 | ||
9 | actions = {}; | 11 | /** @type Actions */ |
12 | actions; | ||
10 | 13 | ||
14 | /** @type Reaction[] */ | ||
11 | _reactions = []; | 15 | _reactions = []; |
12 | 16 | ||
13 | // status implementation | 17 | // status implementation |
@@ -28,8 +32,9 @@ export default class Store { | |||
28 | } | 32 | } |
29 | 33 | ||
30 | registerReactions(reactions) { | 34 | registerReactions(reactions) { |
31 | for (const reaction of reactions) | 35 | for (const reaction of reactions) { |
32 | this._reactions.push(new Reaction(reaction)); | 36 | this._reactions.push(new Reaction(reaction)); |
37 | } | ||
33 | } | 38 | } |
34 | 39 | ||
35 | setup() {} | 40 | setup() {} |
diff --git a/src/stores/lib/TypedStore.ts b/src/stores/lib/TypedStore.ts new file mode 100644 index 000000000..5d8bf3bbd --- /dev/null +++ b/src/stores/lib/TypedStore.ts | |||
@@ -0,0 +1,46 @@ | |||
1 | import { computed, IReactionPublic, observable } from 'mobx'; | ||
2 | import { Actions } from 'src/actions/lib/actions'; | ||
3 | import { ApiInterface } from 'src/api'; | ||
4 | import { Stores } from 'src/stores.types'; | ||
5 | import Reaction from './Reaction'; | ||
6 | |||
7 | export default abstract class TypedStore { | ||
8 | _reactions: Reaction[] = []; | ||
9 | |||
10 | @observable _status: any = null; | ||
11 | |||
12 | @computed get actionStatus() { | ||
13 | return this._status || []; | ||
14 | } | ||
15 | |||
16 | set actionStatus(status) { | ||
17 | this._status = status; | ||
18 | } | ||
19 | |||
20 | constructor( | ||
21 | public stores: Stores, | ||
22 | public api: ApiInterface, | ||
23 | public actions: Actions, | ||
24 | ) {} | ||
25 | |||
26 | registerReactions(reactions: { (r: IReactionPublic): void }[]): void { | ||
27 | for (const reaction of reactions) { | ||
28 | this._reactions.push(new Reaction(reaction)); | ||
29 | } | ||
30 | } | ||
31 | |||
32 | public abstract setup(): void; | ||
33 | |||
34 | initialize(): void { | ||
35 | this.setup(); | ||
36 | for (const reaction of this._reactions) reaction.start(); | ||
37 | } | ||
38 | |||
39 | teardown(): void { | ||
40 | for (const reaction of this._reactions) reaction.stop(); | ||
41 | } | ||
42 | |||
43 | resetStatus(): void { | ||
44 | this._status = null; | ||
45 | } | ||
46 | } | ||