diff --git a/main/index.ts b/main/index.ts index eaf52b42..258a6573 100644 --- a/main/index.ts +++ b/main/index.ts @@ -7,8 +7,6 @@ import toMilliseconds from '@sindresorhus/to-milliseconds'; import './windows/load'; import './utils/sentry'; -require('electron-timber').hookConsole({main: true, renderer: true}); - import {settings} from './common/settings'; import {plugins} from './plugins'; import {initializeTray} from './tray'; @@ -25,6 +23,9 @@ import {windowManager} from './windows/manager'; import {setupProtocol} from './utils/protocol'; import {stopRecordingWithNoEdit} from './aperture'; +const remoteMain = require('@electron/remote/main'); +remoteMain.initialize(); + const prepareNext = require('electron-next'); const filesToOpen: string[] = []; diff --git a/main/plugins/plugin.ts b/main/plugins/plugin.ts index a1a7eded..9f1357ad 100644 --- a/main/plugins/plugin.ts +++ b/main/plugins/plugin.ts @@ -59,7 +59,7 @@ class BasePlugin { } } -export interface KapPlugin { +export interface KapPlugin = any> { shareServices?: Array>; editServices?: Array>; recordServices?: Array>; diff --git a/main/windows/config.ts b/main/windows/config.ts index e799d070..67414ab1 100644 --- a/main/windows/config.ts +++ b/main/windows/config.ts @@ -7,6 +7,8 @@ import pEvent from 'p-event'; import {loadRoute} from '../utils/routes'; import {windowManager} from './manager'; +const remoteMain = require('@electron/remote/main'); + const openConfigWindow = async (pluginName: string) => { const prefsWindow = await windowManager.preferences?.open(); const configWindow = new BrowserWindow({ @@ -23,11 +25,12 @@ const openConfigWindow = async (pluginName: string) => { modal: true, webPreferences: { nodeIntegration: true, - enableRemoteModule: true, contextIsolation: false } }); + remoteMain.enable(configWindow.webContents); + loadRoute(configWindow, 'config'); configWindow.webContents.on('did-finish-load', async () => { @@ -53,11 +56,12 @@ const openEditorConfigWindow = async (pluginName: string, serviceTitle: string, modal: true, webPreferences: { nodeIntegration: true, - enableRemoteModule: true, contextIsolation: false } }); + remoteMain.enable(configWindow.webContents); + loadRoute(configWindow, 'config'); configWindow.webContents.on('did-finish-load', async () => { diff --git a/main/windows/cropper.ts b/main/windows/cropper.ts index 895293a8..d0003217 100644 --- a/main/windows/cropper.ts +++ b/main/windows/cropper.ts @@ -12,6 +12,8 @@ const croppers = new Map(); let notificationId: number | undefined; let isOpen = false; +const remoteMain = require('@electron/remote/main'); + const closeAllCroppers = () => { screen.removeAllListeners('display-removed'); screen.removeAllListeners('display-added'); @@ -47,11 +49,12 @@ const openCropper = (display: Display, activeDisplayId?: number) => { show: false, webPreferences: { nodeIntegration: true, - enableRemoteModule: true, contextIsolation: false } }); + remoteMain.enable(cropper.webContents); + loadRoute(cropper, 'cropper'); cropper.setAlwaysOnTop(true, 'screen-saver', 1); diff --git a/main/windows/dialog.ts b/main/windows/dialog.ts index 158af3bd..8d205b72 100644 --- a/main/windows/dialog.ts +++ b/main/windows/dialog.ts @@ -5,6 +5,8 @@ import {ipcMain as ipc} from 'electron-better-ipc'; import {loadRoute} from '../utils/routes'; import {windowManager} from './manager'; +const remoteMain = require('@electron/remote/main'); + const DIALOG_MIN_WIDTH = 420; const DIALOG_MIN_HEIGHT = 150; @@ -26,11 +28,12 @@ const showDialog = async (options: DialogOptions) => new Promise( useContentSize: true, webPreferences: { nodeIntegration: true, - enableRemoteModule: true, contextIsolation: false } }); + remoteMain.enable(dialogWindow.webContents); + loadRoute(dialogWindow, 'dialog'); let buttons: any[]; diff --git a/main/windows/kap-window.ts b/main/windows/kap-window.ts index fdda4074..87303cec 100644 --- a/main/windows/kap-window.ts +++ b/main/windows/kap-window.ts @@ -4,6 +4,8 @@ import pEvent from 'p-event'; import {customApplicationMenu, defaultApplicationMenu, MenuModifier} from '../menus/application'; import {loadRoute} from '../utils/routes'; +const remoteMain = require('@electron/remote/main'); + interface KapWindowOptions extends Electron.BrowserWindowConstructorOptions { route: string; waitForMount?: boolean; @@ -51,13 +53,14 @@ export default class KapWindow { ...rest, webPreferences: { nodeIntegration: true, - enableRemoteModule: true, contextIsolation: false, ...rest.webPreferences }, show: false }); + remoteMain.enable(this.browserWindow.webContents); + this.id = this.browserWindow.id; KapWindow.windows.set(this.id, this); diff --git a/main/windows/preferences.ts b/main/windows/preferences.ts index b6dd366d..347b2ec6 100644 --- a/main/windows/preferences.ts +++ b/main/windows/preferences.ts @@ -7,6 +7,8 @@ import {loadRoute} from '../utils/routes'; import {track} from '../common/analytics'; import {windowManager} from './manager'; +const remoteMain = require('@electron/remote/main'); + let prefsWindow: BrowserWindow | undefined; export type PreferencesWindowOptions = any; @@ -39,11 +41,12 @@ const openPrefsWindow = async (options?: PreferencesWindowOptions) => { vibrancy: 'window', webPreferences: { nodeIntegration: true, - enableRemoteModule: true, contextIsolation: false } }); + remoteMain.enable(prefsWindow.webContents); + const titlebarHeight = 85; prefsWindow.setSheetOffset(titlebarHeight); diff --git a/package.json b/package.json index ee5148b8..fa9526b5 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "build": "yarn build-main && yarn build-renderer", "dist": "npm run build && electron-builder", "pack": "npm run build && electron-builder --dir", - "postinstall": "electron-builder install-app-deps", + "postinstall": "patch-package && electron-builder install-app-deps", "sentry-version": "echo \"$npm_package_name@$npm_package_version\"", "dev": "next dev renderer" }, @@ -33,6 +33,7 @@ "name": "Kap" }, "dependencies": { + "@electron/remote": "^2.0.8", "@sentry/browser": "^6.2.2", "@sentry/electron": "^2.4.0", "@sindresorhus/to-milliseconds": "^1.2.0", @@ -43,14 +44,13 @@ "clean-stack": "^3.0.1", "cp-file": "^9.0.0", "delay": "^5.0.0", - "electron-better-ipc": "^1.1.1", + "electron-better-ipc": "^2.0.1", "electron-log": "^4.3.2", "electron-next": "^3.1.5", "electron-notarize": "^1.1.1", "electron-store": "^7.0.2", - "electron-timber": "^0.5.1", "electron-updater": "^4.3.8", - "electron-util": "^0.14.2", + "electron-util": "^0.17.2", "ensure-error": "^3.0.1", "execa": "5.0.0", "ffmpeg-static": "^4.4.1", @@ -109,7 +109,7 @@ "@typescript-eslint/parser": "^4.15.0", "ava": "^3.15.0", "babel-eslint": "^10.1.0", - "electron": "13.6.9", + "electron": "14.2.9", "electron-builder": "^23.3.3", "electron-builder-notarize": "^1.4.0", "eslint-config-xo": "^0.35.0", @@ -119,7 +119,8 @@ "eslint-plugin-react-hooks": "^4.2.0", "husky": "^4.2.5", "module-alias": "^2.2.2", - "next": "^10.0.8", + "next": "10.2.3", + "patch-package": "^6.5.0", "run-electron": "^1.0.0", "sinon": "^9.2.4", "tap-xunit": "^2.4.1", diff --git a/patches/electron-is-dev+1.2.0.patch b/patches/electron-is-dev+1.2.0.patch new file mode 100644 index 00000000..5f3252e0 --- /dev/null +++ b/patches/electron-is-dev+1.2.0.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/electron-is-dev/index.js b/node_modules/electron-is-dev/index.js +index 3b3fbc5..042a8a5 100644 +--- a/node_modules/electron-is-dev/index.js ++++ b/node_modules/electron-is-dev/index.js +@@ -5,7 +5,7 @@ if (typeof electron === 'string') { + throw new TypeError('Not running in an Electron environment!'); + } + +-const app = electron.app || electron.remote.app; ++const app = electron.app || require('@electron/remote'); + + const isEnvSet = 'ELECTRON_IS_DEV' in process.env; + const getFromEnv = parseInt(process.env.ELECTRON_IS_DEV, 10) === 1; \ No newline at end of file diff --git a/renderer/components/action-bar/controls/main.js b/renderer/components/action-bar/controls/main.js index 79284921..62c3ecf4 100644 --- a/renderer/components/action-bar/controls/main.js +++ b/renderer/components/action-bar/controls/main.js @@ -1,4 +1,3 @@ -import electron from 'electron'; import PropTypes from 'prop-types'; import React from 'react'; import css from 'styled-jsx/css'; @@ -24,11 +23,10 @@ const mainStyle = css` const MainControls = {}; -const remote = electron.remote || false; let menu; const buildMenu = async ({selectedApp}) => { - const {buildWindowsMenu} = remote.require('./utils/windows'); + const {buildWindowsMenu} = await require('@electron/remote').require('./utils/windows'); menu = await buildWindowsMenu(selectedApp); }; @@ -86,7 +84,7 @@ MainControls.Left = connect( class Right extends React.Component { onCogMenuClick = async () => { - const cogMenu = await electron.remote.require('./menus/cog').getCogMenu(); + const cogMenu = await require('@electron/remote').require('./menus/cog').getCogMenu(); cogMenu.popup(); }; diff --git a/renderer/components/action-bar/record-button.js b/renderer/components/action-bar/record-button.js index f7480b95..1d21b8d3 100644 --- a/renderer/components/action-bar/record-button.js +++ b/renderer/components/action-bar/record-button.js @@ -1,4 +1,3 @@ -import electron from 'electron'; import React, {useState, useEffect} from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; @@ -97,8 +96,7 @@ const RecordButton = ({ event.stopPropagation(); if (cropperExists) { - const {remote} = electron; - const {startRecording} = remote.require('./aperture'); + const {startRecording} = require('@electron/remote').require('./aperture'); willStartRecording(); diff --git a/renderer/components/cropper/cursor.js b/renderer/components/cropper/cursor.js index 06eb86ef..d48d95df 100644 --- a/renderer/components/cropper/cursor.js +++ b/renderer/components/cropper/cursor.js @@ -1,4 +1,3 @@ -import electron from 'electron'; import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; @@ -6,7 +5,13 @@ import classNames from 'classnames'; import {connect, CursorContainer, CropperContainer} from '../../containers'; class Cursor extends React.Component { - remote = electron.remote || false; + constructor() { + super(); + + if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') { + this.remote = require('@electron/remote'); + } + } render() { if (!this.remote) { diff --git a/renderer/components/editor/conversion/title-bar.tsx b/renderer/components/editor/conversion/title-bar.tsx index 80fbbecf..cb696639 100644 --- a/renderer/components/editor/conversion/title-bar.tsx +++ b/renderer/components/editor/conversion/title-bar.tsx @@ -2,17 +2,16 @@ import TrafficLights from 'components/traffic-lights'; import {BackPlainIcon, MoreIcon} from 'vectors'; import {UseConversionState} from 'hooks/editor/use-conversion'; import {flags} from '../../../common/flags'; -import {MenuItemConstructorOptions, remote} from 'electron'; +import {MenuItemConstructorOptions} from 'electron'; import {ExportStatus} from '../../../common/types'; import {useMemo} from 'react'; -import {template} from 'lodash'; import IconMenu from '../../icon-menu'; const TitleBar = ({conversion, cancel, copy, retry, showInFolder}: {conversion: UseConversionState; cancel: () => any; copy: () => any; retry: () => any; showInFolder: () => void}) => { - const {api} = require('electron-util'); + const remote = process.type === 'renderer' ? require('@electron/remote') : false; const shouldClose = async () => { if (conversion.status === ExportStatus.inProgress && !flags.get('backgroundEditorConversion')) { - await api.dialog.showMessageBox(remote.getCurrentWindow(), { + await remote.dialog.showMessageBox(remote.getCurrentWindow(), { type: 'info', message: 'Your export will continue in the background. You can access it through the Export History window.', buttons: ['Ok'], diff --git a/renderer/components/editor/options/select.tsx b/renderer/components/editor/options/select.tsx index d78d7544..52a67389 100644 --- a/renderer/components/editor/options/select.tsx +++ b/renderer/components/editor/options/select.tsx @@ -1,7 +1,7 @@ import {DropdownArrowIcon, CancelIcon} from '../../../vectors'; import classNames from 'classnames'; import {useRef} from 'react'; -import {remote, MenuItemConstructorOptions, NativeImage} from 'electron'; +import {MenuItemConstructorOptions, NativeImage} from 'electron'; type Option = { label: string; @@ -48,7 +48,7 @@ const Select = (props: Props) => { const boundingRect = select.current.getBoundingClientRect(); - const {Menu} = remote; + const {Menu} = require('@electron/remote'); const convertToMenuTemplate = (option: Option | Separator): MenuItemConstructorOptions => { if (option.separator) { diff --git a/renderer/components/editor/video-controls-container.tsx b/renderer/components/editor/video-controls-container.tsx index 5737bf40..c684d22d 100644 --- a/renderer/components/editor/video-controls-container.tsx +++ b/renderer/components/editor/video-controls-container.tsx @@ -1,10 +1,9 @@ import {createContainer} from 'unstated-next'; -import electron from 'electron'; import {useRef, useState, useEffect} from 'react'; const useVideoControls = () => { const videoRef = useRef(); - const currentWindow = electron.remote.getCurrentWindow(); + const currentWindow = require('@electron/remote').getCurrentWindow(); const wasPaused = useRef(true); const transitioningPauseState = useRef>(); diff --git a/renderer/components/icon-menu.tsx b/renderer/components/icon-menu.tsx index e85232f3..61855929 100644 --- a/renderer/components/icon-menu.tsx +++ b/renderer/components/icon-menu.tsx @@ -27,8 +27,7 @@ const IconMenu: FunctionComponent = props => { y: Math.round(bottom) }); } else { - const {api} = require('electron-util'); - const menu = api.Menu.buildFromTemplate(props.template); + const menu = require('@electron/remote').Menu.buildFromTemplate(props.template); menu.popup({ x: Math.round(left), y: Math.round(bottom) diff --git a/renderer/components/preferences/categories/general.js b/renderer/components/preferences/categories/general.js index b9816767..b439f3d2 100644 --- a/renderer/components/preferences/categories/general.js +++ b/renderer/components/preferences/categories/general.js @@ -24,7 +24,7 @@ class General extends React.Component { componentDidMount() { this.setState({ - showCursorSupported: electron.remote.require('macos-version').isGreaterThanOrEqualTo('10.13') + showCursorSupported: require('@electron/remote').require('macos-version').isGreaterThanOrEqualTo('10.13') }); } diff --git a/renderer/components/preferences/item/select.js b/renderer/components/preferences/item/select.js index bff00e59..68e1b308 100644 --- a/renderer/components/preferences/item/select.js +++ b/renderer/components/preferences/item/select.js @@ -1,4 +1,3 @@ -import electron from 'electron'; import PropTypes from 'prop-types'; import React from 'react'; @@ -22,11 +21,13 @@ class Select extends React.Component { static getDerivedStateFromProps(nextProps) { const {options, onSelect, selected} = nextProps; - if (!electron.remote || options.length === 0) { + const remote = require('@electron/remote'); + + if (!remote || options.length === 0) { return {}; } - const {Menu, MenuItem} = electron.remote; + const {Menu, MenuItem} = remote; const menu = new Menu(); for (const option of options) { diff --git a/renderer/components/preferences/shortcut-input.js b/renderer/components/preferences/shortcut-input.js index 1f05ba59..17e3f441 100644 --- a/renderer/components/preferences/shortcut-input.js +++ b/renderer/components/preferences/shortcut-input.js @@ -154,7 +154,7 @@ const ShortcutInput = ({shortcut = '', onChange, tabIndex}) => { }; const openMenu = () => { - const {Menu} = require('electron').remote; + const {Menu} = require('@electron/remote'); const menu = Menu.buildFromTemplate(presets.map(accelerator => ({ label: accelerator.split('+').map(key => metaCharacters.get(key) || key).join(''), click: () => { diff --git a/renderer/components/traffic-lights.tsx b/renderer/components/traffic-lights.tsx index 85db10ce..4f26b96a 100644 --- a/renderer/components/traffic-lights.tsx +++ b/renderer/components/traffic-lights.tsx @@ -1,4 +1,3 @@ -import {remote} from 'electron'; import {useState, useEffect, FunctionComponent} from 'react'; interface TrafficLightsProps { @@ -6,8 +5,9 @@ interface TrafficLightsProps { } const TrafficLights: FunctionComponent = props => { - const currentWindow = remote.getCurrentWindow(); const [tint, setTint] = useState('blue'); + const remote = process.type === 'renderer' ? require('@electron/remote') : false; + const currentWindow = remote.getCurrentWindow(); useEffect(() => { const setTintColor = () => { diff --git a/renderer/containers/action-bar.js b/renderer/containers/action-bar.js index acc874b2..85c0adef 100644 --- a/renderer/containers/action-bar.js +++ b/renderer/containers/action-bar.js @@ -1,15 +1,16 @@ -import electron from 'electron'; import {Container} from 'unstated'; const barWidth = 464; const barHeight = 64; export default class ActionBarContainer extends Container { - remote = electron.remote || false; - constructor() { super(); + if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') { + this.remote = require('@electron/remote'); + } + if (!this.remote) { this.state = {}; return; diff --git a/renderer/containers/config.js b/renderer/containers/config.js index 979e696e..ef8e5297 100644 --- a/renderer/containers/config.js +++ b/renderer/containers/config.js @@ -1,8 +1,13 @@ -import electron from 'electron'; import {Container} from 'unstated'; export default class ConfigContainer extends Container { - remote = electron.remote || false; + constructor() { + super(); + + if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') { + this.remote = require('@electron/remote'); + } + } state = {selectedTab: 0}; diff --git a/renderer/containers/cropper.js b/renderer/containers/cropper.js index 03d4dc7c..77e88ddf 100644 --- a/renderer/containers/cropper.js +++ b/renderer/containers/cropper.js @@ -1,4 +1,3 @@ -import electron from 'electron'; import nearestNormalAspectRatio from 'nearest-normal-aspect-ratio'; import {Container} from 'unstated'; @@ -37,11 +36,13 @@ export const findRatioForSize = (width, height) => { }; export default class CropperContainer extends Container { - remote = electron.remote || false; - constructor() { super(); + if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') { + this.remote = require('@electron/remote'); + } + if (!this.remote) { this.state = {}; return; diff --git a/renderer/containers/preferences.js b/renderer/containers/preferences.js index fb988df8..228f0414 100644 --- a/renderer/containers/preferences.js +++ b/renderer/containers/preferences.js @@ -8,7 +8,12 @@ const defaultInputDeviceId = 'asd'; const SETTINGS_ANALYTICS_BLACKLIST = ['kapturesDir']; export default class PreferencesContainer extends Container { - remote = electron.remote || false; + constructor() { + super(); + if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') { + this.remote = require('@electron/remote'); + } + } state = { category: 'general', diff --git a/renderer/hooks/dark-mode.tsx b/renderer/hooks/dark-mode.tsx index 212fadb7..a6b32daf 100644 --- a/renderer/hooks/dark-mode.tsx +++ b/renderer/hooks/dark-mode.tsx @@ -1,12 +1,24 @@ import {useState, useEffect} from 'react'; const useDarkMode = () => { - const {darkMode} = require('electron-util'); - const [isDarkMode, setIsDarkMode] = useState(darkMode.isEnabled); + const {nativeTheme} = require('@electron/remote'); + const [isDarkMode, setIsDarkMode] = useState(nativeTheme.shouldUseDarkColors); + + const onThemeChange = callback => { + const handler = () => { + callback(); + }; + + nativeTheme.on('updated', handler); + + return () => { + nativeTheme.off('update', handler); + }; + }; useEffect(() => { - return darkMode.onChange(() => { - setIsDarkMode(darkMode.isEnabled); + return onThemeChange(() => { + setIsDarkMode(nativeTheme.shouldUseDarkColors); }); }, []); diff --git a/renderer/hooks/editor/use-share-plugins.tsx b/renderer/hooks/editor/use-share-plugins.tsx index 8960bb19..193a16a2 100644 --- a/renderer/hooks/editor/use-share-plugins.tsx +++ b/renderer/hooks/editor/use-share-plugins.tsx @@ -1,5 +1,4 @@ import OptionsContainer from 'components/editor/options-container'; -import {remote} from 'electron'; import {ipcRenderer} from 'electron-better-ipc'; import {useMemo} from 'react'; @@ -26,7 +25,7 @@ const useSharePlugins = () => { serviceTitle: plugin.title, app }, - icon: remote.nativeImage.createFromDataURL(app.icon).resize({width: 16, height: 16}) + icon: require('@electron/remote').nativeImage.createFromDataURL(app.icon).resize({width: 16, height: 16}) })); if (plugin.apps[0].isDefault) { diff --git a/renderer/hooks/editor/use-window-size.tsx b/renderer/hooks/editor/use-window-size.tsx index cfb40237..6acfbdd0 100644 --- a/renderer/hooks/editor/use-window-size.tsx +++ b/renderer/hooks/editor/use-window-size.tsx @@ -1,4 +1,3 @@ -import {remote} from 'electron'; import {useEffect, useRef} from 'react'; import {resizeKeepingCenter} from 'utils/window'; @@ -19,7 +18,7 @@ export const useEditorWindowSizeEffect = (isConversionWindowState: boolean) => { return; } - const window = remote.getCurrentWindow(); + const window = require('@electron/remote').getCurrentWindow(); const bounds = window.getBounds(); if (isConversionWindowState) { diff --git a/renderer/hooks/use-confirmation.tsx b/renderer/hooks/use-confirmation.tsx index c55fa1d9..0b69cf1f 100644 --- a/renderer/hooks/use-confirmation.tsx +++ b/renderer/hooks/use-confirmation.tsx @@ -12,9 +12,9 @@ export const useConfirmation = ( options: UseConfirmationOptions ) => { return useCallback(() => { - const {dialog, remote} = require('electron-util').api; + const remote = process.type === 'renderer' ? require('@electron/remote') : false; - const buttonIndex = dialog.showMessageBoxSync(remote.getCurrentWindow(), { + const buttonIndex = remote.dialog.showMessageBoxSync(remote.getCurrentWindow(), { type: 'question', buttons: [ options.confirmButtonText, diff --git a/renderer/hooks/use-current-window.tsx b/renderer/hooks/use-current-window.tsx deleted file mode 100644 index 39fbb9e7..00000000 --- a/renderer/hooks/use-current-window.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import {remote} from 'electron'; - -export const useCurrentWindow = () => { - return remote.getCurrentWindow(); -}; diff --git a/renderer/pages/cropper.js b/renderer/pages/cropper.js index a11e798e..907c79cb 100644 --- a/renderer/pages/cropper.js +++ b/renderer/pages/cropper.js @@ -22,7 +22,7 @@ actionBarContainer.bindCropper(cropperContainer); let lastRatioLockState = null; export default class CropperPage extends React.Component { - remote = electron.remote || false; + remote = require('@electron/remote') || false; dev = false; @@ -33,7 +33,8 @@ export default class CropperPage extends React.Component { return; } - const {ipcRenderer, remote} = electron; + const {ipcRenderer} = electron; + const remote = require('@electron/remote'); ipcRenderer.on('display', (_, display) => { cropperContainer.setDisplay(display); diff --git a/renderer/utils/global-styles.tsx b/renderer/utils/global-styles.tsx index 326c0165..3a5fa083 100644 --- a/renderer/utils/global-styles.tsx +++ b/renderer/utils/global-styles.tsx @@ -1,22 +1,19 @@ import {useState, useEffect, useMemo} from 'react'; import useDarkMode from '../hooks/dark-mode'; -import {remote} from 'electron'; const GlobalStyles = () => { - const [accentColor, setAccentColor] = useState(remote.systemPreferences.getAccentColor()); + const [accentColor, setAccentColor] = useState(''); const isDarkMode = useDarkMode(); - const systemColors = useMemo(() => { - return systemColorNames - .map(name => `--system-${name}: ${remote.systemPreferences.getColor(name as any)};`) - .join('\n'); - }, [isDarkMode]); - const updateAccentColor = (_, accentColor) => { setAccentColor(accentColor); }; useEffect(() => { + const remote = require('@electron/remote'); + + setAccentColor(remote.systemPreferences.getAccentColor()); + remote.systemPreferences.on('accent-color-changed', updateAccentColor); // Return () => { @@ -24,6 +21,12 @@ const GlobalStyles = () => { // }; }, []); + const systemColors = useMemo(() => { + return systemColorNames + .map(name => `--system-${name}: ${require('@electron/remote').systemPreferences.getColor(name as any)};`) + .join('\n'); + }, [isDarkMode]); + return (