diff --git a/v2/web/components/App.tsx b/v2/web/components/App.tsx index 204ec26..ec35dfc 100644 --- a/v2/web/components/App.tsx +++ b/v2/web/components/App.tsx @@ -38,7 +38,6 @@ export const App: React.FC = ({ dispatcher }) => { welcome, headings, currentPath, - theme, } = state; let searchInput; @@ -78,7 +77,7 @@ export const App: React.FC = ({ dispatcher }) => { return ( - + {searchInput} {outlineDialog} {historyDialog} diff --git a/v2/web/components/Preview.tsx b/v2/web/components/Preview.tsx index c8fe09b..b56145b 100644 --- a/v2/web/components/Preview.tsx +++ b/v2/web/components/Preview.tsx @@ -7,8 +7,9 @@ import { WindowBar } from './WindowBar'; import { SideBar } from './SideBar'; import { Article } from './Article'; import { ConfigContext } from './ConfigContext'; +import { IS_DARK } from '../css'; import type { MarkdownReactTree } from '../markdown'; -import type { Dispatch, Heading, Theme } from '../reducer'; +import type { Dispatch, Heading } from '../reducer'; const NAV_RESIZE_DIRECTION = { top: false, @@ -30,11 +31,10 @@ export interface Props { tree: MarkdownReactTree; headings: Heading[]; path: string | null; - theme: Theme; dispatch: Dispatch; } -export const Preview: React.FC = ({ tree, headings, path, theme, dispatch }) => { +export const Preview: React.FC = ({ tree, headings, path, dispatch }) => { const { titleBar, vibrant, borderTop } = useContext(ConfigContext); if (tree.root === null) { @@ -49,7 +49,7 @@ export const Preview: React.FC = ({ tree, headings, path, theme, dispatch boxSizing?: string; } = {}; if (!vibrant) { - sx.bgcolor = theme === 'dark' ? 'grey.900' : 'grey.100'; + sx.bgcolor = IS_DARK ? 'grey.900' : 'grey.100'; } if (borderTop) { sx.borderTop = 1; diff --git a/v2/web/dispatcher.ts b/v2/web/dispatcher.ts index a27d0f2..b0d10a0 100644 --- a/v2/web/dispatcher.ts +++ b/v2/web/dispatcher.ts @@ -1,7 +1,6 @@ import { type Dispatch, type State, - type Theme, INITIAL_STATE, initConfig, notifyAlwaysOnTop, @@ -18,7 +17,6 @@ import { setRecentFiles, setSearchMatcher, welcome, - updateTheme, } from './reducer'; import type { MessageFromMain } from './ipc'; import { ReactMarkdownRenderer } from './markdown'; @@ -39,13 +37,12 @@ export class GlobalDispatcher { }; this.state = INITIAL_STATE; this.keymap = new KeyMapping(); - this.markdown = new ReactMarkdownRenderer(this.state.theme); + this.markdown = new ReactMarkdownRenderer(); } setDispatch(dispatch: Dispatch, state: State): void { this.dispatch = dispatch; this.state = state; - this.markdown.theme = state.theme; } openSearch(): void { @@ -66,10 +63,6 @@ export class GlobalDispatcher { } } - updateTheme(theme: Theme): void { - this.dispatch(updateTheme(theme)); - } - async handleIpcMessage(msg: MessageFromMain): Promise { log.debug('Received IPC message from main:', msg.kind, msg); // This method must not throw exception since the main process call this method like `window.postShibaMessageFromMain(msg)`. diff --git a/v2/web/index.tsx b/v2/web/index.tsx index 9511cb4..469f11f 100644 --- a/v2/web/index.tsx +++ b/v2/web/index.tsx @@ -16,10 +16,6 @@ const dispatcher = new GlobalDispatcher(); // The main process will send IPC events via this global function window.postShibaMessageFromMain = dispatcher.handleIpcMessage.bind(dispatcher); -window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { - dispatcher.updateTheme(event.matches ? 'dark' : 'light'); -}); - const reactRoot = document.getElementById('shiba-root'); if (reactRoot) { createRoot(reactRoot).render(); diff --git a/v2/web/markdown.tsx b/v2/web/markdown.tsx index 97d27d6..df3c847 100644 --- a/v2/web/markdown.tsx +++ b/v2/web/markdown.tsx @@ -20,39 +20,25 @@ import type { RenderTreeCodeFence, AlertKind, } from './ipc'; -import type { Theme } from './reducer'; +import { IS_DARK } from './css'; import * as log from './log'; import { Mermaid } from './components/Mermaid'; -type MermaidTheme = 'default' | 'dark'; - class MermaidRenderer { private initialized = false; private id = 0; - constructor(private theme: MermaidTheme) {} - resetId(): void { this.id = 0; } - setTheme(next: MermaidTheme): void { - if (this.theme === next) { - return; - } - if (this.initialized) { - this.initialized = false; - log.debug('Mermaid will be initialized again since the window theme was changed', this.theme, next); - } - this.theme = next; - } - private initMermaid(): void { if (this.initialized) { return; } - mermaid.initialize({ startOnLoad: false, theme: this.theme }); - log.debug('Initialized mermaid renderer', this.theme); + const theme = IS_DARK ? 'dark' : 'default'; + mermaid.initialize({ startOnLoad: false, theme }); + log.debug('Initialized mermaid renderer', theme); this.initialized = true; } @@ -526,17 +512,8 @@ class RenderTreeToReact { } export class ReactMarkdownRenderer { - private readonly mermaid: MermaidRenderer; - private readonly mathjax: MathJaxRenderer; - - constructor(theme: Theme) { - this.mermaid = new MermaidRenderer(theme === 'light' ? 'default' : 'dark'); - this.mathjax = new MathJaxRenderer(); - } - - set theme(t: Theme) { - this.mermaid.setTheme(t === 'light' ? 'default' : 'dark'); - } + private readonly mermaid = new MermaidRenderer(); + private readonly mathjax = new MathJaxRenderer(); render(tree: RenderTreeElem[]): Promise { this.mermaid.resetId(); diff --git a/v2/web/reducer.ts b/v2/web/reducer.ts index b231f75..3a0f880 100644 --- a/v2/web/reducer.ts +++ b/v2/web/reducer.ts @@ -48,7 +48,6 @@ export interface State { welcome: boolean; headings: Heading[]; currentPath: string | null; - theme: Theme; } export const INITIAL_CONFIG: Config = { @@ -78,7 +77,6 @@ export const INITIAL_STATE: State = { welcome: false, headings: [], currentPath: null, - theme: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light', }; const MAX_HISTORIES = 50; @@ -140,10 +138,6 @@ type Action = } | { kind: 'welcome'; - } - | { - kind: 'theme'; - theme: Theme; }; export type Dispatch = React.Dispatch; @@ -212,11 +206,6 @@ export function reducer(state: State, action: Action): State { return { ...state, config: action.config }; case 'recent_files': return { ...state, files: action.paths }; - case 'theme': - if (action.theme === state.theme) { - return state; - } - return { ...state, theme: action.theme }; case 'welcome': return { ...state, welcome: true }; default: @@ -310,10 +299,6 @@ export function updateHeadings(headings: Heading[]): Action { return { kind: 'headings', headings }; } -export function updateTheme(theme: Theme): Action { - return { kind: 'theme', theme }; -} - export function initConfig(config: Config): Action { return { kind: 'init',