aboutsummaryrefslogtreecommitdiffstats
path: root/packages/main/src/index.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/main/src/index.ts')
-rw-r--r--packages/main/src/index.ts109
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
22import {
23 app,
24 BrowserView,
25 BrowserWindow,
26 ipcMain,
27} from 'electron';
28import { arch } from 'os'; 22import { arch } from 'os';
29import osName from 'os-name';
30import { ensureDirSync, readFile, readFileSync } from 'fs-extra';
31import { autorun } from 'mobx';
32import { getSnapshot, onPatch } from 'mobx-state-tree';
33import { join } from 'path'; 23import { join } from 'path';
24import { URL } from 'url';
25
34import { 26import {
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';
44import { URL } from 'url'; 36import {
37 app,
38 BrowserView,
39 BrowserWindow,
40 ipcMain,
41} from 'electron';
42import { ensureDirSync, readFile, readFileSync } from 'fs-extra';
43import { autorun } from 'mobx';
44import { getSnapshot, onPatch } from 'mobx-state-tree';
45import osName from 'os-name';
45 46
46import { init } from './compositionRoot';
47import { 47import {
48 DEVMODE_ALLOWED_URL_PREFIXES, 48 DEVMODE_ALLOWED_URL_PREFIXES,
49 installDevToolsExtensions, 49 installDevToolsExtensions,
50 openDevToolsWhenReady, 50 openDevToolsWhenReady,
51} from './devTools'; 51} from './devTools';
52import init from './init';
52import { createMainStore } from './stores/MainStore'; 53import { createMainStore } from './stores/MainStore';
54import { getLogger } from './utils/log';
53 55
54const isDevelopment = import.meta.env.MODE === 'development'; 56const isDevelopment = import.meta.env.MODE === 'development';
55 57
58const log = getLogger('index');
59
56// Always enable sandboxing. 60// Always enable sandboxing.
57app.enableSandbox(); 61app.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
112let serviceInjectRelativePath = '../../service-inject/dist/index.js'; 116const serviceInjectRelativePath = '../../service-inject/dist/index.js';
113let serviceInjectPath = getResourcePath(serviceInjectRelativePath); 117const serviceInjectPath = getResourcePath(serviceInjectRelativePath);
114let serviceInject: WebSource = { 118const 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();
122init(store).then((disposeCompositionRoot) => { 126init(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
128const rendererBaseUrl = getResourceUrl('../renderer/'); 132const 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});