diff options
author | Kristóf Marussy <kristof@marussy.com> | 2022-02-27 00:57:44 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2022-03-06 18:56:46 +0100 |
commit | f05d54406c9bc4b69609a4935132ff17b8e28824 (patch) | |
tree | e7ffde8f8b3433e004932a6e068dedbb4f2196da /packages/main | |
parent | design: Simpler message count indicators (diff) | |
download | sophie-f05d54406c9bc4b69609a4935132ff17b8e28824.tar.gz sophie-f05d54406c9bc4b69609a4935132ff17b8e28824.tar.zst sophie-f05d54406c9bc4b69609a4935132ff17b8e28824.zip |
refactor: Shared model type factories
Allows customization of stores both in the renderer and in the main
process. Instead of exposing a basic model type from the shared module
(which was be overwritted with more specific props in the main package),
we expose factory function that can create specific model types in
both the renderer and the main process.
Using these package-specific customization to stores, the renderer
package can attach IPC calls directly to store objects, which the main
package can attach the handlers for IPC calls and other internal
actions.
Signed-off-by: Kristóf Marussy <kristof@marussy.com>
Diffstat (limited to 'packages/main')
-rw-r--r-- | packages/main/src/stores/GlobalSettings.ts | 12 | ||||
-rw-r--r-- | packages/main/src/stores/Profile.ts | 7 | ||||
-rw-r--r-- | packages/main/src/stores/ProfileSettings.ts | 30 | ||||
-rw-r--r-- | packages/main/src/stores/Service.ts | 7 | ||||
-rw-r--r-- | packages/main/src/stores/ServiceSettings.ts | 10 | ||||
-rw-r--r-- | packages/main/src/stores/SharedStore.ts | 14 | ||||
-rw-r--r-- | packages/main/src/stores/config/loadConfig.ts | 2 | ||||
-rw-r--r-- | packages/main/src/utils/overrideProps.ts | 62 |
8 files changed, 13 insertions, 131 deletions
diff --git a/packages/main/src/stores/GlobalSettings.ts b/packages/main/src/stores/GlobalSettings.ts index 2af9da2..31b7e12 100644 --- a/packages/main/src/stores/GlobalSettings.ts +++ b/packages/main/src/stores/GlobalSettings.ts | |||
@@ -18,22 +18,16 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { | 21 | import { defineGlobalSettingsModel, ThemeSource } from '@sophie/shared'; |
22 | GlobalSettings as GlobalSettingsBase, | 22 | import { Instance, resolveIdentifier } from 'mobx-state-tree'; |
23 | ThemeSource, | ||
24 | } from '@sophie/shared'; | ||
25 | import { Instance, resolveIdentifier, types } from 'mobx-state-tree'; | ||
26 | 23 | ||
27 | import { getLogger } from '../utils/log'; | 24 | import { getLogger } from '../utils/log'; |
28 | import overrideProps from '../utils/overrideProps'; | ||
29 | 25 | ||
30 | import Service from './Service'; | 26 | import Service from './Service'; |
31 | 27 | ||
32 | const log = getLogger('sharedStore'); | 28 | const log = getLogger('sharedStore'); |
33 | 29 | ||
34 | const GlobalSettings = overrideProps(GlobalSettingsBase, { | 30 | const GlobalSettings = defineGlobalSettingsModel(Service).actions((self) => ({ |
35 | selectedService: types.safeReference(Service), | ||
36 | }).actions((self) => ({ | ||
37 | setThemeSource(mode: ThemeSource): void { | 31 | setThemeSource(mode: ThemeSource): void { |
38 | self.themeSource = mode; | 32 | self.themeSource = mode; |
39 | }, | 33 | }, |
diff --git a/packages/main/src/stores/Profile.ts b/packages/main/src/stores/Profile.ts index 0fd486e..836f4a8 100644 --- a/packages/main/src/stores/Profile.ts +++ b/packages/main/src/stores/Profile.ts | |||
@@ -21,14 +21,9 @@ | |||
21 | import { Profile as ProfileBase } from '@sophie/shared'; | 21 | import { Profile as ProfileBase } from '@sophie/shared'; |
22 | import { getSnapshot, Instance } from 'mobx-state-tree'; | 22 | import { getSnapshot, Instance } from 'mobx-state-tree'; |
23 | 23 | ||
24 | import overrideProps from '../utils/overrideProps'; | ||
25 | |||
26 | import ProfileSettings from './ProfileSettings'; | ||
27 | import type ProfileConfig from './config/ProfileConfig'; | 24 | import type ProfileConfig from './config/ProfileConfig'; |
28 | 25 | ||
29 | const Profile = overrideProps(ProfileBase, { | 26 | const Profile = ProfileBase.views((self) => ({ |
30 | settings: ProfileSettings, | ||
31 | }).views((self) => ({ | ||
32 | get config(): ProfileConfig { | 27 | get config(): ProfileConfig { |
33 | const { id, settings } = self; | 28 | const { id, settings } = self; |
34 | return { ...getSnapshot(settings), id }; | 29 | return { ...getSnapshot(settings), id }; |
diff --git a/packages/main/src/stores/ProfileSettings.ts b/packages/main/src/stores/ProfileSettings.ts deleted file mode 100644 index eed51e3..0000000 --- a/packages/main/src/stores/ProfileSettings.ts +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com> | ||
3 | * | ||
4 | * This file is part of Sophie. | ||
5 | * | ||
6 | * Sophie is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Affero General Public License as | ||
8 | * published by the Free Software Foundation, version 3. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * SPDX-License-Identifier: AGPL-3.0-only | ||
19 | */ | ||
20 | |||
21 | import { ProfileSettings } from '@sophie/shared'; | ||
22 | |||
23 | // TODO Export a modified ProfileSettings once we need to add actions to it. | ||
24 | // eslint-disable-next-line unicorn/prefer-export-from -- Can't export from default. | ||
25 | export default ProfileSettings; | ||
26 | |||
27 | export type { | ||
28 | ProfileSettingsSnapshotIn, | ||
29 | ProfileSettingsSnapshotOut, | ||
30 | } from '@sophie/shared'; | ||
diff --git a/packages/main/src/stores/Service.ts b/packages/main/src/stores/Service.ts index 5302dd4..abef7c2 100644 --- a/packages/main/src/stores/Service.ts +++ b/packages/main/src/stores/Service.ts | |||
@@ -19,18 +19,15 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | import type { UnreadCount } from '@sophie/service-shared'; | 21 | import type { UnreadCount } from '@sophie/service-shared'; |
22 | import { Service as ServiceBase } from '@sophie/shared'; | 22 | import { defineServiceModel } from '@sophie/shared'; |
23 | import { Instance, getSnapshot } from 'mobx-state-tree'; | 23 | import { Instance, getSnapshot } from 'mobx-state-tree'; |
24 | 24 | ||
25 | import type { ServiceView } from '../infrastructure/electron/types'; | 25 | import type { ServiceView } from '../infrastructure/electron/types'; |
26 | import overrideProps from '../utils/overrideProps'; | ||
27 | 26 | ||
28 | import ServiceSettings from './ServiceSettings'; | 27 | import ServiceSettings from './ServiceSettings'; |
29 | import type ServiceConfig from './config/ServiceConfig'; | 28 | import type ServiceConfig from './config/ServiceConfig'; |
30 | 29 | ||
31 | const Service = overrideProps(ServiceBase, { | 30 | const Service = defineServiceModel(ServiceSettings) |
32 | settings: ServiceSettings, | ||
33 | }) | ||
34 | .views((self) => ({ | 31 | .views((self) => ({ |
35 | get config(): ServiceConfig { | 32 | get config(): ServiceConfig { |
36 | const { id, settings } = self; | 33 | const { id, settings } = self; |
diff --git a/packages/main/src/stores/ServiceSettings.ts b/packages/main/src/stores/ServiceSettings.ts index e6f48c6..5d37347 100644 --- a/packages/main/src/stores/ServiceSettings.ts +++ b/packages/main/src/stores/ServiceSettings.ts | |||
@@ -18,16 +18,12 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { ServiceSettings as ServiceSettingsBase } from '@sophie/shared'; | 21 | import { defineServiceSettingsModel } from '@sophie/shared'; |
22 | import { Instance, types } from 'mobx-state-tree'; | 22 | import { Instance } from 'mobx-state-tree'; |
23 | |||
24 | import overrideProps from '../utils/overrideProps'; | ||
25 | 23 | ||
26 | import Profile from './Profile'; | 24 | import Profile from './Profile'; |
27 | 25 | ||
28 | const ServiceSettings = overrideProps(ServiceSettingsBase, { | 26 | const ServiceSettings = defineServiceSettingsModel(Profile); |
29 | profile: types.reference(Profile), | ||
30 | }); | ||
31 | 27 | ||
32 | /* | 28 | /* |
33 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | 29 | eslint-disable-next-line @typescript-eslint/no-redeclare -- |
diff --git a/packages/main/src/stores/SharedStore.ts b/packages/main/src/stores/SharedStore.ts index 182b693..d72c532 100644 --- a/packages/main/src/stores/SharedStore.ts +++ b/packages/main/src/stores/SharedStore.ts | |||
@@ -18,10 +18,8 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { SharedStore as SharedStoreBase } from '@sophie/shared'; | 21 | import { defineSharedStoreModel } from '@sophie/shared'; |
22 | import { getSnapshot, Instance, types } from 'mobx-state-tree'; | 22 | import { getSnapshot, Instance } from 'mobx-state-tree'; |
23 | |||
24 | import overrideProps from '../utils/overrideProps'; | ||
25 | 23 | ||
26 | import GlobalSettings from './GlobalSettings'; | 24 | import GlobalSettings from './GlobalSettings'; |
27 | import Profile from './Profile'; | 25 | import Profile from './Profile'; |
@@ -33,13 +31,7 @@ function getConfigs<T>(models: { config: T }[]): T[] | undefined { | |||
33 | return models.length === 0 ? undefined : models.map((model) => model.config); | 31 | return models.length === 0 ? undefined : models.map((model) => model.config); |
34 | } | 32 | } |
35 | 33 | ||
36 | const SharedStore = overrideProps(SharedStoreBase, { | 34 | const SharedStore = defineSharedStoreModel(GlobalSettings, Profile, Service) |
37 | settings: types.optional(GlobalSettings, {}), | ||
38 | profilesById: types.map(Profile), | ||
39 | profiles: types.array(types.reference(Profile)), | ||
40 | servicesById: types.map(Service), | ||
41 | services: types.array(types.reference(Service)), | ||
42 | }) | ||
43 | .views((self) => ({ | 35 | .views((self) => ({ |
44 | get config(): Config { | 36 | get config(): Config { |
45 | const { settings, profiles, services } = self; | 37 | const { settings, profiles, services } = self; |
diff --git a/packages/main/src/stores/config/loadConfig.ts b/packages/main/src/stores/config/loadConfig.ts index 55d15c8..2463084 100644 --- a/packages/main/src/stores/config/loadConfig.ts +++ b/packages/main/src/stores/config/loadConfig.ts | |||
@@ -18,6 +18,7 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { ProfileSettingsSnapshotIn } from '@sophie/shared'; | ||
21 | import { | 22 | import { |
22 | applySnapshot, | 23 | applySnapshot, |
23 | IMSTArray, | 24 | IMSTArray, |
@@ -31,7 +32,6 @@ import slug from 'slug'; | |||
31 | 32 | ||
32 | import GlobalSettings from '../GlobalSettings'; | 33 | import GlobalSettings from '../GlobalSettings'; |
33 | import type Profile from '../Profile'; | 34 | import type Profile from '../Profile'; |
34 | import type { ProfileSettingsSnapshotIn } from '../ProfileSettings'; | ||
35 | import type Service from '../Service'; | 35 | import type Service from '../Service'; |
36 | import type { ServiceSettingsSnapshotIn } from '../ServiceSettings'; | 36 | import type { ServiceSettingsSnapshotIn } from '../ServiceSettings'; |
37 | 37 | ||
diff --git a/packages/main/src/utils/overrideProps.ts b/packages/main/src/utils/overrideProps.ts deleted file mode 100644 index c626408..0000000 --- a/packages/main/src/utils/overrideProps.ts +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com> | ||
3 | * | ||
4 | * This file is part of Sophie. | ||
5 | * | ||
6 | * Sophie is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Affero General Public License as | ||
8 | * published by the Free Software Foundation, version 3. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * SPDX-License-Identifier: AGPL-3.0-only | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file This file implements a technique to force-override properties of a model. | ||
23 | * | ||
24 | * The overridden properties must conform to the SnapshotIt and SnapshotOut format | ||
25 | * of the original model. Essentially, this means that only views and actions can | ||
26 | * be added safely. | ||
27 | * | ||
28 | * @see https://github.com/mobxjs/mobx-state-tree/issues/1403#issuecomment-940843087 | ||
29 | */ | ||
30 | |||
31 | import { | ||
32 | IAnyModelType, | ||
33 | IModelType, | ||
34 | ModelProperties, | ||
35 | SnapshotIn, | ||
36 | SnapshotOut, | ||
37 | } from 'mobx-state-tree'; | ||
38 | |||
39 | export type IUnsafeOverriddenModelType< | ||
40 | BASE extends IAnyModelType, | ||
41 | PROPS extends ModelProperties, | ||
42 | > = BASE extends IModelType<infer P, infer O, infer CC, infer CS> | ||
43 | ? IModelType<Omit<P, keyof PROPS> & PROPS, O, CC, CS> | ||
44 | : never; | ||
45 | |||
46 | export type IOverriddenModelType< | ||
47 | BASE extends IAnyModelType, | ||
48 | PROPS extends ModelProperties, | ||
49 | > = SnapshotIn<BASE> extends SnapshotIn<IUnsafeOverriddenModelType<BASE, PROPS>> | ||
50 | ? SnapshotOut< | ||
51 | IUnsafeOverriddenModelType<BASE, PROPS> | ||
52 | > extends SnapshotOut<BASE> | ||
53 | ? IUnsafeOverriddenModelType<BASE, PROPS> | ||
54 | : never | ||
55 | : never; | ||
56 | |||
57 | export default function overrideProps< | ||
58 | BASE extends IAnyModelType, | ||
59 | PROPS extends ModelProperties, | ||
60 | >(base: BASE, props: PROPS): IOverriddenModelType<BASE, PROPS> { | ||
61 | return base.props(props) as IOverriddenModelType<BASE, PROPS>; | ||
62 | } | ||