diff --git a/packages/react-devtools-extensions/src/main/index.js b/packages/react-devtools-extensions/src/main/index.js index e1db3d5055..b0210bf8b6 100644 --- a/packages/react-devtools-extensions/src/main/index.js +++ b/packages/react-devtools-extensions/src/main/index.js @@ -5,7 +5,7 @@ import {flushSync} from 'react-dom'; import {createRoot} from 'react-dom/client'; import Bridge from 'react-devtools-shared/src/bridge'; import Store from 'react-devtools-shared/src/devtools/store'; -import {getBrowserTheme} from '../utils'; +import {getBrowserTheme, listenToDevToolsThemeChange} from '../utils'; import { localStorageGetItem, localStorageSetItem, @@ -152,6 +152,7 @@ function createBridgeAndStore() { createElement(DevTools, { bridge, browserTheme: getBrowserTheme(), + browserThemeListener: listenToDevToolsThemeChange, componentsPortalContainer, enabledInspectedElementContextMenu: true, fetchFileWithCaching, diff --git a/packages/react-devtools-extensions/src/utils.js b/packages/react-devtools-extensions/src/utils.js index 3219b58ebc..de35e72f3e 100644 --- a/packages/react-devtools-extensions/src/utils.js +++ b/packages/react-devtools-extensions/src/utils.js @@ -1,6 +1,6 @@ /* global chrome */ -import type {BrowserTheme} from 'react-devtools-shared/src/devtools/views/DevTools'; +import type {BrowserTheme, BrowserThemeListenerUnsubscribe} from 'react-devtools-shared/src/devtools/views/DevTools'; export function getBrowserTheme(): BrowserTheme { if (__IS_CHROME__) { @@ -21,5 +21,17 @@ export function getBrowserTheme(): BrowserTheme { } } +export function listenToDevToolsThemeChange(callback: ((newTheme: BrowserTheme) => void)): BrowserThemeListenerUnsubscribe { + try { + chrome.devtools.panels.setThemeChangeHandler(theme => { + callback(theme); + }); + } catch (e) { + console.warn('couldn\'t set up the dev tools theme change listener.'); + } + // TODO: no way to unsubscribe from "setThemeChangeHandler" + return () => {}; +} + export const COMPACT_VERSION_NAME = 'compact'; export const EXTENSION_CONTAINED_VERSIONS = [COMPACT_VERSION_NAME]; diff --git a/packages/react-devtools-inline/src/frontend.js b/packages/react-devtools-inline/src/frontend.js index 9031f6ffc7..1870bc04c8 100644 --- a/packages/react-devtools-inline/src/frontend.js +++ b/packages/react-devtools-inline/src/frontend.js @@ -13,6 +13,7 @@ import { getHideConsoleLogsInStrictMode, } from 'react-devtools-shared/src/utils'; +import type {BrowserTheme} from 'react-devtools-shared/src/devtools/views/DevTools'; import type {Wall} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; import type {Props} from 'react-devtools-shared/src/devtools/views/DevTools'; @@ -91,8 +92,21 @@ export function initialize( frontendBridge.addListener('getSavedPreferences', onGetSavedPreferences); + function listenToBrowserThemeChange(callback: () => BrowserTheme): void { + window.matchMedia('(prefers-color-scheme: dark)')?.addEventListener?.('change', event => { + callback(event.matches ? 'dark' : 'light'); + console.log('new browser theme:', event.matches ? 'dark' : 'light'); + }); + } + const ForwardRef = forwardRef((props, ref) => ( - + )); ForwardRef.displayName = 'DevTools'; diff --git a/packages/react-devtools-shared/src/devtools/views/DevTools.js b/packages/react-devtools-shared/src/devtools/views/DevTools.js index 23504b6832..0b43603ff3 100644 --- a/packages/react-devtools-shared/src/devtools/views/DevTools.js +++ b/packages/react-devtools-shared/src/devtools/views/DevTools.js @@ -66,9 +66,13 @@ export type CanViewElementSource = ( symbolicatedSource: Source | null, ) => boolean; +export type BrowserThemeListenerUnsubscribe = () => void; +export type BrowserThemeListener = (callback: ((newTheme: BrowserTheme) => void)) => BrowserThemeListenerUnsubscribe; + export type Props = { bridge: FrontendBridge, browserTheme?: BrowserTheme, + browserThemeListener?: BrowserThemeListener, canViewElementSourceFunction?: ?CanViewElementSource, defaultTab?: TabID, enabledInspectedElementContextMenu?: boolean, @@ -123,6 +127,7 @@ const tabs = [componentsTab, profilerTab]; export default function DevTools({ bridge, browserTheme: initialBrowserTheme = 'light', + browserThemeListener = () => () => {}, canViewElementSourceFunction, componentsPortalContainer, defaultTab = 'components', @@ -146,15 +151,10 @@ export default function DevTools({ }: Props): React.Node { const [browserTheme, setBrowserTheme] = useState(initialBrowserTheme); useEffect(() => { - global?.window?.matchMedia('(prefers-color-scheme: dark)')?.addEventListener?.('change', event => { - setBrowserTheme(event.matches ? 'dark' : 'light'); - console.log('new browser theme:', event.matches ? 'dark' : 'light'); - }); - - global?.browser?.devtools?.panels?.onThemeChanged?.addListener(theme => { - setBrowserTheme(theme); - console.log('new panels theme:', theme); - }); + const unsubscribe = browserThemeListener(newTheme => setBrowserTheme(newTheme)); + return () => { + unsubscribe() + }; }, []); const [currentTab, setTab] = useLocalStorage(