diff options
-rw-r--r-- | packages/main/package.json | 3 | ||||
-rw-r--r-- | packages/main/src/controllers/ConfigController.ts | 105 | ||||
-rw-r--r-- | packages/main/src/controllers/MainController.ts (renamed from packages/main/src/services/NativeThemeService.ts) | 26 | ||||
-rw-r--r-- | packages/main/src/controllers/NativeThemeController.ts | 37 | ||||
-rw-r--r-- | packages/main/src/index.ts | 15 | ||||
-rw-r--r-- | packages/main/src/injector.ts | 39 | ||||
-rw-r--r-- | packages/main/src/services/ConfigPersistenceService.ts | 53 | ||||
-rw-r--r-- | packages/shared/src/stores/SharedStore.ts | 2 | ||||
-rw-r--r-- | yarn.lock | 8 |
9 files changed, 166 insertions, 122 deletions
diff --git a/packages/main/package.json b/packages/main/package.json index 48268fb..55bc663 100644 --- a/packages/main/package.json +++ b/packages/main/package.json | |||
@@ -17,7 +17,8 @@ | |||
17 | "lodash": "^4.17.21", | 17 | "lodash": "^4.17.21", |
18 | "mobx": "^6.3.10", | 18 | "mobx": "^6.3.10", |
19 | "mobx-state-tree": "^5.1.0", | 19 | "mobx-state-tree": "^5.1.0", |
20 | "ms": "^2.1.3" | 20 | "ms": "^2.1.3", |
21 | "typed-inject": "^3.0.1" | ||
21 | }, | 22 | }, |
22 | "devDependencies": { | 23 | "devDependencies": { |
23 | "@types/electron-devtools-installer": "^2.2.1", | 24 | "@types/electron-devtools-installer": "^2.2.1", |
diff --git a/packages/main/src/controllers/ConfigController.ts b/packages/main/src/controllers/ConfigController.ts index 6690548..a28746c 100644 --- a/packages/main/src/controllers/ConfigController.ts +++ b/packages/main/src/controllers/ConfigController.ts | |||
@@ -25,56 +25,62 @@ import { | |||
25 | IDisposer, | 25 | IDisposer, |
26 | onSnapshot, | 26 | onSnapshot, |
27 | } from 'mobx-state-tree'; | 27 | } from 'mobx-state-tree'; |
28 | import ms from 'ms'; | ||
29 | 28 | ||
30 | import { ConfigPersistenceService } from '../services/ConfigPersistenceService'; | 29 | import type { ConfigPersistenceService } from '../services/ConfigPersistenceService'; |
31 | import { Config, ConfigSnapshotOut } from '../stores/Config'; | 30 | import type { Config, ConfigSnapshotOut } from '../stores/Config'; |
32 | 31 | ||
33 | const DEFAULT_DEBOUNCE_TIME = ms('1s'); | 32 | export class ConfigController { |
33 | static inject = ['configPersistenceService', 'configDebounceTime'] as const; | ||
34 | 34 | ||
35 | class ConfigController { | 35 | private config: Config | null = null; |
36 | readonly #config: Config; | ||
37 | 36 | ||
38 | readonly #persistenceService: ConfigPersistenceService; | 37 | private onSnapshotDisposer: IDisposer | null = null; |
39 | 38 | ||
40 | readonly #onSnapshotDisposer: IDisposer; | 39 | private lastSnapshotOnDisk: ConfigSnapshotOut | null = null; |
41 | 40 | ||
42 | readonly #watcherDisposer: IDisposer; | 41 | private writingConfig: boolean = false; |
43 | 42 | ||
44 | #lastSnapshotOnDisk: ConfigSnapshotOut | null = null; | 43 | constructor( |
44 | private readonly persistenceService: ConfigPersistenceService, | ||
45 | private readonly debounceTime: number, | ||
46 | ) { | ||
47 | } | ||
45 | 48 | ||
46 | #writingConfig: boolean = false; | 49 | async initConfig(config: Config): Promise<void> { |
50 | this.config = config; | ||
47 | 51 | ||
48 | #configMTime: Date | null = null; | 52 | const foundConfig: boolean = await this.readConfig(); |
53 | if (!foundConfig) { | ||
54 | console.log('Creating new config file'); | ||
55 | try { | ||
56 | await this.writeConfig(); | ||
57 | } catch (err) { | ||
58 | console.error('Failed to initialize config'); | ||
59 | } | ||
60 | } | ||
49 | 61 | ||
50 | constructor( | 62 | this.onSnapshotDisposer = onSnapshot(this.config, debounce((snapshot) => { |
51 | config: Config, | ||
52 | persistenceService: ConfigPersistenceService, | ||
53 | debounceTime: number, | ||
54 | ) { | ||
55 | this.#config = config; | ||
56 | this.#persistenceService = persistenceService; | ||
57 | this.#onSnapshotDisposer = onSnapshot(this.#config, debounce((snapshot) => { | ||
58 | // We can compare snapshots by reference, since it is only recreated on store changes. | 63 | // We can compare snapshots by reference, since it is only recreated on store changes. |
59 | if (this.#lastSnapshotOnDisk !== snapshot) { | 64 | if (this.lastSnapshotOnDisk !== snapshot) { |
60 | this.#writeConfig().catch((err) => { | 65 | this.writeConfig().catch((err) => { |
61 | console.log('Failed to write config on config change', err); | 66 | console.log('Failed to write config on config change', err); |
62 | }) | 67 | }) |
63 | } | 68 | } |
64 | }, debounceTime)); | 69 | }, this.debounceTime)); |
65 | this.#watcherDisposer = this.#persistenceService.watchConfig(async (mtime) => { | 70 | |
66 | if (!this.#writingConfig && (this.#configMTime === null || mtime > this.#configMTime)) { | 71 | this.persistenceService.watchConfig(async () => { |
67 | await this.#readConfig(); | 72 | if (!this.writingConfig) { |
73 | await this.readConfig(); | ||
68 | } | 74 | } |
69 | }, debounceTime); | 75 | }, this.debounceTime); |
70 | } | 76 | } |
71 | 77 | ||
72 | async #readConfig(): Promise<boolean> { | 78 | private async readConfig(): Promise<boolean> { |
73 | const result = await this.#persistenceService.readConfig(); | 79 | const result = await this.persistenceService.readConfig(); |
74 | if (result.found) { | 80 | if (result.found) { |
75 | try { | 81 | try { |
76 | applySnapshot(this.#config, result.data); | 82 | applySnapshot(this.config!, result.data); |
77 | this.#lastSnapshotOnDisk = getSnapshot(this.#config); | 83 | this.lastSnapshotOnDisk = getSnapshot(this.config!); |
78 | console.log('Loaded config'); | 84 | console.log('Loaded config'); |
79 | } catch (err) { | 85 | } catch (err) { |
80 | console.error('Failed to read config', result.data, err); | 86 | console.error('Failed to read config', result.data, err); |
@@ -83,42 +89,19 @@ class ConfigController { | |||
83 | return result.found; | 89 | return result.found; |
84 | } | 90 | } |
85 | 91 | ||
86 | async #writeConfig(): Promise<void> { | 92 | private async writeConfig(): Promise<void> { |
87 | const snapshot = getSnapshot(this.#config); | 93 | const snapshot = getSnapshot(this.config!); |
88 | this.#writingConfig = true; | 94 | this.writingConfig = true; |
89 | try { | 95 | try { |
90 | this.#configMTime = await this.#persistenceService.writeConfig(snapshot); | 96 | await this.persistenceService.writeConfig(snapshot); |
91 | this.#lastSnapshotOnDisk = snapshot; | 97 | this.lastSnapshotOnDisk = snapshot; |
92 | console.log('Wrote config'); | 98 | console.log('Wrote config'); |
93 | } finally { | 99 | } finally { |
94 | this.#writingConfig = false; | 100 | this.writingConfig = false; |
95 | } | ||
96 | } | ||
97 | |||
98 | async initConfig(): Promise<void> { | ||
99 | const foundConfig: boolean = await this.#readConfig(); | ||
100 | if (!foundConfig) { | ||
101 | console.log('Creating new config file'); | ||
102 | try { | ||
103 | await this.#writeConfig(); | ||
104 | } catch (err) { | ||
105 | console.error('Failed to initialize config'); | ||
106 | } | ||
107 | } | 101 | } |
108 | } | 102 | } |
109 | 103 | ||
110 | dispose(): void { | 104 | dispose(): void { |
111 | this.#onSnapshotDisposer(); | 105 | this.onSnapshotDisposer?.(); |
112 | this.#watcherDisposer(); | ||
113 | } | 106 | } |
114 | } | 107 | } |
115 | |||
116 | export async function initConfig( | ||
117 | config: Config, | ||
118 | persistenceService: ConfigPersistenceService, | ||
119 | debounceTime: number = DEFAULT_DEBOUNCE_TIME, | ||
120 | ): Promise<IDisposer> { | ||
121 | const controller = new ConfigController(config, persistenceService, debounceTime); | ||
122 | await controller.initConfig(); | ||
123 | return () => controller.dispose(); | ||
124 | } | ||
diff --git a/packages/main/src/services/NativeThemeService.ts b/packages/main/src/controllers/MainController.ts index 7a26c3c..6b97330 100644 --- a/packages/main/src/services/NativeThemeService.ts +++ b/packages/main/src/controllers/MainController.ts | |||
@@ -18,21 +18,21 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { nativeTheme } from 'electron'; | 21 | import type { ConfigController } from './ConfigController'; |
22 | import type { IDisposer } from 'mobx-state-tree'; | 22 | import type { NativeThemeController } from './NativeThemeController'; |
23 | import type { ThemeSource } from '@sophie/shared'; | 23 | import type { MainStore } from '../stores/MainStore'; |
24 | 24 | ||
25 | export class NativeThemeService { | 25 | export class MainController { |
26 | setThemeSource(themeSource: ThemeSource): void { | 26 | static inject = ['configController', 'nativeThemeController'] as const; |
27 | nativeTheme.themeSource = themeSource; | 27 | |
28 | constructor( | ||
29 | private readonly configController: ConfigController, | ||
30 | private readonly nativeThemeController: NativeThemeController, | ||
31 | ) { | ||
28 | } | 32 | } |
29 | 33 | ||
30 | onShouldUseDarkColorsUpdated(callback: (shouldUseDarkColors: boolean) => void): IDisposer { | 34 | async connect(store: MainStore): Promise<void> { |
31 | const wrappedCallback = () => { | 35 | await this.configController.initConfig(store.config); |
32 | callback(nativeTheme.shouldUseDarkColors); | 36 | this.nativeThemeController.connect(store); |
33 | }; | ||
34 | wrappedCallback(); | ||
35 | nativeTheme.on('updated', wrappedCallback); | ||
36 | return () => nativeTheme.off('updated', wrappedCallback); | ||
37 | } | 37 | } |
38 | } | 38 | } |
diff --git a/packages/main/src/controllers/NativeThemeController.ts b/packages/main/src/controllers/NativeThemeController.ts index 07a3292..a50d41e 100644 --- a/packages/main/src/controllers/NativeThemeController.ts +++ b/packages/main/src/controllers/NativeThemeController.ts | |||
@@ -18,21 +18,32 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { nativeTheme } from 'electron'; | ||
21 | import { autorun } from 'mobx'; | 22 | import { autorun } from 'mobx'; |
22 | import type { IDisposer } from 'mobx-state-tree'; | 23 | import { IDisposer } from 'mobx-state-tree'; |
23 | 24 | ||
24 | import type { NativeThemeService } from '../services/NativeThemeService'; | ||
25 | import type { MainStore } from '../stores/MainStore'; | 25 | import type { MainStore } from '../stores/MainStore'; |
26 | 26 | ||
27 | export function initNativeTheme(store: MainStore, service: NativeThemeService): IDisposer { | 27 | export class NativeThemeController { |
28 | const themeSourceReactionDisposer = autorun(() => { | 28 | private autorunDisposer: IDisposer | null = null; |
29 | service.setThemeSource(store.config.themeSource); | 29 | |
30 | }); | 30 | private shouldUseDarkColorsListener: (() => void) | null = null; |
31 | const onShouldUseDarkColorsUpdatedDisposer = service.onShouldUseDarkColorsUpdated( | 31 | |
32 | store.setShouldUseDarkColors, | 32 | connect(store: MainStore): void { |
33 | ); | 33 | this.autorunDisposer = autorun(() => { |
34 | return () => { | 34 | nativeTheme.themeSource = store.config.themeSource; |
35 | onShouldUseDarkColorsUpdatedDisposer(); | 35 | }); |
36 | themeSourceReactionDisposer(); | 36 | store.setShouldUseDarkColors(nativeTheme.shouldUseDarkColors); |
37 | }; | 37 | this.shouldUseDarkColorsListener = () => { |
38 | store.setShouldUseDarkColors(nativeTheme.shouldUseDarkColors); | ||
39 | }; | ||
40 | nativeTheme.on('updated', this.shouldUseDarkColorsListener); | ||
41 | } | ||
42 | |||
43 | dispose(): void { | ||
44 | if (this.shouldUseDarkColorsListener !== null) { | ||
45 | nativeTheme.off('updated', this.shouldUseDarkColorsListener); | ||
46 | } | ||
47 | this.autorunDisposer?.(); | ||
48 | } | ||
38 | } | 49 | } |
diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts index 7aa3ee9..8eb0803 100644 --- a/packages/main/src/index.ts +++ b/packages/main/src/index.ts | |||
@@ -45,10 +45,7 @@ import { | |||
45 | installDevToolsExtensions, | 45 | installDevToolsExtensions, |
46 | openDevToolsWhenReady, | 46 | openDevToolsWhenReady, |
47 | } from './devTools'; | 47 | } from './devTools'; |
48 | import { initConfig } from './controllers/ConfigController'; | 48 | import { injector } from './injector'; |
49 | import { initNativeTheme } from './controllers/NativeThemeController'; | ||
50 | import { ConfigPersistenceService } from './services/ConfigPersistenceService'; | ||
51 | import { NativeThemeService } from './services/NativeThemeService'; | ||
52 | import { createMainStore } from './stores/MainStore'; | 49 | import { createMainStore } from './stores/MainStore'; |
53 | 50 | ||
54 | const isDevelopment = import.meta.env.MODE === 'development'; | 51 | const isDevelopment = import.meta.env.MODE === 'development'; |
@@ -108,12 +105,10 @@ let mainWindow: BrowserWindow | null = null; | |||
108 | 105 | ||
109 | const store = createMainStore(); | 106 | const store = createMainStore(); |
110 | 107 | ||
111 | initConfig( | 108 | const controller = injector.resolve('mainController'); |
112 | store.config, | 109 | controller.connect(store).catch((err) => { |
113 | new ConfigPersistenceService(app.getPath('userData'), 'config.json5'), | 110 | console.log('Error while initializing app', err); |
114 | ).then(() => { | 111 | }); |
115 | initNativeTheme(store, new NativeThemeService()); | ||
116 | }).catch((err) => console.error(err)); | ||
117 | 112 | ||
118 | const rendererBaseUrl = getResourceUrl('../renderer/'); | 113 | const rendererBaseUrl = getResourceUrl('../renderer/'); |
119 | function shouldCancelMainWindowRequest(url: string, method: string): boolean { | 114 | function shouldCancelMainWindowRequest(url: string, method: string): boolean { |
diff --git a/packages/main/src/injector.ts b/packages/main/src/injector.ts new file mode 100644 index 0000000..2c05c85 --- /dev/null +++ b/packages/main/src/injector.ts | |||
@@ -0,0 +1,39 @@ | |||
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 { app } from 'electron'; | ||
22 | import ms from 'ms'; | ||
23 | import { createInjector, Injector } from 'typed-inject'; | ||
24 | |||
25 | import { ConfigController } from './controllers/ConfigController'; | ||
26 | import { MainController } from './controllers/MainController'; | ||
27 | import { NativeThemeController } from './controllers/NativeThemeController'; | ||
28 | import { ConfigPersistenceService } from './services/ConfigPersistenceService'; | ||
29 | |||
30 | export const injector: Injector<{ | ||
31 | 'mainController': MainController, | ||
32 | }> = createInjector() | ||
33 | .provideFactory('userDataDir', () => app.getPath('userData')) | ||
34 | .provideValue('configFileName', 'config.json5') | ||
35 | .provideValue('configDebounceTime', ms('1s')) | ||
36 | .provideClass('configPersistenceService', ConfigPersistenceService) | ||
37 | .provideClass('configController', ConfigController) | ||
38 | .provideClass('nativeThemeController', NativeThemeController) | ||
39 | .provideClass('mainController', MainController); | ||
diff --git a/packages/main/src/services/ConfigPersistenceService.ts b/packages/main/src/services/ConfigPersistenceService.ts index 85b0088..61123d9 100644 --- a/packages/main/src/services/ConfigPersistenceService.ts +++ b/packages/main/src/services/ConfigPersistenceService.ts | |||
@@ -17,12 +17,10 @@ | |||
17 | * | 17 | * |
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | import { FSWatcher, watch } from 'fs'; | |
21 | import { watch } from 'fs'; | ||
22 | import { readFile, stat, writeFile } from 'fs/promises'; | 21 | import { readFile, stat, writeFile } from 'fs/promises'; |
23 | import JSON5 from 'json5'; | 22 | import JSON5 from 'json5'; |
24 | import { throttle } from 'lodash'; | 23 | import { throttle } from 'lodash'; |
25 | import { IDisposer } from 'mobx-state-tree'; | ||
26 | import { join } from 'path'; | 24 | import { join } from 'path'; |
27 | 25 | ||
28 | import type { ConfigSnapshotOut } from '../stores/Config'; | 26 | import type { ConfigSnapshotOut } from '../stores/Config'; |
@@ -30,25 +28,26 @@ import type { ConfigSnapshotOut } from '../stores/Config'; | |||
30 | export type ReadConfigResult = { found: true; data: unknown; } | { found: false; }; | 28 | export type ReadConfigResult = { found: true; data: unknown; } | { found: false; }; |
31 | 29 | ||
32 | export class ConfigPersistenceService { | 30 | export class ConfigPersistenceService { |
33 | readonly #userDataDir: string; | 31 | static inject = ['userDataDir', 'configFileName'] as const; |
32 | |||
33 | private readonly configFilePath: string; | ||
34 | 34 | ||
35 | readonly #configFileName: string; | 35 | private timeLastWritten: Date | null = null; |
36 | 36 | ||
37 | readonly #configFilePath: string; | 37 | private watcher: FSWatcher | null = null; |
38 | 38 | ||
39 | constructor( | 39 | constructor( |
40 | userDataDir: string, | 40 | private readonly userDataDir: string, |
41 | configFileName: string, | 41 | private readonly configFileName: string, |
42 | ) { | 42 | ) { |
43 | this.#userDataDir = userDataDir; | 43 | this.configFileName = configFileName; |
44 | this.#configFileName = configFileName; | 44 | this.configFilePath = join(this.userDataDir, this.configFileName); |
45 | this.#configFilePath = join(this.#userDataDir, this.#configFileName); | ||
46 | } | 45 | } |
47 | 46 | ||
48 | async readConfig(): Promise<ReadConfigResult> { | 47 | async readConfig(): Promise<ReadConfigResult> { |
49 | let configStr; | 48 | let configStr; |
50 | try { | 49 | try { |
51 | configStr = await readFile(this.#configFilePath, 'utf8'); | 50 | configStr = await readFile(this.configFilePath, 'utf8'); |
52 | } catch (err) { | 51 | } catch (err) { |
53 | if ((err as NodeJS.ErrnoException).code === 'ENOENT') { | 52 | if ((err as NodeJS.ErrnoException).code === 'ENOENT') { |
54 | return { found: false }; | 53 | return { found: false }; |
@@ -61,20 +60,24 @@ export class ConfigPersistenceService { | |||
61 | }; | 60 | }; |
62 | } | 61 | } |
63 | 62 | ||
64 | async writeConfig(configSnapshot: ConfigSnapshotOut): Promise<Date> { | 63 | async writeConfig(configSnapshot: ConfigSnapshotOut): Promise<void> { |
65 | const configJson = JSON5.stringify(configSnapshot, { | 64 | const configJson = JSON5.stringify(configSnapshot, { |
66 | space: 2, | 65 | space: 2, |
67 | }); | 66 | }); |
68 | await writeFile(this.#configFilePath, configJson, 'utf8'); | 67 | await writeFile(this.configFilePath, configJson, 'utf8'); |
69 | const { mtime } = await stat(this.#configFilePath); | 68 | const stats = await stat(this.configFilePath); |
70 | return mtime; | 69 | this.timeLastWritten = stats.mtime; |
71 | } | 70 | } |
72 | 71 | ||
73 | watchConfig(callback: (mtime: Date) => Promise<void>, throttleMs: number): IDisposer { | 72 | watchConfig(callback: () => Promise<void>, throttleMs: number): void { |
73 | if (this.watcher !== null) { | ||
74 | throw new Error('watchConfig was already called'); | ||
75 | } | ||
76 | |||
74 | const configChanged = throttle(async () => { | 77 | const configChanged = throttle(async () => { |
75 | let mtime: Date; | 78 | let mtime: Date; |
76 | try { | 79 | try { |
77 | const stats = await stat(this.#configFilePath); | 80 | const stats = await stat(this.configFilePath); |
78 | mtime = stats.mtime; | 81 | mtime = stats.mtime; |
79 | } catch (err) { | 82 | } catch (err) { |
80 | if ((err as NodeJS.ErrnoException).code === 'ENOENT') { | 83 | if ((err as NodeJS.ErrnoException).code === 'ENOENT') { |
@@ -82,22 +85,26 @@ export class ConfigPersistenceService { | |||
82 | } | 85 | } |
83 | throw err; | 86 | throw err; |
84 | } | 87 | } |
85 | return callback(mtime); | 88 | if (this.timeLastWritten === null || mtime > this.timeLastWritten) { |
89 | return callback(); | ||
90 | } | ||
86 | }, throttleMs); | 91 | }, throttleMs); |
87 | 92 | ||
88 | const watcher = watch(this.#userDataDir, { | 93 | this.watcher = watch(this.userDataDir, { |
89 | persistent: false, | 94 | persistent: false, |
90 | }); | 95 | }); |
91 | 96 | ||
92 | watcher.on('change', (eventType, filename) => { | 97 | this.watcher.on('change', (eventType, filename) => { |
93 | if (eventType === 'change' | 98 | if (eventType === 'change' |
94 | && (filename === this.#configFileName || filename === null)) { | 99 | && (filename === this.configFileName || filename === null)) { |
95 | configChanged()?.catch((err) => { | 100 | configChanged()?.catch((err) => { |
96 | console.log('Unhandled error while listening for config changes', err); | 101 | console.log('Unhandled error while listening for config changes', err); |
97 | }); | 102 | }); |
98 | } | 103 | } |
99 | }); | 104 | }); |
105 | } | ||
100 | 106 | ||
101 | return () => watcher.close(); | 107 | dispose(): void { |
108 | this.watcher?.close(); | ||
102 | } | 109 | } |
103 | } | 110 | } |
diff --git a/packages/shared/src/stores/SharedStore.ts b/packages/shared/src/stores/SharedStore.ts index cfff6d5..c6c3ddc 100644 --- a/packages/shared/src/stores/SharedStore.ts +++ b/packages/shared/src/stores/SharedStore.ts | |||
@@ -30,7 +30,7 @@ import { config } from './Config'; | |||
30 | 30 | ||
31 | export const sharedStore = types.model('SharedStore', { | 31 | export const sharedStore = types.model('SharedStore', { |
32 | config: types.optional(config, {}), | 32 | config: types.optional(config, {}), |
33 | shouldUseDarkColors: true, | 33 | shouldUseDarkColors: false, |
34 | }); | 34 | }); |
35 | 35 | ||
36 | export interface SharedStore extends Instance<typeof sharedStore> {} | 36 | export interface SharedStore extends Instance<typeof sharedStore> {} |
@@ -1238,6 +1238,7 @@ __metadata: | |||
1238 | mobx-state-tree: ^5.1.0 | 1238 | mobx-state-tree: ^5.1.0 |
1239 | ms: ^2.1.3 | 1239 | ms: ^2.1.3 |
1240 | rimraf: ^3.0.2 | 1240 | rimraf: ^3.0.2 |
1241 | typed-inject: ^3.0.1 | ||
1241 | typescript: ^4.5.4 | 1242 | typescript: ^4.5.4 |
1242 | vite: ^2.7.7 | 1243 | vite: ^2.7.7 |
1243 | languageName: unknown | 1244 | languageName: unknown |
@@ -7377,6 +7378,13 @@ __metadata: | |||
7377 | languageName: node | 7378 | languageName: node |
7378 | linkType: hard | 7379 | linkType: hard |
7379 | 7380 | ||
7381 | "typed-inject@npm:^3.0.1": | ||
7382 | version: 3.0.1 | ||
7383 | resolution: "typed-inject@npm:3.0.1" | ||
7384 | checksum: a400797a42951bc46a38873e9be40fe90fdba6ae3362e2d4da4972c4ec48e962ff167bc5f090ca42dc20bb3f6063cd07a80426df520c64dc9e94d1e89ff4779e | ||
7385 | languageName: node | ||
7386 | linkType: hard | ||
7387 | |||
7380 | "typedarray-to-buffer@npm:^3.1.5": | 7388 | "typedarray-to-buffer@npm:^3.1.5": |
7381 | version: 3.1.5 | 7389 | version: 3.1.5 |
7382 | resolution: "typedarray-to-buffer@npm:3.1.5" | 7390 | resolution: "typedarray-to-buffer@npm:3.1.5" |