diff options
Diffstat (limited to 'packages')
25 files changed, 348 insertions, 230 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/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 | } | ||
diff --git a/packages/renderer/src/components/locationBar/LocationTextField.tsx b/packages/renderer/src/components/locationBar/LocationTextField.tsx index f436bf0..e6da59f 100644 --- a/packages/renderer/src/components/locationBar/LocationTextField.tsx +++ b/packages/renderer/src/components/locationBar/LocationTextField.tsx | |||
@@ -20,11 +20,12 @@ | |||
20 | 20 | ||
21 | import FilledInput from '@mui/material/FilledInput'; | 21 | import FilledInput from '@mui/material/FilledInput'; |
22 | import { styled } from '@mui/material/styles'; | 22 | import { styled } from '@mui/material/styles'; |
23 | import { Service } from '@sophie/shared'; | ||
24 | import { autorun } from 'mobx'; | 23 | import { autorun } from 'mobx'; |
25 | import { observer } from 'mobx-react-lite'; | 24 | import { observer } from 'mobx-react-lite'; |
26 | import React, { useCallback, useEffect, useState } from 'react'; | 25 | import React, { useCallback, useEffect, useState } from 'react'; |
27 | 26 | ||
27 | import Service from '../../stores/Service'; | ||
28 | |||
28 | import GoAdornment from './GoAdornment'; | 29 | import GoAdornment from './GoAdornment'; |
29 | import LocationOverlayInput from './LocationOverlayInput'; | 30 | import LocationOverlayInput from './LocationOverlayInput'; |
30 | import UrlAdornment from './UrlAdornment'; | 31 | import UrlAdornment from './UrlAdornment'; |
diff --git a/packages/renderer/src/components/locationBar/NavigationButtons.tsx b/packages/renderer/src/components/locationBar/NavigationButtons.tsx index 77b02b6..ce59692 100644 --- a/packages/renderer/src/components/locationBar/NavigationButtons.tsx +++ b/packages/renderer/src/components/locationBar/NavigationButtons.tsx | |||
@@ -26,10 +26,11 @@ import IconRefresh from '@mui/icons-material/Refresh'; | |||
26 | import { useTheme } from '@mui/material'; | 26 | import { useTheme } from '@mui/material'; |
27 | import Box from '@mui/material/Box'; | 27 | import Box from '@mui/material/Box'; |
28 | import IconButton from '@mui/material/IconButton'; | 28 | import IconButton from '@mui/material/IconButton'; |
29 | import { Service } from '@sophie/shared'; | ||
30 | import { observer } from 'mobx-react-lite'; | 29 | import { observer } from 'mobx-react-lite'; |
31 | import React from 'react'; | 30 | import React from 'react'; |
32 | 31 | ||
32 | import Service from '../../stores/Service'; | ||
33 | |||
33 | function NavigationButtons({ | 34 | function NavigationButtons({ |
34 | service, | 35 | service, |
35 | }: { | 36 | }: { |
diff --git a/packages/renderer/src/components/sidebar/ServiceIcon.tsx b/packages/renderer/src/components/sidebar/ServiceIcon.tsx index 144f860..5db8a0c 100644 --- a/packages/renderer/src/components/sidebar/ServiceIcon.tsx +++ b/packages/renderer/src/components/sidebar/ServiceIcon.tsx | |||
@@ -20,10 +20,11 @@ | |||
20 | 20 | ||
21 | import Badge from '@mui/material/Badge'; | 21 | import Badge from '@mui/material/Badge'; |
22 | import { styled, useTheme } from '@mui/material/styles'; | 22 | import { styled, useTheme } from '@mui/material/styles'; |
23 | import { Service } from '@sophie/shared'; | ||
24 | import { observer } from 'mobx-react-lite'; | 23 | import { observer } from 'mobx-react-lite'; |
25 | import React, { useEffect, useState } from 'react'; | 24 | import React, { useEffect, useState } from 'react'; |
26 | 25 | ||
26 | import type Service from '../../stores/Service'; | ||
27 | |||
27 | const ServiceIconRoot = styled('div', { | 28 | const ServiceIconRoot = styled('div', { |
28 | name: 'ServiceIcon', | 29 | name: 'ServiceIcon', |
29 | slot: 'Root', | 30 | slot: 'Root', |
diff --git a/packages/renderer/src/components/sidebar/ServiceSwitcher.tsx b/packages/renderer/src/components/sidebar/ServiceSwitcher.tsx index 2241476..eba21b5 100644 --- a/packages/renderer/src/components/sidebar/ServiceSwitcher.tsx +++ b/packages/renderer/src/components/sidebar/ServiceSwitcher.tsx | |||
@@ -65,11 +65,8 @@ const ServiceSwitcherTab = styled(Tab, { | |||
65 | })); | 65 | })); |
66 | 66 | ||
67 | function ServiceSwitcher(): JSX.Element { | 67 | function ServiceSwitcher(): JSX.Element { |
68 | const store = useStore(); | 68 | const { settings, services } = useStore(); |
69 | const { | 69 | const { selectedService } = settings; |
70 | settings: { selectedService }, | ||
71 | services, | ||
72 | } = store; | ||
73 | 70 | ||
74 | return ( | 71 | return ( |
75 | <ServiceSwitcherRoot | 72 | <ServiceSwitcherRoot |
@@ -77,7 +74,7 @@ function ServiceSwitcher(): JSX.Element { | |||
77 | orientation="vertical" | 74 | orientation="vertical" |
78 | value={selectedService === undefined ? false : selectedService.id} | 75 | value={selectedService === undefined ? false : selectedService.id} |
79 | onChange={(_event, newValue: string) => | 76 | onChange={(_event, newValue: string) => |
80 | store.setSelectedServiceId(newValue) | 77 | settings.setSelectedServiceId(newValue) |
81 | } | 78 | } |
82 | > | 79 | > |
83 | {services.map((service) => ( | 80 | {services.map((service) => ( |
diff --git a/packages/renderer/src/components/sidebar/ToggleDarkModeButton.tsx b/packages/renderer/src/components/sidebar/ToggleDarkModeButton.tsx index 164b066..bacbf07 100644 --- a/packages/renderer/src/components/sidebar/ToggleDarkModeButton.tsx +++ b/packages/renderer/src/components/sidebar/ToggleDarkModeButton.tsx | |||
@@ -27,15 +27,13 @@ import React from 'react'; | |||
27 | import { useStore } from '../StoreProvider'; | 27 | import { useStore } from '../StoreProvider'; |
28 | 28 | ||
29 | export default observer(() => { | 29 | export default observer(() => { |
30 | const store = useStore(); | 30 | const { shared } = useStore(); |
31 | const { | 31 | const { shouldUseDarkColors } = shared; |
32 | shared: { shouldUseDarkColors }, | ||
33 | } = store; | ||
34 | 32 | ||
35 | return ( | 33 | return ( |
36 | <IconButton | 34 | <IconButton |
37 | aria-label="Toggle dark mode" | 35 | aria-label="Toggle dark mode" |
38 | onClick={() => store.toggleDarkMode()} | 36 | onClick={() => shared.toggleDarkMode()} |
39 | > | 37 | > |
40 | {shouldUseDarkColors ? <LightModeIcon /> : <DarkModeIcon />} | 38 | {shouldUseDarkColors ? <LightModeIcon /> : <DarkModeIcon />} |
41 | </IconButton> | 39 | </IconButton> |
diff --git a/packages/renderer/src/components/sidebar/ToggleLocationBarButton.tsx b/packages/renderer/src/components/sidebar/ToggleLocationBarButton.tsx index 60033b0..d2f0745 100644 --- a/packages/renderer/src/components/sidebar/ToggleLocationBarButton.tsx +++ b/packages/renderer/src/components/sidebar/ToggleLocationBarButton.tsx | |||
@@ -45,17 +45,15 @@ function ToggleLocationBarIcon({ | |||
45 | } | 45 | } |
46 | 46 | ||
47 | function ToggleLocationBarButton(): JSX.Element { | 47 | function ToggleLocationBarButton(): JSX.Element { |
48 | const store = useStore(); | 48 | const { settings } = useStore(); |
49 | const { | 49 | const { selectedService, showLocationBar } = settings; |
50 | settings: { selectedService, showLocationBar }, | ||
51 | } = store; | ||
52 | 50 | ||
53 | return ( | 51 | return ( |
54 | <IconButton | 52 | <IconButton |
55 | aria-pressed={showLocationBar} | 53 | aria-pressed={showLocationBar} |
56 | aria-controls={LOCATION_BAR_ID} | 54 | aria-controls={LOCATION_BAR_ID} |
57 | aria-label="Show location bar" | 55 | aria-label="Show location bar" |
58 | onClick={() => store.toggleLocationBar()} | 56 | onClick={() => settings.toggleLocationBar()} |
59 | > | 57 | > |
60 | <ToggleLocationBarIcon | 58 | <ToggleLocationBarIcon |
61 | loading={selectedService?.state === 'loading'} | 59 | loading={selectedService?.state === 'loading'} |
diff --git a/packages/renderer/src/stores/GlobalSettings.ts b/packages/renderer/src/stores/GlobalSettings.ts new file mode 100644 index 0000000..79815ba --- /dev/null +++ b/packages/renderer/src/stores/GlobalSettings.ts | |||
@@ -0,0 +1,63 @@ | |||
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 { defineGlobalSettingsModel, ThemeSource } from '@sophie/shared'; | ||
22 | import { Instance } from 'mobx-state-tree'; | ||
23 | |||
24 | import getEnv from '../env/getEnv'; | ||
25 | |||
26 | import Service from './Service'; | ||
27 | |||
28 | const GlobalSettings = defineGlobalSettingsModel(Service).actions((self) => ({ | ||
29 | setSelectedServiceId(serviceId: string): void { | ||
30 | getEnv(self).dispatchMainAction({ | ||
31 | action: 'set-selected-service-id', | ||
32 | serviceId, | ||
33 | }); | ||
34 | }, | ||
35 | setThemeSource(themeSource: ThemeSource): void { | ||
36 | getEnv(self).dispatchMainAction({ | ||
37 | action: 'set-theme-source', | ||
38 | themeSource, | ||
39 | }); | ||
40 | }, | ||
41 | setShowLocationBar(showLocationBar: boolean): void { | ||
42 | getEnv(self).dispatchMainAction({ | ||
43 | action: 'set-show-location-bar', | ||
44 | showLocationBar, | ||
45 | }); | ||
46 | }, | ||
47 | toggleLocationBar(): void { | ||
48 | this.setShowLocationBar(!self.showLocationBar); | ||
49 | }, | ||
50 | })); | ||
51 | |||
52 | /* | ||
53 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | ||
54 | Intentionally naming the type the same as the store definition. | ||
55 | */ | ||
56 | interface GlobalSettings extends Instance<typeof GlobalSettings> {} | ||
57 | |||
58 | export default GlobalSettings; | ||
59 | |||
60 | export type { | ||
61 | GlobalSettingsSnapshotIn, | ||
62 | GlobalSettingsSnapshotOut, | ||
63 | } from '@sophie/shared'; | ||
diff --git a/packages/main/src/stores/ProfileSettings.ts b/packages/renderer/src/stores/Profile.ts index eed51e3..20a3a17 100644 --- a/packages/main/src/stores/ProfileSettings.ts +++ b/packages/renderer/src/stores/Profile.ts | |||
@@ -18,13 +18,15 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { ProfileSettings } from '@sophie/shared'; | 21 | import { Profile as ProfileBase } from '@sophie/shared'; |
22 | import { Instance } from 'mobx-state-tree'; | ||
22 | 23 | ||
23 | // TODO Export a modified ProfileSettings once we need to add actions to it. | 24 | const Profile = ProfileBase; |
24 | // eslint-disable-next-line unicorn/prefer-export-from -- Can't export from default. | ||
25 | export default ProfileSettings; | ||
26 | 25 | ||
27 | export type { | 26 | /* |
28 | ProfileSettingsSnapshotIn, | 27 | eslint-disable-next-line @typescript-eslint/no-redeclare -- |
29 | ProfileSettingsSnapshotOut, | 28 | Intentionally naming the type the same as the store definition. |
30 | } from '@sophie/shared'; | 29 | */ |
30 | interface Profile extends Instance<typeof Profile> {} | ||
31 | |||
32 | export default Profile; | ||
diff --git a/packages/renderer/src/stores/RendererStore.ts b/packages/renderer/src/stores/RendererStore.ts index 1acc605..8f424f6 100644 --- a/packages/renderer/src/stores/RendererStore.ts +++ b/packages/renderer/src/stores/RendererStore.ts | |||
@@ -18,20 +18,17 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { | 21 | import { BrowserViewBounds, SophieRenderer } from '@sophie/shared'; |
22 | BrowserViewBounds, | ||
23 | SharedStore, | ||
24 | Service, | ||
25 | SophieRenderer, | ||
26 | ThemeSource, | ||
27 | GlobalSettings, | ||
28 | } from '@sophie/shared'; | ||
29 | import { applySnapshot, applyPatch, Instance, types } from 'mobx-state-tree'; | 22 | import { applySnapshot, applyPatch, Instance, types } from 'mobx-state-tree'; |
30 | 23 | ||
31 | import RendererEnv from '../env/RendererEnv'; | 24 | import RendererEnv from '../env/RendererEnv'; |
32 | import getEnv from '../env/getEnv'; | 25 | import getEnv from '../env/getEnv'; |
33 | import { getLogger } from '../utils/log'; | 26 | import { getLogger } from '../utils/log'; |
34 | 27 | ||
28 | import GlobalSettings from './GlobalSettings'; | ||
29 | import Service from './Service'; | ||
30 | import SharedStore from './SharedStore'; | ||
31 | |||
35 | const log = getLogger('RendererStore'); | 32 | const log = getLogger('RendererStore'); |
36 | 33 | ||
37 | const RendererStore = types | 34 | const RendererStore = types |
@@ -47,40 +44,12 @@ const RendererStore = types | |||
47 | }, | 44 | }, |
48 | })) | 45 | })) |
49 | .actions((self) => ({ | 46 | .actions((self) => ({ |
50 | setSelectedServiceId(serviceId: string): void { | ||
51 | getEnv(self).dispatchMainAction({ | ||
52 | action: 'set-selected-service-id', | ||
53 | serviceId, | ||
54 | }); | ||
55 | }, | ||
56 | setBrowserViewBounds(browserViewBounds: BrowserViewBounds): void { | 47 | setBrowserViewBounds(browserViewBounds: BrowserViewBounds): void { |
57 | getEnv(self).dispatchMainAction({ | 48 | getEnv(self).dispatchMainAction({ |
58 | action: 'set-browser-view-bounds', | 49 | action: 'set-browser-view-bounds', |
59 | browserViewBounds, | 50 | browserViewBounds, |
60 | }); | 51 | }); |
61 | }, | 52 | }, |
62 | setThemeSource(themeSource: ThemeSource): void { | ||
63 | getEnv(self).dispatchMainAction({ | ||
64 | action: 'set-theme-source', | ||
65 | themeSource, | ||
66 | }); | ||
67 | }, | ||
68 | toggleDarkMode(): void { | ||
69 | if (self.shared.shouldUseDarkColors) { | ||
70 | this.setThemeSource('light'); | ||
71 | } else { | ||
72 | this.setThemeSource('dark'); | ||
73 | } | ||
74 | }, | ||
75 | setShowLocationBar(showLocationBar: boolean): void { | ||
76 | getEnv(self).dispatchMainAction({ | ||
77 | action: 'set-show-location-bar', | ||
78 | showLocationBar, | ||
79 | }); | ||
80 | }, | ||
81 | toggleLocationBar(): void { | ||
82 | this.setShowLocationBar(!self.settings.showLocationBar); | ||
83 | }, | ||
84 | })); | 53 | })); |
85 | 54 | ||
86 | /* | 55 | /* |
diff --git a/packages/renderer/src/stores/Service.ts b/packages/renderer/src/stores/Service.ts new file mode 100644 index 0000000..c2c938a --- /dev/null +++ b/packages/renderer/src/stores/Service.ts | |||
@@ -0,0 +1,34 @@ | |||
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 { defineServiceModel } from '@sophie/shared'; | ||
22 | import { Instance } from 'mobx-state-tree'; | ||
23 | |||
24 | import ServiceSettings from './ServiceSettings'; | ||
25 | |||
26 | const Service = defineServiceModel(ServiceSettings); | ||
27 | |||
28 | /* | ||
29 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | ||
30 | Intentionally naming the type the same as the store definition. | ||
31 | */ | ||
32 | interface Service extends Instance<typeof Service> {} | ||
33 | |||
34 | export default Service; | ||
diff --git a/packages/shared/src/stores/ServiceSettings.ts b/packages/renderer/src/stores/ServiceSettings.ts index a5811f5..5d37347 100644 --- a/packages/shared/src/stores/ServiceSettings.ts +++ b/packages/renderer/src/stores/ServiceSettings.ts | |||
@@ -18,17 +18,12 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { Instance, types, SnapshotIn, SnapshotOut } from 'mobx-state-tree'; | 21 | import { defineServiceSettingsModel } from '@sophie/shared'; |
22 | import { Instance } from 'mobx-state-tree'; | ||
22 | 23 | ||
23 | import Profile from './Profile'; | 24 | import Profile from './Profile'; |
24 | 25 | ||
25 | const ServiceSettings = /* @__PURE__ */ (() => | 26 | const ServiceSettings = defineServiceSettingsModel(Profile); |
26 | types.model('ServiceSettings', { | ||
27 | name: types.string, | ||
28 | profile: types.reference(Profile), | ||
29 | // TODO: Remove this once recipes are added. | ||
30 | url: types.string, | ||
31 | }))(); | ||
32 | 27 | ||
33 | /* | 28 | /* |
34 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | 29 | eslint-disable-next-line @typescript-eslint/no-redeclare -- |
@@ -38,8 +33,7 @@ interface ServiceSettings extends Instance<typeof ServiceSettings> {} | |||
38 | 33 | ||
39 | export default ServiceSettings; | 34 | export default ServiceSettings; |
40 | 35 | ||
41 | export interface ServiceSettingsSnapshotIn | 36 | export type { |
42 | extends SnapshotIn<typeof ServiceSettings> {} | 37 | ServiceSettingsSnapshotIn, |
43 | 38 | ServiceSettingsSnapshotOut, | |
44 | export interface ServiceSettingsSnapshotOut | 39 | } from '@sophie/shared'; |
45 | extends SnapshotOut<typeof ServiceSettings> {} | ||
diff --git a/packages/shared/src/stores/SharedStore.ts b/packages/renderer/src/stores/SharedStore.ts index d81a3d3..062479d 100644 --- a/packages/shared/src/stores/SharedStore.ts +++ b/packages/renderer/src/stores/SharedStore.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2021-2022 Kristóf Marussy <kristof@marussy.com> | 2 | * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com> |
3 | * | 3 | * |
4 | * This file is part of Sophie. | 4 | * This file is part of Sophie. |
5 | * | 5 | * |
@@ -18,27 +18,26 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { | 21 | import { defineSharedStoreModel } from '@sophie/shared'; |
22 | IJsonPatch, | 22 | import { Instance } from 'mobx-state-tree'; |
23 | Instance, | ||
24 | types, | ||
25 | SnapshotIn, | ||
26 | SnapshotOut, | ||
27 | } from 'mobx-state-tree'; | ||
28 | 23 | ||
29 | import GlobalSettings from './GlobalSettings'; | 24 | import GlobalSettings from './GlobalSettings'; |
30 | import Profile from './Profile'; | 25 | import Profile from './Profile'; |
31 | import Service from './Service'; | 26 | import Service from './Service'; |
32 | 27 | ||
33 | const SharedStore = /* @__PURE__ */ (() => | 28 | const SharedStore = defineSharedStoreModel( |
34 | types.model('SharedStore', { | 29 | GlobalSettings, |
35 | settings: types.optional(GlobalSettings, {}), | 30 | Profile, |
36 | profilesById: types.map(Profile), | 31 | Service, |
37 | profiles: types.array(types.reference(Profile)), | 32 | ).actions((self) => ({ |
38 | servicesById: types.map(Service), | 33 | toggleDarkMode(): void { |
39 | services: types.array(types.reference(Service)), | 34 | if (self.shouldUseDarkColors) { |
40 | shouldUseDarkColors: false, | 35 | self.settings.setThemeSource('light'); |
41 | }))(); | 36 | } else { |
37 | self.settings.setThemeSource('dark'); | ||
38 | } | ||
39 | }, | ||
40 | })); | ||
42 | 41 | ||
43 | /* | 42 | /* |
44 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | 43 | eslint-disable-next-line @typescript-eslint/no-redeclare -- |
@@ -48,13 +47,7 @@ interface SharedStore extends Instance<typeof SharedStore> {} | |||
48 | 47 | ||
49 | export default SharedStore; | 48 | export default SharedStore; |
50 | 49 | ||
51 | export interface SharedStoreSnapshotIn extends SnapshotIn<typeof SharedStore> {} | 50 | export type { |
52 | 51 | SharedStoreSnapshotIn, | |
53 | export interface SharedStoreSnapshotOut | 52 | SharedStoreSnapshotOut, |
54 | extends SnapshotOut<typeof SharedStore> {} | 53 | } from '@sophie/shared'; |
55 | |||
56 | export interface SharedStoreListener { | ||
57 | onSnapshot(snapshot: SharedStoreSnapshotIn): void; | ||
58 | |||
59 | onPatch(patches: IJsonPatch[]): void; | ||
60 | } | ||
diff --git a/packages/shared/src/contextBridge/SophieRenderer.ts b/packages/shared/src/contextBridge/SophieRenderer.ts index 28dc0b7..9e087da 100644 --- a/packages/shared/src/contextBridge/SophieRenderer.ts +++ b/packages/shared/src/contextBridge/SophieRenderer.ts | |||
@@ -19,7 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { Action } from '../schemas'; | 21 | import { Action } from '../schemas'; |
22 | import { SharedStoreListener } from '../stores/SharedStore'; | 22 | import { SharedStoreListener } from '../stores/SharedStoreBase'; |
23 | 23 | ||
24 | export default interface SophieRenderer { | 24 | export default interface SophieRenderer { |
25 | onSharedStoreChange(this: void, listener: SharedStoreListener): Promise<void>; | 25 | onSharedStoreChange(this: void, listener: SharedStoreListener): Promise<void>; |
diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 3d30488..66debf7 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts | |||
@@ -27,8 +27,11 @@ export { Action, BrowserViewBounds, ThemeSource } from './schemas'; | |||
27 | export type { | 27 | export type { |
28 | GlobalSettingsSnapshotIn, | 28 | GlobalSettingsSnapshotIn, |
29 | GlobalSettingsSnapshotOut, | 29 | GlobalSettingsSnapshotOut, |
30 | } from './stores/GlobalSettings'; | 30 | } from './stores/GlobalSettingsBase'; |
31 | export { default as GlobalSettings } from './stores/GlobalSettings'; | 31 | export { |
32 | default as GlobalSettingsBase, | ||
33 | defineGlobalSettingsModel, | ||
34 | } from './stores/GlobalSettingsBase'; | ||
32 | 35 | ||
33 | export { default as Profile } from './stores/Profile'; | 36 | export { default as Profile } from './stores/Profile'; |
34 | 37 | ||
@@ -38,17 +41,26 @@ export type { | |||
38 | } from './stores/ProfileSettings'; | 41 | } from './stores/ProfileSettings'; |
39 | export { default as ProfileSettings } from './stores/ProfileSettings'; | 42 | export { default as ProfileSettings } from './stores/ProfileSettings'; |
40 | 43 | ||
41 | export { default as Service } from './stores/Service'; | 44 | export { |
45 | default as ServiceBase, | ||
46 | defineServiceModel, | ||
47 | } from './stores/ServiceBase'; | ||
42 | 48 | ||
43 | export type { | 49 | export type { |
44 | ServiceSettingsSnapshotIn, | 50 | ServiceSettingsSnapshotIn, |
45 | ServiceSettingsSnapshotOut, | 51 | ServiceSettingsSnapshotOut, |
46 | } from './stores/ServiceSettings'; | 52 | } from './stores/ServiceSettingsBase'; |
47 | export { default as ServiceSettings } from './stores/ServiceSettings'; | 53 | export { |
54 | default as ServiceSettingsBase, | ||
55 | defineServiceSettingsModel, | ||
56 | } from './stores/ServiceSettingsBase'; | ||
48 | 57 | ||
49 | export type { | 58 | export type { |
50 | SharedStoreListener, | 59 | SharedStoreListener, |
51 | SharedStoreSnapshotIn, | 60 | SharedStoreSnapshotIn, |
52 | SharedStoreSnapshotOut, | 61 | SharedStoreSnapshotOut, |
53 | } from './stores/SharedStore'; | 62 | } from './stores/SharedStoreBase'; |
54 | export { default as SharedStore } from './stores/SharedStore'; | 63 | export { |
64 | default as SharedStoreBase, | ||
65 | defineSharedStoreModel, | ||
66 | } from './stores/SharedStoreBase'; | ||
diff --git a/packages/shared/src/stores/GlobalSettings.ts b/packages/shared/src/stores/GlobalSettingsBase.ts index f316af9..48092fd 100644 --- a/packages/shared/src/stores/GlobalSettings.ts +++ b/packages/shared/src/stores/GlobalSettingsBase.ts | |||
@@ -18,32 +18,44 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { Instance, types, SnapshotIn, SnapshotOut } from 'mobx-state-tree'; | 21 | import { |
22 | Instance, | ||
23 | types, | ||
24 | SnapshotIn, | ||
25 | SnapshotOut, | ||
26 | IAnyModelType, | ||
27 | } from 'mobx-state-tree'; | ||
22 | 28 | ||
23 | import { ThemeSource } from '../schemas'; | 29 | import { ThemeSource } from '../schemas'; |
24 | 30 | ||
25 | import Service from './Service'; | 31 | import ServiceBase from './ServiceBase'; |
26 | 32 | ||
27 | const GlobalSettings = /* @__PURE__ */ (() => | 33 | export function defineGlobalSettingsModel<TS extends IAnyModelType>( |
28 | types.model('GlobalSettings', { | 34 | service: TS, |
35 | ) { | ||
36 | return types.model('GlobalSettings', { | ||
29 | themeSource: types.optional( | 37 | themeSource: types.optional( |
30 | types.enumeration(ThemeSource.options), | 38 | types.enumeration(ThemeSource.options), |
31 | 'system', | 39 | 'system', |
32 | ), | 40 | ), |
33 | showLocationBar: false, | 41 | showLocationBar: false, |
34 | selectedService: types.safeReference(Service), | 42 | selectedService: types.safeReference(service), |
35 | }))(); | 43 | }); |
44 | } | ||
45 | |||
46 | const GlobalSettingsBase = /* @__PURE__ */ (() => | ||
47 | defineGlobalSettingsModel(ServiceBase))(); | ||
36 | 48 | ||
37 | /* | 49 | /* |
38 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | 50 | eslint-disable-next-line @typescript-eslint/no-redeclare -- |
39 | Intentionally naming the type the same as the store definition. | 51 | Intentionally naming the type the same as the store definition. |
40 | */ | 52 | */ |
41 | interface GlobalSettings extends Instance<typeof GlobalSettings> {} | 53 | interface GlobalSettingsBase extends Instance<typeof GlobalSettingsBase> {} |
42 | 54 | ||
43 | export default GlobalSettings; | 55 | export default GlobalSettingsBase; |
44 | 56 | ||
45 | export interface GlobalSettingsSnapshotIn | 57 | export interface GlobalSettingsSnapshotIn |
46 | extends SnapshotIn<typeof GlobalSettings> {} | 58 | extends SnapshotIn<typeof GlobalSettingsBase> {} |
47 | 59 | ||
48 | export interface GlobalSettingsSnapshotOut | 60 | export interface GlobalSettingsSnapshotOut |
49 | extends SnapshotOut<typeof GlobalSettings> {} | 61 | extends SnapshotOut<typeof GlobalSettingsBase> {} |
diff --git a/packages/shared/src/stores/Service.ts b/packages/shared/src/stores/ServiceBase.ts index a4e3c92..cde403b 100644 --- a/packages/shared/src/stores/Service.ts +++ b/packages/shared/src/stores/ServiceBase.ts | |||
@@ -18,14 +18,14 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { Instance, types } from 'mobx-state-tree'; | 21 | import { IAnyModelType, Instance, types } from 'mobx-state-tree'; |
22 | 22 | ||
23 | import ServiceSettings from './ServiceSettings'; | 23 | import ServiceSettingsBase from './ServiceSettingsBase'; |
24 | 24 | ||
25 | const Service = /* @__PURE__ */ (() => | 25 | export function defineServiceModel<TS extends IAnyModelType>(settings: TS) { |
26 | types.model('Service', { | 26 | return types.model('Service', { |
27 | id: types.identifier, | 27 | id: types.identifier, |
28 | settings: ServiceSettings, | 28 | settings, |
29 | currentUrl: types.maybe(types.string), | 29 | currentUrl: types.maybe(types.string), |
30 | canGoBack: false, | 30 | canGoBack: false, |
31 | canGoForward: false, | 31 | canGoForward: false, |
@@ -36,12 +36,16 @@ const Service = /* @__PURE__ */ (() => | |||
36 | ), | 36 | ), |
37 | directMessageCount: 0, | 37 | directMessageCount: 0, |
38 | indirectMessageCount: 0, | 38 | indirectMessageCount: 0, |
39 | }))(); | 39 | }); |
40 | } | ||
41 | |||
42 | const ServiceBase = /* @__PURE__ */ (() => | ||
43 | defineServiceModel(ServiceSettingsBase))(); | ||
40 | 44 | ||
41 | /* | 45 | /* |
42 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | 46 | eslint-disable-next-line @typescript-eslint/no-redeclare -- |
43 | Intentionally naming the type the same as the store definition. | 47 | Intentionally naming the type the same as the store definition. |
44 | */ | 48 | */ |
45 | interface Service extends Instance<typeof Service> {} | 49 | interface ServiceBase extends Instance<typeof ServiceBase> {} |
46 | 50 | ||
47 | export default Service; | 51 | export default ServiceBase; |
diff --git a/packages/shared/src/stores/ServiceSettingsBase.ts b/packages/shared/src/stores/ServiceSettingsBase.ts new file mode 100644 index 0000000..45eb15d --- /dev/null +++ b/packages/shared/src/stores/ServiceSettingsBase.ts | |||
@@ -0,0 +1,57 @@ | |||
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 { | ||
22 | Instance, | ||
23 | types, | ||
24 | SnapshotIn, | ||
25 | SnapshotOut, | ||
26 | IAnyModelType, | ||
27 | } from 'mobx-state-tree'; | ||
28 | |||
29 | import ProfileBase from './Profile'; | ||
30 | |||
31 | export function defineServiceSettingsModel<TP extends IAnyModelType>( | ||
32 | profile: TP, | ||
33 | ) { | ||
34 | return types.model('ServiceSettings', { | ||
35 | name: types.string, | ||
36 | profile: types.reference(profile), | ||
37 | // TODO: Remove this once recipes are added. | ||
38 | url: types.string, | ||
39 | }); | ||
40 | } | ||
41 | |||
42 | const ServiceSettingsBase = /* @__PURE__ */ (() => | ||
43 | defineServiceSettingsModel(ProfileBase))(); | ||
44 | |||
45 | /* | ||
46 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | ||
47 | Intentionally naming the type the same as the store definition. | ||
48 | */ | ||
49 | interface ServiceSettingsBase extends Instance<typeof ServiceSettingsBase> {} | ||
50 | |||
51 | export default ServiceSettingsBase; | ||
52 | |||
53 | export interface ServiceSettingsSnapshotIn | ||
54 | extends SnapshotIn<typeof ServiceSettingsBase> {} | ||
55 | |||
56 | export interface ServiceSettingsSnapshotOut | ||
57 | extends SnapshotOut<typeof ServiceSettingsBase> {} | ||
diff --git a/packages/shared/src/stores/SharedStoreBase.ts b/packages/shared/src/stores/SharedStoreBase.ts new file mode 100644 index 0000000..8d6624b --- /dev/null +++ b/packages/shared/src/stores/SharedStoreBase.ts | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2021-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 { | ||
22 | IJsonPatch, | ||
23 | Instance, | ||
24 | types, | ||
25 | SnapshotIn, | ||
26 | SnapshotOut, | ||
27 | IAnyModelType, | ||
28 | } from 'mobx-state-tree'; | ||
29 | |||
30 | import GlobalSettingsBase from './GlobalSettingsBase'; | ||
31 | import ProfileBase from './Profile'; | ||
32 | import ServiceBase from './ServiceBase'; | ||
33 | |||
34 | export function defineSharedStoreModel< | ||
35 | TG extends IAnyModelType, | ||
36 | TP extends IAnyModelType, | ||
37 | TS extends IAnyModelType, | ||
38 | >(globalSettings: TG, profile: TP, service: TS) { | ||
39 | return types.model('SharedStore', { | ||
40 | settings: types.optional(globalSettings, {}), | ||
41 | profilesById: types.map(profile), | ||
42 | profiles: types.array(types.reference(profile)), | ||
43 | servicesById: types.map(service), | ||
44 | services: types.array(types.reference(service)), | ||
45 | shouldUseDarkColors: false, | ||
46 | }); | ||
47 | } | ||
48 | |||
49 | const SharedStoreBase = /* @__PURE__ */ (() => | ||
50 | defineSharedStoreModel(GlobalSettingsBase, ProfileBase, ServiceBase))(); | ||
51 | |||
52 | /* | ||
53 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | ||
54 | Intentionally naming the type the same as the store definition. | ||
55 | */ | ||
56 | interface SharedStoreBase extends Instance<typeof SharedStoreBase> {} | ||
57 | |||
58 | export default SharedStoreBase; | ||
59 | |||
60 | export interface SharedStoreSnapshotIn | ||
61 | extends SnapshotIn<typeof SharedStoreBase> {} | ||
62 | |||
63 | export interface SharedStoreSnapshotOut | ||
64 | extends SnapshotOut<typeof SharedStoreBase> {} | ||
65 | |||
66 | export interface SharedStoreListener { | ||
67 | onSnapshot(snapshot: SharedStoreSnapshotIn): void; | ||
68 | |||
69 | onPatch(patches: IJsonPatch[]): void; | ||
70 | } | ||