aboutsummaryrefslogtreecommitdiffstats
path: root/packages/main
diff options
context:
space:
mode:
Diffstat (limited to 'packages/main')
-rw-r--r--packages/main/package.json6
-rw-r--r--packages/main/src/devTools.ts49
-rw-r--r--packages/main/src/index.ts66
-rw-r--r--packages/main/src/stores/RootStore.ts12
4 files changed, 97 insertions, 36 deletions
diff --git a/packages/main/package.json b/packages/main/package.json
index 63da432..22afafa 100644
--- a/packages/main/package.json
+++ b/packages/main/package.json
@@ -9,11 +9,13 @@
9 }, 9 },
10 "dependencies": { 10 "dependencies": {
11 "@sophie/shared": "workspace:*", 11 "@sophie/shared": "workspace:*",
12 "electron": "^16.0.5" 12 "electron": "^16.0.5",
13 "mobx": "^6.3.10",
14 "mobx-state-tree": "^5.1.0"
13 }, 15 },
14 "devDependencies": { 16 "devDependencies": {
15 "@types/electron-devtools-installer": "^2.2.0", 17 "@types/electron-devtools-installer": "^2.2.0",
16 "@types/node": "^16.11.15", 18 "@types/node": "^16.11.17",
17 "electron-devtools-installer": "^3.2.0", 19 "electron-devtools-installer": "^3.2.0",
18 "typescript": "^4.5.4", 20 "typescript": "^4.5.4",
19 "vite": "^2.7.6" 21 "vite": "^2.7.6"
diff --git a/packages/main/src/devTools.ts b/packages/main/src/devTools.ts
new file mode 100644
index 0000000..d02bfbf
--- /dev/null
+++ b/packages/main/src/devTools.ts
@@ -0,0 +1,49 @@
1import type { App, BrowserWindow } from 'electron';
2
3/**
4 * Installs the react and redux developer tools extensions.
5 *
6 * We use the redux devtools and connect the mobx store to it with `mst-middlewares`,
7 * because the mobx-state-tree devtools are currently unmaintained.
8 *
9 * @param app The electron application instance.
10 */
11export function installDevToolsExtensions(app: App): void {
12 app.whenReady().then(async () => {
13 const {
14 default: installExtension,
15 REACT_DEVELOPER_TOOLS,
16 REDUX_DEVTOOLS,
17 } = await import('electron-devtools-installer');
18 installExtension(
19 [
20 REACT_DEVELOPER_TOOLS,
21 REDUX_DEVTOOLS,
22 ],
23 {
24 forceDownload: false,
25 loadExtensionOptions: {
26 allowFileAccess: true,
27 },
28 },
29 );
30 }).catch((err) => {
31 console.error('Failed to install devtools extension', err);
32 });
33}
34
35/**
36 * Opens the developer tools while applying a workaround to enable the redux devtools.
37 *
38 * @param browserWindow The browser window to open the devtools in.
39 * @see https://github.com/MarshallOfSound/electron-devtools-installer/issues/195#issuecomment-998872878
40 */
41export function openDevToolsWhenReady(browserWindow: BrowserWindow): void {
42 const { webContents } = browserWindow;
43 webContents.once('dom-ready', () => {
44 webContents.once('devtools-opened', () => {
45 browserWindow?.focus();
46 });
47 webContents.openDevTools();
48 });
49}
diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts
index cd04276..dbe6890 100644
--- a/packages/main/src/index.ts
+++ b/packages/main/src/index.ts
@@ -1,8 +1,18 @@
1import { app, BrowserWindow } from 'electron'; 1import { app, BrowserWindow } from 'electron';
2import { getSnapshot, onPatch } from 'mobx-state-tree';
2import { join } from 'path'; 3import { join } from 'path';
3import { RendererIpcMessage } from '@sophie/shared'; 4import {
5 MainToRendererIpcMessage,
6 RendererToMainIpcMessage,
7} from '@sophie/shared';
4import { URL } from 'url'; 8import { URL } from 'url';
5 9
10import {
11 installDevToolsExtensions,
12 openDevToolsWhenReady,
13} from './devTools';
14import { rootStore } from './stores/RootStore';
15
6const isSingleInstance = app.requestSingleInstanceLock(); 16const isSingleInstance = app.requestSingleInstanceLock();
7const isDevelopment = import.meta.env.MODE === 'development'; 17const isDevelopment = import.meta.env.MODE === 'development';
8 18
@@ -14,62 +24,46 @@ if (!isSingleInstance) {
14app.enableSandbox(); 24app.enableSandbox();
15 25
16if (isDevelopment) { 26if (isDevelopment) {
17 app.whenReady().then(async () => { 27 installDevToolsExtensions(app);
18 const {
19 default: installExtension,
20 MOBX_DEVTOOLS,
21 REACT_DEVELOPER_TOOLS,
22 } = await import('electron-devtools-installer');
23 installExtension(
24 [
25 MOBX_DEVTOOLS,
26 REACT_DEVELOPER_TOOLS,
27 ],
28 {
29 forceDownload: false,
30 loadExtensionOptions: {
31 allowFileAccess: true,
32 },
33 },
34 );
35 }).catch((err) => {
36 console.error('Failed to install devtools extension', err);
37 });
38} 28}
39 29
40let mainWindow: BrowserWindow | null = null; 30let mainWindow: BrowserWindow | null = null;
41 31
32const store = rootStore.create({
33 shared: {
34 clickCount: 1,
35 },
36});
37
42function createWindow(): Promise<void> { 38function createWindow(): Promise<void> {
43 mainWindow = new BrowserWindow({ 39 mainWindow = new BrowserWindow({
44 show: false, 40 show: false,
41 autoHideMenuBar: true,
45 webPreferences: { 42 webPreferences: {
46 nativeWindowOpen: true, 43 nativeWindowOpen: true,
47 webviewTag: false, 44 webviewTag: false,
48 sandbox: true, 45 sandbox: true,
49 preload: join(__dirname, '../../preload/dist/index.cjs'), 46 preload: join(__dirname, '../../preload/dist/index.cjs'),
50 } 47 },
51 }); 48 });
52 49
53 const { webContents } = mainWindow;
54
55 // See https://github.com/MarshallOfSound/electron-devtools-installer/issues/195#issuecomment-998872878
56 if (isDevelopment) { 50 if (isDevelopment) {
57 webContents.once('dom-ready', () => { 51 openDevToolsWhenReady(mainWindow);
58 webContents.once('devtools-opened', () => {
59 mainWindow?.focus();
60 });
61 webContents.openDevTools();
62 });
63 } 52 }
64 53
65 mainWindow.on('ready-to-show', () => { 54 mainWindow.on('ready-to-show', () => {
66 mainWindow?.show(); 55 mainWindow?.show();
67 }); 56 });
68 57
58 const { webContents } = mainWindow;
59
69 webContents.on('ipc-message', (_event, channel, ...args) => { 60 webContents.on('ipc-message', (_event, channel, ...args) => {
70 switch (channel) { 61 switch (channel) {
71 case RendererIpcMessage.ButtonClicked: 62 case RendererToMainIpcMessage.SharedStoreSnapshotRequest:
72 console.log('Button clicked'); 63 webContents.send(MainToRendererIpcMessage.SharedStoreSnapshot, getSnapshot(store.shared));
64 break;
65 case RendererToMainIpcMessage.ButtonClick:
66 store.buttonClick();
73 break; 67 break;
74 default: 68 default:
75 console.warn('Unknown IPC message:', channel, args); 69 console.warn('Unknown IPC message:', channel, args);
@@ -77,6 +71,10 @@ function createWindow(): Promise<void> {
77 } 71 }
78 }); 72 });
79 73
74 onPatch(store.shared, (patch) => {
75 webContents.send(MainToRendererIpcMessage.SharedStorePatch, patch);
76 });
77
80 const pageUrl = (isDevelopment && import.meta.env.VITE_DEV_SERVER_URL !== undefined) 78 const pageUrl = (isDevelopment && import.meta.env.VITE_DEV_SERVER_URL !== undefined)
81 ? import.meta.env.VITE_DEV_SERVER_URL 79 ? import.meta.env.VITE_DEV_SERVER_URL
82 : new URL('../renderer/dist/index.html', `file://${__dirname}`).toString(); 80 : new URL('../renderer/dist/index.html', `file://${__dirname}`).toString();
diff --git a/packages/main/src/stores/RootStore.ts b/packages/main/src/stores/RootStore.ts
new file mode 100644
index 0000000..a9c1290
--- /dev/null
+++ b/packages/main/src/stores/RootStore.ts
@@ -0,0 +1,12 @@
1import { Instance, types } from 'mobx-state-tree';
2import { sharedStore } from '@sophie/shared';
3
4export const rootStore = types.model('RootStore', {
5 shared: sharedStore,
6}).actions((self) => ({
7 buttonClick() {
8 self.shared.clickCount += 1;
9 },
10}));
11
12export interface RootStore extends Instance<typeof rootStore> {}