diff options
Diffstat (limited to 'packages/main/src/index.ts')
-rw-r--r-- | packages/main/src/index.ts | 109 |
1 files changed, 63 insertions, 46 deletions
diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts index d0191b7..bc10b4c 100644 --- a/packages/main/src/index.ts +++ b/packages/main/src/index.ts | |||
@@ -19,18 +19,10 @@ | |||
19 | * SPDX-License-Identifier: AGPL-3.0-only | 19 | * SPDX-License-Identifier: AGPL-3.0-only |
20 | */ | 20 | */ |
21 | 21 | ||
22 | import { | ||
23 | app, | ||
24 | BrowserView, | ||
25 | BrowserWindow, | ||
26 | ipcMain, | ||
27 | } from 'electron'; | ||
28 | import { arch } from 'os'; | 22 | import { arch } from 'os'; |
29 | import osName from 'os-name'; | ||
30 | import { ensureDirSync, readFile, readFileSync } from 'fs-extra'; | ||
31 | import { autorun } from 'mobx'; | ||
32 | import { getSnapshot, onPatch } from 'mobx-state-tree'; | ||
33 | import { join } from 'path'; | 23 | import { join } from 'path'; |
24 | import { URL } from 'url'; | ||
25 | |||
34 | import { | 26 | import { |
35 | ServiceToMainIpcMessage, | 27 | ServiceToMainIpcMessage, |
36 | unreadCount, | 28 | unreadCount, |
@@ -41,18 +33,30 @@ import { | |||
41 | MainToRendererIpcMessage, | 33 | MainToRendererIpcMessage, |
42 | RendererToMainIpcMessage, | 34 | RendererToMainIpcMessage, |
43 | } from '@sophie/shared'; | 35 | } from '@sophie/shared'; |
44 | import { URL } from 'url'; | 36 | import { |
37 | app, | ||
38 | BrowserView, | ||
39 | BrowserWindow, | ||
40 | ipcMain, | ||
41 | } from 'electron'; | ||
42 | import { ensureDirSync, readFile, readFileSync } from 'fs-extra'; | ||
43 | import { autorun } from 'mobx'; | ||
44 | import { getSnapshot, onPatch } from 'mobx-state-tree'; | ||
45 | import osName from 'os-name'; | ||
45 | 46 | ||
46 | import { init } from './compositionRoot'; | ||
47 | import { | 47 | import { |
48 | DEVMODE_ALLOWED_URL_PREFIXES, | 48 | DEVMODE_ALLOWED_URL_PREFIXES, |
49 | installDevToolsExtensions, | 49 | installDevToolsExtensions, |
50 | openDevToolsWhenReady, | 50 | openDevToolsWhenReady, |
51 | } from './devTools'; | 51 | } from './devTools'; |
52 | import init from './init'; | ||
52 | import { createMainStore } from './stores/MainStore'; | 53 | import { createMainStore } from './stores/MainStore'; |
54 | import { getLogger } from './utils/log'; | ||
53 | 55 | ||
54 | const isDevelopment = import.meta.env.MODE === 'development'; | 56 | const isDevelopment = import.meta.env.MODE === 'development'; |
55 | 57 | ||
58 | const log = getLogger('index'); | ||
59 | |||
56 | // Always enable sandboxing. | 60 | // Always enable sandboxing. |
57 | app.enableSandbox(); | 61 | app.enableSandbox(); |
58 | 62 | ||
@@ -93,7 +97,7 @@ app.setAboutPanelOptions({ | |||
93 | `Node.js: ${process.versions.node}`, | 97 | `Node.js: ${process.versions.node}`, |
94 | `Platform: ${osName()}`, | 98 | `Platform: ${osName()}`, |
95 | `Arch: ${arch()}`, | 99 | `Arch: ${arch()}`, |
96 | `Build date: ${new Date(Number(import.meta.env.BUILD_DATE))}`, | 100 | `Build date: ${new Date(Number(import.meta.env.BUILD_DATE)).toLocaleString()}`, |
97 | `Git SHA: ${import.meta.env.GIT_SHA}`, | 101 | `Git SHA: ${import.meta.env.GIT_SHA}`, |
98 | `Git branch: ${import.meta.env.GIT_BRANCH}`, | 102 | `Git branch: ${import.meta.env.GIT_BRANCH}`, |
99 | ].join('\n'), | 103 | ].join('\n'), |
@@ -109,9 +113,9 @@ function getResourceUrl(relativePath: string): string { | |||
109 | return new URL(relativePath, baseUrl).toString(); | 113 | return new URL(relativePath, baseUrl).toString(); |
110 | } | 114 | } |
111 | 115 | ||
112 | let serviceInjectRelativePath = '../../service-inject/dist/index.js'; | 116 | const serviceInjectRelativePath = '../../service-inject/dist/index.js'; |
113 | let serviceInjectPath = getResourcePath(serviceInjectRelativePath); | 117 | const serviceInjectPath = getResourcePath(serviceInjectRelativePath); |
114 | let serviceInject: WebSource = { | 118 | const serviceInject: WebSource = { |
115 | code: readFileSync(serviceInjectPath, 'utf8'), | 119 | code: readFileSync(serviceInjectPath, 'utf8'), |
116 | url: getResourceUrl(serviceInjectRelativePath), | 120 | url: getResourceUrl(serviceInjectRelativePath), |
117 | }; | 121 | }; |
@@ -122,7 +126,7 @@ const store = createMainStore(); | |||
122 | init(store).then((disposeCompositionRoot) => { | 126 | init(store).then((disposeCompositionRoot) => { |
123 | app.on('will-quit', disposeCompositionRoot); | 127 | app.on('will-quit', disposeCompositionRoot); |
124 | }).catch((err) => { | 128 | }).catch((err) => { |
125 | console.log('Failed to initialize application', err); | 129 | log.log('Failed to initialize application', err); |
126 | }); | 130 | }); |
127 | 131 | ||
128 | const rendererBaseUrl = getResourceUrl('../renderer/'); | 132 | const rendererBaseUrl = getResourceUrl('../renderer/'); |
@@ -211,7 +215,7 @@ async function createWindow(): Promise<unknown> { | |||
211 | 215 | ||
212 | ipcMain.handle(RendererToMainIpcMessage.GetSharedStoreSnapshot, (event) => { | 216 | ipcMain.handle(RendererToMainIpcMessage.GetSharedStoreSnapshot, (event) => { |
213 | if (event.sender.id !== webContents.id) { | 217 | if (event.sender.id !== webContents.id) { |
214 | console.warn( | 218 | log.warn( |
215 | 'Unexpected', | 219 | 'Unexpected', |
216 | RendererToMainIpcMessage.GetSharedStoreSnapshot, | 220 | RendererToMainIpcMessage.GetSharedStoreSnapshot, |
217 | 'from webContents', | 221 | 'from webContents', |
@@ -224,7 +228,7 @@ async function createWindow(): Promise<unknown> { | |||
224 | 228 | ||
225 | ipcMain.on(RendererToMainIpcMessage.DispatchAction, (event, rawAction) => { | 229 | ipcMain.on(RendererToMainIpcMessage.DispatchAction, (event, rawAction) => { |
226 | if (event.sender.id !== webContents.id) { | 230 | if (event.sender.id !== webContents.id) { |
227 | console.warn( | 231 | log.warn( |
228 | 'Unexpected', | 232 | 'Unexpected', |
229 | RendererToMainIpcMessage.DispatchAction, | 233 | RendererToMainIpcMessage.DispatchAction, |
230 | 'from webContents', | 234 | 'from webContents', |
@@ -242,17 +246,26 @@ async function createWindow(): Promise<unknown> { | |||
242 | store.config.setThemeSource(actionToDispatch.themeSource); | 246 | store.config.setThemeSource(actionToDispatch.themeSource); |
243 | break; | 247 | break; |
244 | case 'reload-all-services': | 248 | case 'reload-all-services': |
245 | readFile(serviceInjectPath, 'utf8').then((data) => { | 249 | readFile(serviceInjectPath, 'utf8') |
246 | serviceInject.code = data; | 250 | .then((data) => { |
247 | }).catch((err) => { | 251 | serviceInject.code = data; |
248 | console.error('Error while reloading', serviceInjectPath, err); | 252 | }) |
249 | }).then(() => { | 253 | .catch((err) => { |
250 | browserView.webContents.reload(); | 254 | log.error('Error while reloading', serviceInjectPath, err); |
251 | }); | 255 | }) |
256 | .then(() => { | ||
257 | browserView.webContents.reload(); | ||
258 | }) | ||
259 | .catch((err) => { | ||
260 | log.error('Failed to reload browserView', err); | ||
261 | }); | ||
262 | break; | ||
263 | default: | ||
264 | log.error('Unexpected action from UI renderer:', actionToDispatch); | ||
252 | break; | 265 | break; |
253 | } | 266 | } |
254 | } catch (err) { | 267 | } catch (err) { |
255 | console.error('Error while dispatching renderer action', rawAction, err); | 268 | log.error('Error while dispatching renderer action', rawAction, err); |
256 | } | 269 | } |
257 | }); | 270 | }); |
258 | 271 | ||
@@ -260,11 +273,10 @@ async function createWindow(): Promise<unknown> { | |||
260 | webContents.send(MainToRendererIpcMessage.SharedStorePatch, patch); | 273 | webContents.send(MainToRendererIpcMessage.SharedStorePatch, patch); |
261 | }); | 274 | }); |
262 | 275 | ||
263 | ipcMain.handle(ServiceToMainIpcMessage.ApiExposedInMainWorld, (event) => { | 276 | ipcMain.handle( |
264 | return event.sender.id === browserView.webContents.id | 277 | ServiceToMainIpcMessage.ApiExposedInMainWorld, |
265 | ? serviceInject | 278 | (event) => (event.sender.id === browserView.webContents.id ? serviceInject : null), |
266 | : null; | 279 | ); |
267 | }); | ||
268 | 280 | ||
269 | browserView.webContents.on('ipc-message', (_event, channel, ...args) => { | 281 | browserView.webContents.on('ipc-message', (_event, channel, ...args) => { |
270 | try { | 282 | try { |
@@ -274,14 +286,14 @@ async function createWindow(): Promise<unknown> { | |||
274 | // otherwise electron emits a no handler registered warning. | 286 | // otherwise electron emits a no handler registered warning. |
275 | break; | 287 | break; |
276 | case ServiceToMainIpcMessage.SetUnreadCount: | 288 | case ServiceToMainIpcMessage.SetUnreadCount: |
277 | console.log('Unread count:', unreadCount.parse(args[0])); | 289 | log.log('Unread count:', unreadCount.parse(args[0])); |
278 | break; | 290 | break; |
279 | default: | 291 | default: |
280 | console.error('Unknown IPC message:', channel, args); | 292 | log.error('Unknown IPC message:', channel, args); |
281 | break; | 293 | break; |
282 | } | 294 | } |
283 | } catch (err) { | 295 | } catch (err) { |
284 | console.error('Error while processing IPC message:', channel, args, err); | 296 | log.error('Error while processing IPC message:', channel, args, err); |
285 | } | 297 | } |
286 | }); | 298 | }); |
287 | 299 | ||
@@ -291,17 +303,22 @@ async function createWindow(): Promise<unknown> { | |||
291 | }, | 303 | }, |
292 | ); | 304 | ); |
293 | 305 | ||
294 | browserView.webContents.session.webRequest.onBeforeSendHeaders(({ url, requestHeaders }, callback) => { | 306 | browserView.webContents.session.webRequest.onBeforeSendHeaders( |
295 | if (url.match(/^[^:]+:\/\/accounts\.google\.[^.\/]+\//)) { | 307 | ({ url, requestHeaders }, callback) => { |
296 | requestHeaders['User-Agent'] = chromelessUserAgent; | 308 | const requestUserAgent = url.match(/^[^:]+:\/\/accounts\.google\.[^./]+\//) |
297 | } else { | 309 | ? chromelessUserAgent |
298 | requestHeaders['User-Agent'] = userAgent; | 310 | : userAgent; |
299 | } | 311 | callback({ |
300 | callback({ requestHeaders }); | 312 | requestHeaders: { |
301 | }); | 313 | ...requestHeaders, |
314 | 'User-Agent': requestUserAgent, | ||
315 | }, | ||
316 | }); | ||
317 | }, | ||
318 | ); | ||
302 | 319 | ||
303 | browserView.webContents.loadURL('https://gitlab.com/say-hi-to-sophie/sophie').catch((err) => { | 320 | browserView.webContents.loadURL('https://gitlab.com/say-hi-to-sophie/sophie').catch((err) => { |
304 | console.error('Failed to load browser', err); | 321 | log.error('Failed to load browser', err); |
305 | }); | 322 | }); |
306 | 323 | ||
307 | return mainWindow.loadURL(pageUrl); | 324 | return mainWindow.loadURL(pageUrl); |
@@ -330,12 +347,12 @@ app.whenReady().then(async () => { | |||
330 | try { | 347 | try { |
331 | await installDevToolsExtensions(); | 348 | await installDevToolsExtensions(); |
332 | } catch (err) { | 349 | } catch (err) { |
333 | console.error('Failed to install devtools extensions', err); | 350 | log.error('Failed to install devtools extensions', err); |
334 | } | 351 | } |
335 | } | 352 | } |
336 | 353 | ||
337 | return createWindow(); | 354 | return createWindow(); |
338 | }).catch((err) => { | 355 | }).catch((err) => { |
339 | console.error('Failed to create window', err); | 356 | log.error('Failed to create window', err); |
340 | process.exit(1); | 357 | process.exit(1); |
341 | }); | 358 | }); |