diff options
author | Kristóf Marussy <kristof@marussy.com> | 2022-01-09 20:33:53 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2022-01-09 20:33:53 +0100 |
commit | d85f09cbed5f3d2501f791e689011ae127df1cbb (patch) | |
tree | 0ed5be55dd5d3dec1d51eb60e7ff229274030a57 /packages/main/src | |
parent | build: Disable single-run eslint-typescript (diff) | |
download | sophie-d85f09cbed5f3d2501f791e689011ae127df1cbb.tar.gz sophie-d85f09cbed5f3d2501f791e689011ae127df1cbb.tar.zst sophie-d85f09cbed5f3d2501f791e689011ae127df1cbb.zip |
build: Add prettier
eslint will also enforce prettier rules, so there is no need to call
prettier separately in CI.
Signed-off-by: Kristóf Marussy <kristof@marussy.com>
Diffstat (limited to 'packages/main/src')
-rw-r--r-- | packages/main/src/controllers/__tests__/initConfig.spec.ts | 20 | ||||
-rw-r--r-- | packages/main/src/controllers/__tests__/initNativeTheme.spec.ts | 8 | ||||
-rw-r--r-- | packages/main/src/controllers/initConfig.ts | 21 | ||||
-rw-r--r-- | packages/main/src/devTools.ts | 16 | ||||
-rw-r--r-- | packages/main/src/index.ts | 108 | ||||
-rw-r--r-- | packages/main/src/init.ts | 9 | ||||
-rw-r--r-- | packages/main/src/services/ConfigPersistenceService.ts | 4 | ||||
-rw-r--r-- | packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts | 22 | ||||
-rw-r--r-- | packages/main/src/stores/MainStore.ts | 46 | ||||
-rw-r--r-- | packages/main/src/stores/SharedStore.ts | 5 | ||||
-rw-r--r-- | packages/main/src/utils/log.ts | 7 |
11 files changed, 161 insertions, 105 deletions
diff --git a/packages/main/src/controllers/__tests__/initConfig.spec.ts b/packages/main/src/controllers/__tests__/initConfig.spec.ts index e386a07..7b6d6ab 100644 --- a/packages/main/src/controllers/__tests__/initConfig.spec.ts +++ b/packages/main/src/controllers/__tests__/initConfig.spec.ts | |||
@@ -60,8 +60,12 @@ describe('when initializing', () => { | |||
60 | }); | 60 | }); |
61 | 61 | ||
62 | it('should bail if there is an an error creating the config file', async () => { | 62 | it('should bail if there is an an error creating the config file', async () => { |
63 | mocked(persistenceService.writeConfig).mockRejectedValue(new Error('boo')); | 63 | mocked(persistenceService.writeConfig).mockRejectedValue( |
64 | await expect(() => initConfig(config, persistenceService)).rejects.toBeInstanceOf(Error); | 64 | new Error('boo'), |
65 | ); | ||
66 | await expect(() => | ||
67 | initConfig(config, persistenceService), | ||
68 | ).rejects.toBeInstanceOf(Error); | ||
65 | }); | 69 | }); |
66 | }); | 70 | }); |
67 | 71 | ||
@@ -85,7 +89,9 @@ describe('when initializing', () => { | |||
85 | mocked(persistenceService.watchConfig).mockImplementationOnce(() => { | 89 | mocked(persistenceService.watchConfig).mockImplementationOnce(() => { |
86 | throw new Error('boo'); | 90 | throw new Error('boo'); |
87 | }); | 91 | }); |
88 | await expect(() => initConfig(config, persistenceService)).rejects.toBeInstanceOf(Error); | 92 | await expect(() => |
93 | initConfig(config, persistenceService), | ||
94 | ).rejects.toBeInstanceOf(Error); | ||
89 | }); | 95 | }); |
90 | }); | 96 | }); |
91 | 97 | ||
@@ -102,7 +108,9 @@ describe('when initializing', () => { | |||
102 | 108 | ||
103 | it('should bail if it cannot determine whether there is a config file', async () => { | 109 | it('should bail if it cannot determine whether there is a config file', async () => { |
104 | mocked(persistenceService.readConfig).mockRejectedValue(new Error('boo')); | 110 | mocked(persistenceService.readConfig).mockRejectedValue(new Error('boo')); |
105 | await expect(() => initConfig(config, persistenceService)).rejects.toBeInstanceOf(Error); | 111 | await expect(() => |
112 | initConfig(config, persistenceService), | ||
113 | ).rejects.toBeInstanceOf(Error); | ||
106 | }); | 114 | }); |
107 | }); | 115 | }); |
108 | 116 | ||
@@ -118,7 +126,9 @@ describe('when it has loaded the config', () => { | |||
118 | }); | 126 | }); |
119 | mocked(persistenceService.watchConfig).mockReturnValueOnce(watcherDisposer); | 127 | mocked(persistenceService.watchConfig).mockReturnValueOnce(watcherDisposer); |
120 | sutDisposer = await initConfig(config, persistenceService, throttleMs); | 128 | sutDisposer = await initConfig(config, persistenceService, throttleMs); |
121 | [[configChangedCallback]] = mocked(persistenceService.watchConfig).mock.calls; | 129 | [[configChangedCallback]] = mocked( |
130 | persistenceService.watchConfig, | ||
131 | ).mock.calls; | ||
122 | jest.resetAllMocks(); | 132 | jest.resetAllMocks(); |
123 | }); | 133 | }); |
124 | 134 | ||
diff --git a/packages/main/src/controllers/__tests__/initNativeTheme.spec.ts b/packages/main/src/controllers/__tests__/initNativeTheme.spec.ts index bd33f48..d4068af 100644 --- a/packages/main/src/controllers/__tests__/initNativeTheme.spec.ts +++ b/packages/main/src/controllers/__tests__/initNativeTheme.spec.ts | |||
@@ -58,14 +58,18 @@ it('should synchronize themeSource changes to the nativeTheme', () => { | |||
58 | }); | 58 | }); |
59 | 59 | ||
60 | it('should synchronize shouldUseDarkColors changes to the store', () => { | 60 | it('should synchronize shouldUseDarkColors changes to the store', () => { |
61 | const listener = mocked(nativeTheme.on).mock.calls.find(([event]) => event === 'updated')![1]; | 61 | const listener = mocked(nativeTheme.on).mock.calls.find( |
62 | ([event]) => event === 'updated', | ||
63 | )![1]; | ||
62 | shouldUseDarkColors = true; | 64 | shouldUseDarkColors = true; |
63 | listener(); | 65 | listener(); |
64 | expect(store.shared.shouldUseDarkColors).toBe(true); | 66 | expect(store.shared.shouldUseDarkColors).toBe(true); |
65 | }); | 67 | }); |
66 | 68 | ||
67 | it('should remove the listener on dispose', () => { | 69 | it('should remove the listener on dispose', () => { |
68 | const listener = mocked(nativeTheme.on).mock.calls.find(([event]) => event === 'updated')![1]; | 70 | const listener = mocked(nativeTheme.on).mock.calls.find( |
71 | ([event]) => event === 'updated', | ||
72 | )![1]; | ||
69 | disposeSut(); | 73 | disposeSut(); |
70 | expect(nativeTheme.off).toBeCalledWith('updated', listener); | 74 | expect(nativeTheme.off).toBeCalledWith('updated', listener); |
71 | }); | 75 | }); |
diff --git a/packages/main/src/controllers/initConfig.ts b/packages/main/src/controllers/initConfig.ts index 1d40762..e83b8da 100644 --- a/packages/main/src/controllers/initConfig.ts +++ b/packages/main/src/controllers/initConfig.ts | |||
@@ -59,20 +59,23 @@ export default async function initConfig( | |||
59 | lastSnapshotOnDisk = snapshot; | 59 | lastSnapshotOnDisk = snapshot; |
60 | } | 60 | } |
61 | 61 | ||
62 | if (!await readConfig()) { | 62 | if (!(await readConfig())) { |
63 | log.info('Config file was not found'); | 63 | log.info('Config file was not found'); |
64 | await writeConfig(); | 64 | await writeConfig(); |
65 | log.info('Created config file'); | 65 | log.info('Created config file'); |
66 | } | 66 | } |
67 | 67 | ||
68 | const disposeOnSnapshot = onSnapshot(config, debounce((snapshot) => { | 68 | const disposeOnSnapshot = onSnapshot( |
69 | // We can compare snapshots by reference, since it is only recreated on store changes. | 69 | config, |
70 | if (lastSnapshotOnDisk !== snapshot) { | 70 | debounce((snapshot) => { |
71 | writeConfig().catch((err) => { | 71 | // We can compare snapshots by reference, since it is only recreated on store changes. |
72 | log.error('Failed to write config on config change', err); | 72 | if (lastSnapshotOnDisk !== snapshot) { |
73 | }); | 73 | writeConfig().catch((err) => { |
74 | } | 74 | log.error('Failed to write config on config change', err); |
75 | }, debounceTime)); | 75 | }); |
76 | } | ||
77 | }, debounceTime), | ||
78 | ); | ||
76 | 79 | ||
77 | const disposeWatcher = persistenceService.watchConfig(async () => { | 80 | const disposeWatcher = persistenceService.watchConfig(async () => { |
78 | try { | 81 | try { |
diff --git a/packages/main/src/devTools.ts b/packages/main/src/devTools.ts index 0486c36..69f1514 100644 --- a/packages/main/src/devTools.ts +++ b/packages/main/src/devTools.ts | |||
@@ -52,18 +52,12 @@ export async function installDevToolsExtensions(): Promise<void> { | |||
52 | @typescript-eslint/no-var-requires | 52 | @typescript-eslint/no-var-requires |
53 | */ | 53 | */ |
54 | } = require('electron-devtools-installer') as typeof import('electron-devtools-installer'); | 54 | } = require('electron-devtools-installer') as typeof import('electron-devtools-installer'); |
55 | await installExtension( | 55 | await installExtension([REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS], { |
56 | [ | 56 | forceDownload: false, |
57 | REACT_DEVELOPER_TOOLS, | 57 | loadExtensionOptions: { |
58 | REDUX_DEVTOOLS, | 58 | allowFileAccess: true, |
59 | ], | ||
60 | { | ||
61 | forceDownload: false, | ||
62 | loadExtensionOptions: { | ||
63 | allowFileAccess: true, | ||
64 | }, | ||
65 | }, | 59 | }, |
66 | ); | 60 | }); |
67 | } | 61 | } |
68 | 62 | ||
69 | /** | 63 | /** |
diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts index bc10b4c..1f80e44 100644 --- a/packages/main/src/index.ts +++ b/packages/main/src/index.ts | |||
@@ -33,12 +33,7 @@ import { | |||
33 | MainToRendererIpcMessage, | 33 | MainToRendererIpcMessage, |
34 | RendererToMainIpcMessage, | 34 | RendererToMainIpcMessage, |
35 | } from '@sophie/shared'; | 35 | } from '@sophie/shared'; |
36 | import { | 36 | import { app, BrowserView, BrowserWindow, ipcMain } from 'electron'; |
37 | app, | ||
38 | BrowserView, | ||
39 | BrowserWindow, | ||
40 | ipcMain, | ||
41 | } from 'electron'; | ||
42 | import { ensureDirSync, readFile, readFileSync } from 'fs-extra'; | 37 | import { ensureDirSync, readFile, readFileSync } from 'fs-extra'; |
43 | import { autorun } from 'mobx'; | 38 | import { autorun } from 'mobx'; |
44 | import { getSnapshot, onPatch } from 'mobx-state-tree'; | 39 | import { getSnapshot, onPatch } from 'mobx-state-tree'; |
@@ -97,7 +92,9 @@ app.setAboutPanelOptions({ | |||
97 | `Node.js: ${process.versions.node}`, | 92 | `Node.js: ${process.versions.node}`, |
98 | `Platform: ${osName()}`, | 93 | `Platform: ${osName()}`, |
99 | `Arch: ${arch()}`, | 94 | `Arch: ${arch()}`, |
100 | `Build date: ${new Date(Number(import.meta.env.BUILD_DATE)).toLocaleString()}`, | 95 | `Build date: ${new Date( |
96 | Number(import.meta.env.BUILD_DATE), | ||
97 | ).toLocaleString()}`, | ||
101 | `Git SHA: ${import.meta.env.GIT_SHA}`, | 98 | `Git SHA: ${import.meta.env.GIT_SHA}`, |
102 | `Git branch: ${import.meta.env.GIT_BRANCH}`, | 99 | `Git branch: ${import.meta.env.GIT_BRANCH}`, |
103 | ].join('\n'), | 100 | ].join('\n'), |
@@ -123,11 +120,13 @@ const serviceInject: WebSource = { | |||
123 | let mainWindow: BrowserWindow | null = null; | 120 | let mainWindow: BrowserWindow | null = null; |
124 | 121 | ||
125 | const store = createMainStore(); | 122 | const store = createMainStore(); |
126 | init(store).then((disposeCompositionRoot) => { | 123 | init(store) |
127 | app.on('will-quit', disposeCompositionRoot); | 124 | .then((disposeCompositionRoot) => { |
128 | }).catch((err) => { | 125 | app.on('will-quit', disposeCompositionRoot); |
129 | log.log('Failed to initialize application', err); | 126 | }) |
130 | }); | 127 | .catch((err) => { |
128 | log.log('Failed to initialize application', err); | ||
129 | }); | ||
131 | 130 | ||
132 | const rendererBaseUrl = getResourceUrl('../renderer/'); | 131 | const rendererBaseUrl = getResourceUrl('../renderer/'); |
133 | function shouldCancelMainWindowRequest(url: string, method: string): boolean { | 132 | function shouldCancelMainWindowRequest(url: string, method: string): boolean { |
@@ -141,12 +140,20 @@ function shouldCancelMainWindowRequest(url: string, method: string): boolean { | |||
141 | return true; | 140 | return true; |
142 | } | 141 | } |
143 | if (isDevelopment) { | 142 | if (isDevelopment) { |
144 | if (DEVMODE_ALLOWED_URL_PREFIXES.some((prefix) => normalizedUrl.startsWith(prefix))) { | 143 | if ( |
144 | DEVMODE_ALLOWED_URL_PREFIXES.some((prefix) => | ||
145 | normalizedUrl.startsWith(prefix), | ||
146 | ) | ||
147 | ) { | ||
145 | return false; | 148 | return false; |
146 | } | 149 | } |
147 | if (import.meta.env.VITE_DEV_SERVER_URL !== undefined) { | 150 | if (import.meta.env.VITE_DEV_SERVER_URL !== undefined) { |
148 | const isHttp = normalizedUrl.startsWith(import.meta.env.VITE_DEV_SERVER_URL); | 151 | const isHttp = normalizedUrl.startsWith( |
149 | const isWs = normalizedUrl.startsWith(import.meta.env.VITE_DEV_SERVER_URL.replace(/^http:/, 'ws:')); | 152 | import.meta.env.VITE_DEV_SERVER_URL, |
153 | ); | ||
154 | const isWs = normalizedUrl.startsWith( | ||
155 | import.meta.env.VITE_DEV_SERVER_URL.replace(/^http:/, 'ws:'), | ||
156 | ); | ||
150 | return !isHttp && !isWs; | 157 | return !isHttp && !isWs; |
151 | } | 158 | } |
152 | } | 159 | } |
@@ -168,19 +175,24 @@ async function createWindow(): Promise<unknown> { | |||
168 | 175 | ||
169 | webContents.userAgent = originalUserAgent; | 176 | webContents.userAgent = originalUserAgent; |
170 | 177 | ||
171 | webContents.session.setPermissionRequestHandler((_webContents, _permission, callback) => { | 178 | webContents.session.setPermissionRequestHandler( |
172 | callback(false); | 179 | (_webContents, _permission, callback) => { |
173 | }); | 180 | callback(false); |
181 | }, | ||
182 | ); | ||
174 | 183 | ||
175 | webContents.session.webRequest.onBeforeRequest(({ url, method }, callback) => { | 184 | webContents.session.webRequest.onBeforeRequest( |
176 | callback({ | 185 | ({ url, method }, callback) => { |
177 | cancel: shouldCancelMainWindowRequest(url, method), | 186 | callback({ |
178 | }); | 187 | cancel: shouldCancelMainWindowRequest(url, method), |
179 | }); | 188 | }); |
189 | }, | ||
190 | ); | ||
180 | 191 | ||
181 | const pageUrl = (isDevelopment && import.meta.env.VITE_DEV_SERVER_URL !== undefined) | 192 | const pageUrl = |
182 | ? import.meta.env.VITE_DEV_SERVER_URL | 193 | isDevelopment && import.meta.env.VITE_DEV_SERVER_URL !== undefined |
183 | : getResourceUrl('../renderer/dist/index.html'); | 194 | ? import.meta.env.VITE_DEV_SERVER_URL |
195 | : getResourceUrl('../renderer/dist/index.html'); | ||
184 | 196 | ||
185 | webContents.on('will-navigate', (event, url) => { | 197 | webContents.on('will-navigate', (event, url) => { |
186 | if (url !== pageUrl) { | 198 | if (url !== pageUrl) { |
@@ -273,9 +285,8 @@ async function createWindow(): Promise<unknown> { | |||
273 | webContents.send(MainToRendererIpcMessage.SharedStorePatch, patch); | 285 | webContents.send(MainToRendererIpcMessage.SharedStorePatch, patch); |
274 | }); | 286 | }); |
275 | 287 | ||
276 | ipcMain.handle( | 288 | ipcMain.handle(ServiceToMainIpcMessage.ApiExposedInMainWorld, (event) => |
277 | ServiceToMainIpcMessage.ApiExposedInMainWorld, | 289 | event.sender.id === browserView.webContents.id ? serviceInject : null, |
278 | (event) => (event.sender.id === browserView.webContents.id ? serviceInject : null), | ||
279 | ); | 290 | ); |
280 | 291 | ||
281 | browserView.webContents.on('ipc-message', (_event, channel, ...args) => { | 292 | browserView.webContents.on('ipc-message', (_event, channel, ...args) => { |
@@ -305,7 +316,9 @@ async function createWindow(): Promise<unknown> { | |||
305 | 316 | ||
306 | browserView.webContents.session.webRequest.onBeforeSendHeaders( | 317 | browserView.webContents.session.webRequest.onBeforeSendHeaders( |
307 | ({ url, requestHeaders }, callback) => { | 318 | ({ url, requestHeaders }, callback) => { |
308 | const requestUserAgent = url.match(/^[^:]+:\/\/accounts\.google\.[^./]+\//) | 319 | const requestUserAgent = url.match( |
320 | /^[^:]+:\/\/accounts\.google\.[^./]+\//, | ||
321 | ) | ||
309 | ? chromelessUserAgent | 322 | ? chromelessUserAgent |
310 | : userAgent; | 323 | : userAgent; |
311 | callback({ | 324 | callback({ |
@@ -317,9 +330,11 @@ async function createWindow(): Promise<unknown> { | |||
317 | }, | 330 | }, |
318 | ); | 331 | ); |
319 | 332 | ||
320 | browserView.webContents.loadURL('https://gitlab.com/say-hi-to-sophie/sophie').catch((err) => { | 333 | browserView.webContents |
321 | log.error('Failed to load browser', err); | 334 | .loadURL('https://gitlab.com/say-hi-to-sophie/sophie') |
322 | }); | 335 | .catch((err) => { |
336 | log.error('Failed to load browser', err); | ||
337 | }); | ||
323 | 338 | ||
324 | return mainWindow.loadURL(pageUrl); | 339 | return mainWindow.loadURL(pageUrl); |
325 | } | 340 | } |
@@ -342,17 +357,20 @@ app.on('window-all-closed', () => { | |||
342 | } | 357 | } |
343 | }); | 358 | }); |
344 | 359 | ||
345 | app.whenReady().then(async () => { | 360 | app |
346 | if (isDevelopment) { | 361 | .whenReady() |
347 | try { | 362 | .then(async () => { |
348 | await installDevToolsExtensions(); | 363 | if (isDevelopment) { |
349 | } catch (err) { | 364 | try { |
350 | log.error('Failed to install devtools extensions', err); | 365 | await installDevToolsExtensions(); |
366 | } catch (err) { | ||
367 | log.error('Failed to install devtools extensions', err); | ||
368 | } | ||
351 | } | 369 | } |
352 | } | ||
353 | 370 | ||
354 | return createWindow(); | 371 | return createWindow(); |
355 | }).catch((err) => { | 372 | }) |
356 | log.error('Failed to create window', err); | 373 | .catch((err) => { |
357 | process.exit(1); | 374 | log.error('Failed to create window', err); |
358 | }); | 375 | process.exit(1); |
376 | }); | ||
diff --git a/packages/main/src/init.ts b/packages/main/src/init.ts index 4487cc4..f3794bb 100644 --- a/packages/main/src/init.ts +++ b/packages/main/src/init.ts | |||
@@ -27,8 +27,13 @@ import { MainStore } from './stores/MainStore'; | |||
27 | import type Disposer from './utils/Disposer'; | 27 | import type Disposer from './utils/Disposer'; |
28 | 28 | ||
29 | export default async function init(store: MainStore): Promise<Disposer> { | 29 | export default async function init(store: MainStore): Promise<Disposer> { |
30 | const configPersistenceService = new ConfigPersistenceServiceImpl(app.getPath('userData')); | 30 | const configPersistenceService = new ConfigPersistenceServiceImpl( |
31 | const disposeConfigController = await initConfig(store.config, configPersistenceService); | 31 | app.getPath('userData'), |
32 | ); | ||
33 | const disposeConfigController = await initConfig( | ||
34 | store.config, | ||
35 | configPersistenceService, | ||
36 | ); | ||
32 | const disposeNativeThemeController = initNativeTheme(store); | 37 | const disposeNativeThemeController = initNativeTheme(store); |
33 | 38 | ||
34 | return () => { | 39 | return () => { |
diff --git a/packages/main/src/services/ConfigPersistenceService.ts b/packages/main/src/services/ConfigPersistenceService.ts index 7d508c5..ee5696d 100644 --- a/packages/main/src/services/ConfigPersistenceService.ts +++ b/packages/main/src/services/ConfigPersistenceService.ts | |||
@@ -21,7 +21,9 @@ | |||
21 | import type { ConfigSnapshotOut } from '../stores/Config'; | 21 | import type { ConfigSnapshotOut } from '../stores/Config'; |
22 | import type Disposer from '../utils/Disposer'; | 22 | import type Disposer from '../utils/Disposer'; |
23 | 23 | ||
24 | export type ReadConfigResult = { found: true; data: unknown; } | { found: false; }; | 24 | export type ReadConfigResult = |
25 | | { found: true; data: unknown } | ||
26 | | { found: false }; | ||
25 | 27 | ||
26 | export default interface ConfigPersistenceService { | 28 | export default interface ConfigPersistenceService { |
27 | readConfig(): Promise<ReadConfigResult>; | 29 | readConfig(): Promise<ReadConfigResult>; |
diff --git a/packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts b/packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts index df8c807..e92f706 100644 --- a/packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts +++ b/packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts | |||
@@ -32,7 +32,9 @@ import type { ReadConfigResult } from '../ConfigPersistenceService'; | |||
32 | 32 | ||
33 | const log = getLogger('configPersistence'); | 33 | const log = getLogger('configPersistence'); |
34 | 34 | ||
35 | export default class ConfigPersistenceServiceImpl implements ConfigPersistenceService { | 35 | export default class ConfigPersistenceServiceImpl |
36 | implements ConfigPersistenceService | ||
37 | { | ||
36 | private readonly configFilePath: string; | 38 | private readonly configFilePath: string; |
37 | 39 | ||
38 | private writingConfig = false; | 40 | private writingConfig = false; |
@@ -92,13 +94,19 @@ export default class ConfigPersistenceServiceImpl implements ConfigPersistenceSe | |||
92 | log.trace('Config file last modified at', mtime); | 94 | log.trace('Config file last modified at', mtime); |
93 | } catch (err) { | 95 | } catch (err) { |
94 | if ((err as NodeJS.ErrnoException).code === 'ENOENT') { | 96 | if ((err as NodeJS.ErrnoException).code === 'ENOENT') { |
95 | log.debug('Config file', this.configFilePath, 'was deleted after being changed'); | 97 | log.debug( |
98 | 'Config file', | ||
99 | this.configFilePath, | ||
100 | 'was deleted after being changed', | ||
101 | ); | ||
96 | return; | 102 | return; |
97 | } | 103 | } |
98 | throw err; | 104 | throw err; |
99 | } | 105 | } |
100 | if (!this.writingConfig | 106 | if ( |
101 | && (this.timeLastWritten === null || mtime > this.timeLastWritten)) { | 107 | !this.writingConfig && |
108 | (this.timeLastWritten === null || mtime > this.timeLastWritten) | ||
109 | ) { | ||
102 | log.debug( | 110 | log.debug( |
103 | 'Found a config file modified at', | 111 | 'Found a config file modified at', |
104 | mtime, | 112 | mtime, |
@@ -114,8 +122,10 @@ export default class ConfigPersistenceServiceImpl implements ConfigPersistenceSe | |||
114 | }); | 122 | }); |
115 | 123 | ||
116 | watcher.on('change', (eventType, filename) => { | 124 | watcher.on('change', (eventType, filename) => { |
117 | if (eventType === 'change' | 125 | if ( |
118 | && (filename === this.configFileName || filename === null)) { | 126 | eventType === 'change' && |
127 | (filename === this.configFileName || filename === null) | ||
128 | ) { | ||
119 | configChanged()?.catch((err) => { | 129 | configChanged()?.catch((err) => { |
120 | log.error('Unhandled error while listening for config changes', err); | 130 | log.error('Unhandled error while listening for config changes', err); |
121 | }); | 131 | }); |
diff --git a/packages/main/src/stores/MainStore.ts b/packages/main/src/stores/MainStore.ts index 7b26c52..eaf5b3c 100644 --- a/packages/main/src/stores/MainStore.ts +++ b/packages/main/src/stores/MainStore.ts | |||
@@ -24,26 +24,32 @@ import { applySnapshot, Instance, types } from 'mobx-state-tree'; | |||
24 | import type { Config } from './Config.js'; | 24 | import type { Config } from './Config.js'; |
25 | import { sharedStore } from './SharedStore'; | 25 | import { sharedStore } from './SharedStore'; |
26 | 26 | ||
27 | export const mainStore = types.model('MainStore', { | 27 | export const mainStore = types |
28 | browserViewBounds: types.optional(types.model('BrowserViewBounds', { | 28 | .model('MainStore', { |
29 | x: 0, | 29 | browserViewBounds: types.optional( |
30 | y: 0, | 30 | types.model('BrowserViewBounds', { |
31 | width: 0, | 31 | x: 0, |
32 | height: 0, | 32 | y: 0, |
33 | }), {}), | 33 | width: 0, |
34 | shared: types.optional(sharedStore, {}), | 34 | height: 0, |
35 | }).views((self) => ({ | 35 | }), |
36 | get config(): Config { | 36 | {}, |
37 | return self.shared.config; | 37 | ), |
38 | }, | 38 | shared: types.optional(sharedStore, {}), |
39 | })).actions((self) => ({ | 39 | }) |
40 | setBrowserViewBounds(bounds: BrowserViewBounds): void { | 40 | .views((self) => ({ |
41 | applySnapshot(self.browserViewBounds, bounds); | 41 | get config(): Config { |
42 | }, | 42 | return self.shared.config; |
43 | setShouldUseDarkColors(shouldUseDarkColors: boolean): void { | 43 | }, |
44 | self.shared.shouldUseDarkColors = shouldUseDarkColors; | 44 | })) |
45 | }, | 45 | .actions((self) => ({ |
46 | })); | 46 | setBrowserViewBounds(bounds: BrowserViewBounds): void { |
47 | applySnapshot(self.browserViewBounds, bounds); | ||
48 | }, | ||
49 | setShouldUseDarkColors(shouldUseDarkColors: boolean): void { | ||
50 | self.shared.shouldUseDarkColors = shouldUseDarkColors; | ||
51 | }, | ||
52 | })); | ||
47 | 53 | ||
48 | export interface MainStore extends Instance<typeof mainStore> {} | 54 | export interface MainStore extends Instance<typeof mainStore> {} |
49 | 55 | ||
diff --git a/packages/main/src/stores/SharedStore.ts b/packages/main/src/stores/SharedStore.ts index c023fc7..73245cd 100644 --- a/packages/main/src/stores/SharedStore.ts +++ b/packages/main/src/stores/SharedStore.ts | |||
@@ -23,7 +23,10 @@ import { Instance, types } from 'mobx-state-tree'; | |||
23 | 23 | ||
24 | import { config } from './Config'; | 24 | import { config } from './Config'; |
25 | 25 | ||
26 | export type { SharedStoreSnapshotIn, SharedStoreSnapshotOut } from '@sophie/shared'; | 26 | export type { |
27 | SharedStoreSnapshotIn, | ||
28 | SharedStoreSnapshotOut, | ||
29 | } from '@sophie/shared'; | ||
27 | 30 | ||
28 | export const sharedStore = originalSharedStore.props({ | 31 | export const sharedStore = originalSharedStore.props({ |
29 | config: types.optional(config, {}), | 32 | config: types.optional(config, {}), |
diff --git a/packages/main/src/utils/log.ts b/packages/main/src/utils/log.ts index c704797..5218721 100644 --- a/packages/main/src/utils/log.ts +++ b/packages/main/src/utils/log.ts | |||
@@ -46,9 +46,10 @@ prefix.apply(loglevel, { | |||
46 | format(level, name, timestamp) { | 46 | format(level, name, timestamp) { |
47 | const levelColor = getColor(level); | 47 | const levelColor = getColor(level); |
48 | const timeStr = timestamp.toString(); | 48 | const timeStr = timestamp.toString(); |
49 | const nameStr = typeof name === 'undefined' | 49 | const nameStr = |
50 | ? levelColor(':') | 50 | typeof name === 'undefined' |
51 | : ` ${chalk.green(`${name}:`)}`; | 51 | ? levelColor(':') |
52 | : ` ${chalk.green(`${name}:`)}`; | ||
52 | return `${chalk.gray(`[${timeStr}]`)} ${levelColor(level)}${nameStr}`; | 53 | return `${chalk.gray(`[${timeStr}]`)} ${levelColor(level)}${nameStr}`; |
53 | }, | 54 | }, |
54 | }); | 55 | }); |