aboutsummaryrefslogtreecommitdiffstats
path: root/packages/main/src/stores/MainStore.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/main/src/stores/MainStore.ts')
-rw-r--r--packages/main/src/stores/MainStore.ts127
1 files changed, 91 insertions, 36 deletions
diff --git a/packages/main/src/stores/MainStore.ts b/packages/main/src/stores/MainStore.ts
index 9ac56f4..1abd20c 100644
--- a/packages/main/src/stores/MainStore.ts
+++ b/packages/main/src/stores/MainStore.ts
@@ -18,31 +18,27 @@
18 * SPDX-License-Identifier: AGPL-3.0-only 18 * SPDX-License-Identifier: AGPL-3.0-only
19 */ 19 */
20 20
21import type { Action, BrowserViewBounds } from '@sophie/shared'; 21import type { Action } from '@sophie/shared';
22import { applySnapshot, Instance, types } from 'mobx-state-tree'; 22import type { ResourceKey } from 'i18next';
23import { flow, Instance, types } from 'mobx-state-tree';
23 24
24import type { MainWindow } from '../infrastructure/electron/types'; 25import type I18nStore from '../i18n/I18nStore.js';
25import { getLogger } from '../utils/log'; 26import type { UseTranslationResult } from '../i18n/I18nStore.js';
27import type { MainWindow } from '../infrastructure/electron/types.js';
28import getLogger from '../utils/getLogger.js';
26 29
27import GlobalSettings from './GlobalSettings'; 30import GlobalSettings from './GlobalSettings.js';
28import Profile from './Profile'; 31import { getEnv } from './MainEnv.js';
29import Service from './Service'; 32import Profile from './Profile.js';
30import SharedStore from './SharedStore'; 33import Service from './Service.js';
34import SharedStore from './SharedStore.js';
31 35
32const log = getLogger('MainStore'); 36const log = getLogger('MainStore');
33 37
34const MainStore = types 38const MainStore = types
35 .model('MainStore', { 39 .model('MainStore', {
36 browserViewBounds: types.optional(
37 types.model('BrowserViewBounds', {
38 x: 0,
39 y: 0,
40 width: 0,
41 height: 0,
42 }),
43 {},
44 ),
45 shared: types.optional(SharedStore, {}), 40 shared: types.optional(SharedStore, {}),
41 i18n: types.frozen<I18nStore | undefined>(),
46 }) 42 })
47 .views((self) => ({ 43 .views((self) => ({
48 get settings(): GlobalSettings { 44 get settings(): GlobalSettings {
@@ -56,10 +52,19 @@ const MainStore = types
56 }, 52 },
57 get visibleService(): Service | undefined { 53 get visibleService(): Service | undefined {
58 const { selectedService } = this.settings; 54 const { selectedService } = this.settings;
59 return selectedService !== undefined && selectedService.shouldBeLoaded 55 return selectedService !== undefined && selectedService.shouldBeVisible
60 ? selectedService 56 ? selectedService
61 : undefined; 57 : undefined;
62 }, 58 },
59 useTranslation(ns?: string): UseTranslationResult {
60 return self.i18n?.useTranslation(ns) ?? { ready: false };
61 },
62 getTranslation(language: string, namespace: string): Promise<ResourceKey> {
63 if (self.i18n === undefined) {
64 throw new Error('i18next has not been set');
65 }
66 return self.i18n.getTranslation(language, namespace);
67 },
63 })) 68 }))
64 .volatile( 69 .volatile(
65 (): { 70 (): {
@@ -69,34 +74,88 @@ const MainStore = types
69 }), 74 }),
70 ) 75 )
71 .actions((self) => ({ 76 .actions((self) => ({
72 setBrowserViewBounds(bounds: BrowserViewBounds): void { 77 setMainWindow(mainWindow: MainWindow | undefined): void {
73 applySnapshot(self.browserViewBounds, bounds); 78 self.mainWindow = mainWindow;
79 },
80 openWebpageInBrowser() {
81 getEnv(self).openURLInExternalBrowser(
82 'https://gitlab.com/say-hi-to-sophie/shophie',
83 );
84 },
85 openAboutDialog() {
86 getEnv(self).openAboutDialog();
87 },
88 beforeDestroy(): void {
89 self.mainWindow?.dispose();
90 },
91 setI18n(i18n: I18nStore): void {
92 self.i18n = i18n;
93 },
94 addMissingTranslation(
95 languages: string[],
96 namespace: string,
97 key: string,
98 value: string,
99 ): void {
100 self.i18n?.addMissingTranslation(languages, namespace, key, value);
74 }, 101 },
102 reloadTranslations: flow(function* reloadTranslations() {
103 if (self.i18n !== undefined) {
104 yield self.i18n.reloadTranslations();
105 self.mainWindow?.reloadTranslations();
106 }
107 }),
108 }))
109 .actions((self) => ({
75 dispatch(action: Action): void { 110 dispatch(action: Action): void {
76 switch (action.action) { 111 switch (action.action) {
77 case 'reload-all-services':
78 // TODO
79 break;
80 case 'set-browser-view-bounds':
81 this.setBrowserViewBounds(action.browserViewBounds);
82 break;
83 case 'set-selected-service-id': 112 case 'set-selected-service-id':
84 self.settings.setSelectedServiceId(action.serviceId); 113 self.settings.setSelectedServiceId(action.serviceId);
85 break; 114 break;
86 case 'set-theme-source': 115 case 'set-theme-source':
87 self.settings.setThemeSource(action.themeSource); 116 self.settings.setThemeSource(action.themeSource);
88 break; 117 break;
118 case 'set-show-location-bar':
119 self.settings.setShowLocationBar(action.showLocationBar);
120 break;
121 case 'reload-all-services':
122 self.services.forEach((service) => service.reload());
123 break;
124 case 'reload-all-translations':
125 if (self.i18n !== undefined) {
126 self.reloadTranslations().catch((error) => {
127 log.error('Failed to reload translations', error);
128 });
129 }
130 break;
131 case 'add-missing-translation':
132 self.addMissingTranslation(
133 action.languages,
134 action.namespace,
135 action.key,
136 action.value,
137 );
138 break;
139 case 'dispatch-service-action': {
140 const { serviceId, serviceAction } = action;
141 const service = self.shared.servicesById.get(serviceId);
142 if (service === undefined) {
143 log.error(
144 'No such service',
145 serviceId,
146 'to dispatch action',
147 serviceAction,
148 );
149 } else {
150 service.dispatch(serviceAction);
151 }
152 break;
153 }
89 default: 154 default:
90 log.error('Unknown action to dispatch', action); 155 log.error('Unknown action to dispatch', action);
91 break; 156 break;
92 } 157 }
93 }, 158 },
94 setMainWindow(mainWindow: MainWindow | undefined): void {
95 self.mainWindow = mainWindow;
96 },
97 beforeDestroy(): void {
98 self.mainWindow?.dispose();
99 },
100 })); 159 }));
101 160
102/* 161/*
@@ -106,7 +165,3 @@ const MainStore = types
106interface MainStore extends Instance<typeof MainStore> {} 165interface MainStore extends Instance<typeof MainStore> {}
107 166
108export default MainStore; 167export default MainStore;
109
110export function createMainStore(): MainStore {
111 return MainStore.create();
112}