aboutsummaryrefslogtreecommitdiffstats
path: root/packages/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'packages/renderer')
-rw-r--r--packages/renderer/.eslinrc.cjs11
-rw-r--r--packages/renderer/.eslintrc.json5
-rw-r--r--packages/renderer/package.json10
-rw-r--r--packages/renderer/src/components/App.tsx6
-rw-r--r--packages/renderer/src/components/BrowserViewPlaceholder.tsx14
-rw-r--r--packages/renderer/src/components/Sidebar.tsx4
-rw-r--r--packages/renderer/src/components/StoreProvider.tsx2
-rw-r--r--packages/renderer/src/components/ThemeProvider.tsx8
-rw-r--r--packages/renderer/src/components/ToggleDarkModeButton.tsx9
-rw-r--r--packages/renderer/src/devTools.ts21
-rw-r--r--packages/renderer/src/index.tsx13
-rw-r--r--packages/renderer/src/stores/RendererEnv.ts4
-rw-r--r--packages/renderer/src/stores/RendererStore.ts21
-rw-r--r--packages/renderer/src/utils/log.ts50
-rw-r--r--packages/renderer/tsconfig.json8
-rw-r--r--packages/renderer/vite.config.js5
16 files changed, 126 insertions, 65 deletions
diff --git a/packages/renderer/.eslinrc.cjs b/packages/renderer/.eslinrc.cjs
new file mode 100644
index 0000000..3385ac5
--- /dev/null
+++ b/packages/renderer/.eslinrc.cjs
@@ -0,0 +1,11 @@
1module.exports = {
2 extends: [
3 'airbnb',
4 'airbnb/hooks',
5 'airbnb-typescript',
6 ],
7 env: {
8 node: false,
9 browser: true,
10 },
11};
diff --git a/packages/renderer/.eslintrc.json b/packages/renderer/.eslintrc.json
deleted file mode 100644
index a28aec9..0000000
--- a/packages/renderer/.eslintrc.json
+++ /dev/null
@@ -1,5 +0,0 @@
1{
2 "globals": {
3 "JSX": false
4 }
5}
diff --git a/packages/renderer/package.json b/packages/renderer/package.json
index df15abb..fde4c28 100644
--- a/packages/renderer/package.json
+++ b/packages/renderer/package.json
@@ -5,7 +5,7 @@
5 "type": "module", 5 "type": "module",
6 "types": "dist-types/index.d.ts", 6 "types": "dist-types/index.d.ts",
7 "scripts": { 7 "scripts": {
8 "typecheck": "tsc" 8 "typecheck:workspace": "yarn g:typecheck"
9 }, 9 },
10 "dependencies": { 10 "dependencies": {
11 "@emotion/react": "^11.7.1", 11 "@emotion/react": "^11.7.1",
@@ -14,7 +14,9 @@
14 "@mui/icons-material": "^5.2.5", 14 "@mui/icons-material": "^5.2.5",
15 "@mui/material": "^5.2.7", 15 "@mui/material": "^5.2.7",
16 "@sophie/shared": "workspace:*", 16 "@sophie/shared": "workspace:*",
17 "lodash": "^4.17.21", 17 "lodash-es": "^4.17.21",
18 "loglevel": "^1.8.0",
19 "loglevel-plugin-prefix": "^0.8.4",
18 "mobx": "^6.3.12", 20 "mobx": "^6.3.12",
19 "mobx-react-lite": "^3.2.3", 21 "mobx-react-lite": "^3.2.3",
20 "mobx-state-tree": "^5.1.0", 22 "mobx-state-tree": "^5.1.0",
@@ -22,14 +24,12 @@
22 "react-dom": "^17.0.2" 24 "react-dom": "^17.0.2"
23 }, 25 },
24 "devDependencies": { 26 "devDependencies": {
25 "@types/lodash": "^4.14.178", 27 "@types/lodash-es": "^4.14.178",
26 "@types/react": "^17.0.38", 28 "@types/react": "^17.0.38",
27 "@types/react-dom": "^17.0.11", 29 "@types/react-dom": "^17.0.11",
28 "@vitejs/plugin-react": "^1.1.4", 30 "@vitejs/plugin-react": "^1.1.4",
29 "mst-middlewares": "^5.1.0", 31 "mst-middlewares": "^5.1.0",
30 "remotedev": "^0.2.9", 32 "remotedev": "^0.2.9",
31 "rimraf": "^3.0.2",
32 "typescript": "^4.5.4",
33 "vite": "^2.7.10" 33 "vite": "^2.7.10"
34 } 34 }
35} 35}
diff --git a/packages/renderer/src/components/App.tsx b/packages/renderer/src/components/App.tsx
index 8bd3dd8..1174bbb 100644
--- a/packages/renderer/src/components/App.tsx
+++ b/packages/renderer/src/components/App.tsx
@@ -21,10 +21,10 @@
21import Box from '@mui/material/Box'; 21import Box from '@mui/material/Box';
22import React from 'react'; 22import React from 'react';
23 23
24import { BrowserViewPlaceholder } from './BrowserViewPlaceholder'; 24import BrowserViewPlaceholder from './BrowserViewPlaceholder';
25import { Sidebar } from './Sidebar'; 25import Sidebar from './Sidebar';
26 26
27export function App(): JSX.Element { 27export default function App(): JSX.Element {
28 return ( 28 return (
29 <Box 29 <Box
30 sx={{ 30 sx={{
diff --git a/packages/renderer/src/components/BrowserViewPlaceholder.tsx b/packages/renderer/src/components/BrowserViewPlaceholder.tsx
index 6aa6b7b..c671983 100644
--- a/packages/renderer/src/components/BrowserViewPlaceholder.tsx
+++ b/packages/renderer/src/components/BrowserViewPlaceholder.tsx
@@ -18,17 +18,15 @@
18 * SPDX-License-Identifier: AGPL-3.0-only 18 * SPDX-License-Identifier: AGPL-3.0-only
19 */ 19 */
20 20
21import { throttle } from 'lodash';
22import { observer } from 'mobx-react-lite';
23import Box from '@mui/material/Box'; 21import Box from '@mui/material/Box';
22import throttle from 'lodash-es/throttle';
23import { observer } from 'mobx-react-lite';
24import React, { useCallback, useRef } from 'react'; 24import React, { useCallback, useRef } from 'react';
25 25
26import { useStore } from './StoreProvider'; 26import { useStore } from './StoreProvider';
27 27
28export const BrowserViewPlaceholder = observer(function BrowserViewPlaceholder() { 28export default observer(() => {
29 const { 29 const store = useStore();
30 setBrowserViewBounds,
31 } = useStore();
32 30
33 const onResize = useCallback(throttle(([entry]: ResizeObserverEntry[]) => { 31 const onResize = useCallback(throttle(([entry]: ResizeObserverEntry[]) => {
34 if (entry) { 32 if (entry) {
@@ -38,14 +36,14 @@ export const BrowserViewPlaceholder = observer(function BrowserViewPlaceholder()
38 width, 36 width,
39 height, 37 height,
40 } = entry.target.getBoundingClientRect(); 38 } = entry.target.getBoundingClientRect();
41 setBrowserViewBounds({ 39 store.setBrowserViewBounds({
42 x, 40 x,
43 y, 41 y,
44 width, 42 width,
45 height, 43 height,
46 }); 44 });
47 } 45 }
48 }, 100), [setBrowserViewBounds]); 46 }, 100), [store]);
49 47
50 const resizeObserverRef = useRef<ResizeObserver | null>(null); 48 const resizeObserverRef = useRef<ResizeObserver | null>(null);
51 49
diff --git a/packages/renderer/src/components/Sidebar.tsx b/packages/renderer/src/components/Sidebar.tsx
index 6c79932..44a47b0 100644
--- a/packages/renderer/src/components/Sidebar.tsx
+++ b/packages/renderer/src/components/Sidebar.tsx
@@ -21,9 +21,9 @@
21import Box from '@mui/material/Box'; 21import Box from '@mui/material/Box';
22import React from 'react'; 22import React from 'react';
23 23
24import { ToggleDarkModeButton } from './ToggleDarkModeButton'; 24import ToggleDarkModeButton from './ToggleDarkModeButton';
25 25
26export function Sidebar(): JSX.Element { 26export default function Sidebar(): JSX.Element {
27 return ( 27 return (
28 <Box 28 <Box
29 sx={(theme) => ({ 29 sx={(theme) => ({
diff --git a/packages/renderer/src/components/StoreProvider.tsx b/packages/renderer/src/components/StoreProvider.tsx
index da1e699..cde6a31 100644
--- a/packages/renderer/src/components/StoreProvider.tsx
+++ b/packages/renderer/src/components/StoreProvider.tsx
@@ -32,7 +32,7 @@ export function useStore(): RendererStore {
32 return store; 32 return store;
33} 33}
34 34
35export function StoreProvider({ children, store }: { 35export default function StoreProvider({ children, store }: {
36 children: JSX.Element | JSX.Element[], 36 children: JSX.Element | JSX.Element[],
37 store: RendererStore, 37 store: RendererStore,
38}): JSX.Element { 38}): JSX.Element {
diff --git a/packages/renderer/src/components/ThemeProvider.tsx b/packages/renderer/src/components/ThemeProvider.tsx
index 9215f5c..eacaa52 100644
--- a/packages/renderer/src/components/ThemeProvider.tsx
+++ b/packages/renderer/src/components/ThemeProvider.tsx
@@ -18,18 +18,18 @@
18 * SPDX-License-Identifier: AGPL-3.0-only 18 * SPDX-License-Identifier: AGPL-3.0-only
19 */ 19 */
20 20
21import { observer } from 'mobx-react-lite';
22import { 21import {
23 unstable_createMuiStrictModeTheme as createTheme, 22 unstable_createMuiStrictModeTheme as createTheme,
24 ThemeProvider as MuiThemeProvider, 23 ThemeProvider as MuiThemeProvider,
25} from '@mui/material/styles'; 24} from '@mui/material/styles';
25import { observer } from 'mobx-react-lite';
26import React from 'react'; 26import React from 'react';
27 27
28import { useStore } from './StoreProvider'; 28import { useStore } from './StoreProvider';
29 29
30export const ThemeProvider = observer(function ThemeProvider({ children }: { 30export default observer(({ children }: {
31 children: JSX.Element | JSX.Element[], 31 children: JSX.Element | JSX.Element[];
32}) { 32}) => {
33 const { shared: { shouldUseDarkColors } } = useStore(); 33 const { shared: { shouldUseDarkColors } } = useStore();
34 34
35 const theme = createTheme({ 35 const theme = createTheme({
diff --git a/packages/renderer/src/components/ToggleDarkModeButton.tsx b/packages/renderer/src/components/ToggleDarkModeButton.tsx
index 1b6757e..c8ffdf0 100644
--- a/packages/renderer/src/components/ToggleDarkModeButton.tsx
+++ b/packages/renderer/src/components/ToggleDarkModeButton.tsx
@@ -18,21 +18,22 @@
18 * SPDX-License-Identifier: AGPL-3.0-only 18 * SPDX-License-Identifier: AGPL-3.0-only
19 */ 19 */
20 20
21import { observer } from 'mobx-react-lite';
22import DarkModeIcon from '@mui/icons-material/DarkMode'; 21import DarkModeIcon from '@mui/icons-material/DarkMode';
23import LightModeIcon from '@mui/icons-material/LightMode'; 22import LightModeIcon from '@mui/icons-material/LightMode';
24import IconButton from '@mui/material/IconButton'; 23import IconButton from '@mui/material/IconButton';
24import { observer } from 'mobx-react-lite';
25import React from 'react'; 25import React from 'react';
26 26
27import { useStore } from './StoreProvider'; 27import { useStore } from './StoreProvider';
28 28
29export const ToggleDarkModeButton = observer(function ToggleDarkModeButton() { 29export default observer(() => {
30 const { shared: { shouldUseDarkColors }, toggleDarkMode } = useStore(); 30 const store = useStore();
31 const { shared: { shouldUseDarkColors } } = store;
31 32
32 return ( 33 return (
33 <IconButton 34 <IconButton
34 aria-label="Toggle dark mode" 35 aria-label="Toggle dark mode"
35 onClick={() => toggleDarkMode()} 36 onClick={() => store.toggleDarkMode()}
36 > 37 >
37 {shouldUseDarkColors ? <LightModeIcon /> : <DarkModeIcon />} 38 {shouldUseDarkColors ? <LightModeIcon /> : <DarkModeIcon />}
38 </IconButton> 39 </IconButton>
diff --git a/packages/renderer/src/devTools.ts b/packages/renderer/src/devTools.ts
index 3ec66aa..3d3ba99 100644
--- a/packages/renderer/src/devTools.ts
+++ b/packages/renderer/src/devTools.ts
@@ -32,31 +32,24 @@ import type { IAnyStateTreeNode } from 'mobx-state-tree';
32 * However, we don't bundle `remotedev` in production, so the call would fail anyways. 32 * However, we don't bundle `remotedev` in production, so the call would fail anyways.
33 * 33 *
34 * @param model The store to connect to the redux devtools. 34 * @param model The store to connect to the redux devtools.
35 * @return A promise that resolves when the store was exposed to the devtools.
35 * @see https://github.com/SocketCluster/socketcluster-client/issues/118#issuecomment-469064682 36 * @see https://github.com/SocketCluster/socketcluster-client/issues/118#issuecomment-469064682
36 */ 37 */
37async function exposeToReduxDevtoolsAsync(model: IAnyStateTreeNode): Promise<void> { 38export async function exposeToReduxDevtools(model: IAnyStateTreeNode): Promise<void> {
38 (window as { global?: unknown }).global = window; 39 (window as { global?: unknown }).global = window;
39 40
41 // Hack to load dev dependencies on demand.
40 const [remotedev, { connectReduxDevtools }] = await Promise.all([ 42 const [remotedev, { connectReduxDevtools }] = await Promise.all([
41 // @ts-ignore 43 // @ts-expect-error `remotedev` has no typings.
42 import('remotedev'), 44 // eslint-disable-next-line import/no-extraneous-dependencies
45 import('remotedev') as unknown,
46 // eslint-disable-next-line import/no-extraneous-dependencies
43 import('mst-middlewares'), 47 import('mst-middlewares'),
44 ]); 48 ]);
45 connectReduxDevtools(remotedev, model); 49 connectReduxDevtools(remotedev, model);
46} 50}
47 51
48/** 52/**
49 * Connects the `model` to the redux devtools extension.
50 *
51 * @param model The store to connect to the redux devtools.
52 */
53export function exposeToReduxDevtools(model: IAnyStateTreeNode): void {
54 exposeToReduxDevtoolsAsync(model).catch((err) => {
55 console.error('Could not connect to Redux devtools', err);
56 });
57}
58
59/**
60 * Sends a message to the main process to reload all services when 53 * Sends a message to the main process to reload all services when
61 * `build/watch.js` sends a reload event on bundle write. 54 * `build/watch.js` sends a reload event on bundle write.
62 */ 55 */
diff --git a/packages/renderer/src/index.tsx b/packages/renderer/src/index.tsx
index 1626bef..d900e50 100644
--- a/packages/renderer/src/index.tsx
+++ b/packages/renderer/src/index.tsx
@@ -26,14 +26,17 @@ import CssBaseline from '@mui/material/CssBaseline';
26import React from 'react'; 26import React from 'react';
27import { render } from 'react-dom'; 27import { render } from 'react-dom';
28 28
29import { App } from './components/App'; 29import App from './components/App';
30import { StoreProvider } from './components/StoreProvider'; 30import StoreProvider from './components/StoreProvider';
31import { ThemeProvider } from './components/ThemeProvider'; 31import ThemeProvider from './components/ThemeProvider';
32import { exposeToReduxDevtools, hotReloadServices } from './devTools'; 32import { exposeToReduxDevtools, hotReloadServices } from './devTools';
33import { createAndConnectRendererStore } from './stores/RendererStore'; 33import { createAndConnectRendererStore } from './stores/RendererStore';
34import { getLogger } from './utils/log';
34 35
35const isDevelopment = import.meta.env.MODE === 'development'; 36const isDevelopment = import.meta.env.MODE === 'development';
36 37
38const log = getLogger('index');
39
37if (isDevelopment) { 40if (isDevelopment) {
38 hotReloadServices(); 41 hotReloadServices();
39 document.title = `[dev] ${document.title}`; 42 document.title = `[dev] ${document.title}`;
@@ -42,7 +45,9 @@ if (isDevelopment) {
42const store = createAndConnectRendererStore(window.sophieRenderer); 45const store = createAndConnectRendererStore(window.sophieRenderer);
43 46
44if (isDevelopment) { 47if (isDevelopment) {
45 exposeToReduxDevtools(store); 48 exposeToReduxDevtools(store).catch((err) => {
49 log.error('Cannot initialize redux devtools', err);
50 });
46} 51}
47 52
48function Root(): JSX.Element { 53function Root(): JSX.Element {
diff --git a/packages/renderer/src/stores/RendererEnv.ts b/packages/renderer/src/stores/RendererEnv.ts
index d687738..f0a5a51 100644
--- a/packages/renderer/src/stores/RendererEnv.ts
+++ b/packages/renderer/src/stores/RendererEnv.ts
@@ -18,10 +18,10 @@
18 * SPDX-License-Identifier: AGPL-3.0-only 18 * SPDX-License-Identifier: AGPL-3.0-only
19 */ 19 */
20 20
21import { getEnv as getAnyEnv, IAnyStateTreeNode } from 'mobx-state-tree';
22import type { Action } from '@sophie/shared'; 21import type { Action } from '@sophie/shared';
22import { getEnv as getAnyEnv, IAnyStateTreeNode } from 'mobx-state-tree';
23 23
24export interface RendererEnv { 24export default interface RendererEnv {
25 dispatchMainAction(action: Action): void; 25 dispatchMainAction(action: Action): void;
26} 26}
27 27
diff --git a/packages/renderer/src/stores/RendererStore.ts b/packages/renderer/src/stores/RendererStore.ts
index 037b212..e684759 100644
--- a/packages/renderer/src/stores/RendererStore.ts
+++ b/packages/renderer/src/stores/RendererStore.ts
@@ -19,19 +19,24 @@
19 */ 19 */
20 20
21import { 21import {
22 applySnapshot,
23 applyPatch,
24 Instance,
25 types,
26} from 'mobx-state-tree';
27import {
28 BrowserViewBounds, 22 BrowserViewBounds,
29 sharedStore, 23 sharedStore,
30 SophieRenderer, 24 SophieRenderer,
31 ThemeSource, 25 ThemeSource,
32} from '@sophie/shared'; 26} from '@sophie/shared';
27import {
28 applySnapshot,
29 applyPatch,
30 Instance,
31 types,
32} from 'mobx-state-tree';
33
34import { getLogger } from '../utils/log';
35
36import type RendererEnv from './RendererEnv';
37import { getEnv } from './RendererEnv';
33 38
34import { getEnv, RendererEnv } from './RendererEnv'; 39const log = getLogger('RendererStore');
35 40
36export const rendererStore = types.model('RendererStore', { 41export const rendererStore = types.model('RendererStore', {
37 shared: types.optional(sharedStore, {}), 42 shared: types.optional(sharedStore, {}),
@@ -81,7 +86,7 @@ export function createAndConnectRendererStore(ipc: SophieRenderer): RendererStor
81 applyPatch(store.shared, patch); 86 applyPatch(store.shared, patch);
82 }, 87 },
83 }).catch((err) => { 88 }).catch((err) => {
84 console.error('Failed to connect to shared store', err); 89 log.error('Failed to connect to shared store', err);
85 }); 90 });
86 91
87 return store; 92 return store;
diff --git a/packages/renderer/src/utils/log.ts b/packages/renderer/src/utils/log.ts
new file mode 100644
index 0000000..c17fc2a
--- /dev/null
+++ b/packages/renderer/src/utils/log.ts
@@ -0,0 +1,50 @@
1/*
2 * Copyright (C) 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
21import loglevel, { Logger } from 'loglevel';
22import prefix from 'loglevel-plugin-prefix';
23
24if (import.meta.env?.DEV) {
25 loglevel.setLevel('debug');
26} else {
27 // No devtools in production, so there's not point to log anything.
28 loglevel.disableAll();
29}
30
31prefix.reg(loglevel);
32prefix.apply(loglevel, {
33 format(level, name, timestamp) {
34 const timeStr = timestamp.toString();
35 const nameStr = typeof name === 'undefined' ? '' : ` ${name}`;
36 return `[${timeStr}] ${level}${nameStr}:`;
37 },
38});
39
40export function getLogger(loggerName: string): Logger {
41 return loglevel.getLogger(loggerName);
42}
43
44export function silenceLogger(): void {
45 loglevel.disableAll();
46 const loggers = loglevel.getLoggers();
47 Object.keys(loggers).forEach((loggerName) => {
48 loggers[loggerName].disableAll();
49 });
50}
diff --git a/packages/renderer/tsconfig.json b/packages/renderer/tsconfig.json
index 8746462..14c3e0c 100644
--- a/packages/renderer/tsconfig.json
+++ b/packages/renderer/tsconfig.json
@@ -1,5 +1,5 @@
1{ 1{
2 "extends": "../../tsconfig.json", 2 "extends": "../../config/tsconfig.base.json",
3 "compilerOptions": { 3 "compilerOptions": {
4 "noEmit": true, 4 "noEmit": true,
5 "jsx": "react", 5 "jsx": "react",
@@ -14,12 +14,14 @@
14 }, 14 },
15 "references": [ 15 "references": [
16 { 16 {
17 "path": "../shared" 17 "path": "../shared/tsconfig.build.json"
18 } 18 }
19 ], 19 ],
20 "include": [ 20 "include": [
21 "src/**/*.ts", 21 "src/**/*.ts",
22 "src/**/*.tsx", 22 "src/**/*.tsx",
23 "types/**/*.d.ts" 23 "types/**/*.d.ts",
24 ".eslintrc.cjs",
25 "vite.config.js"
24 ] 26 ]
25} 27}
diff --git a/packages/renderer/vite.config.js b/packages/renderer/vite.config.js
index bcd1975..6440ead 100644
--- a/packages/renderer/vite.config.js
+++ b/packages/renderer/vite.config.js
@@ -3,10 +3,11 @@
3 3
4import { builtinModules } from 'module'; 4import { builtinModules } from 'module';
5import { join } from 'path'; 5import { join } from 'path';
6
6import react from '@vitejs/plugin-react'; 7import react from '@vitejs/plugin-react';
7 8
8import { banner, chrome } from '../../config/buildConstants.js'; 9import { banner, chrome } from '../../config/buildConstants.js';
9import { fileURLToDirname } from '../../config/utils.js'; 10import fileURLToDirname from '../../config/fileURLToDirname.js';
10 11
11const thisDir = fileURLToDirname(import.meta.url); 12const thisDir = fileURLToDirname(import.meta.url);
12 13
@@ -45,7 +46,7 @@ export default {
45 preserveSymlinks: true, 46 preserveSymlinks: true,
46 }, 47 },
47 optimizeDeps: { 48 optimizeDeps: {
48 link: [ 49 exclude: [
49 '@sophie/shared', 50 '@sophie/shared',
50 ], 51 ],
51 }, 52 },