From 2743ae05150ffb2b274851b80228c61ff983ccc3 Mon Sep 17 00:00:00 2001 From: rhysd Date: Wed, 28 Aug 2024 18:20:49 +0900 Subject: [PATCH] fix mermaid theme doesn't follow color scheme change --- v2/web/components/Preview.tsx | 4 ++-- v2/web/css.ts | 38 ++++++++++++++++++++++++++++++++++- v2/web/markdown.tsx | 10 +++++++-- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/v2/web/components/Preview.tsx b/v2/web/components/Preview.tsx index b56145b..5d4431e 100644 --- a/v2/web/components/Preview.tsx +++ b/v2/web/components/Preview.tsx @@ -7,7 +7,7 @@ import { WindowBar } from './WindowBar'; import { SideBar } from './SideBar'; import { Article } from './Article'; import { ConfigContext } from './ConfigContext'; -import { IS_DARK } from '../css'; +import { colorScheme } from '../css'; import type { MarkdownReactTree } from '../markdown'; import type { Dispatch, Heading } from '../reducer'; @@ -49,7 +49,7 @@ export const Preview: React.FC = ({ tree, headings, path, dispatch }) => boxSizing?: string; } = {}; if (!vibrant) { - sx.bgcolor = IS_DARK ? 'grey.900' : 'grey.100'; + sx.bgcolor = colorScheme.isDark ? 'grey.900' : 'grey.100'; } if (borderTop) { sx.borderTop = 1; diff --git a/v2/web/css.ts b/v2/web/css.ts index 48e35b3..8b12245 100644 --- a/v2/web/css.ts +++ b/v2/web/css.ts @@ -1,4 +1,40 @@ -export const IS_DARK = window.matchMedia('(prefers-color-scheme: dark)').matches; +import { sendMessage } from './ipc'; +import * as log from './log'; + +type Listener = (isDark: boolean) => void; + +class ColorScheme { + private readonly listeners: Listener[] = []; + private dark: boolean; + + constructor() { + const media = window.matchMedia('(prefers-color-scheme: dark)'); + media.addEventListener('change', this.onEvent.bind(this)); + this.dark = media.matches; + } + + get isDark(): boolean { + return this.dark; + } + + addListener(listener: Listener): void { + this.listeners.push(listener); + } + + private onEvent(event: MediaQueryListEvent): void { + if (this.dark === event.matches) { + return; + } + this.dark = !this.dark; + for (const listener of this.listeners) { + listener(this.dark); + } + sendMessage({ kind: 'reload' }); // Rerender the preview with the changed theme after all callbacks were run + log.debug('prefers-color-scheme media query has changed. isDark:', !this.dark, '->', this.dark); + } +} + +export const colorScheme = new ColorScheme(); export function parseColor(color: string): [number, number, number] | null { if (!color.startsWith('#')) { diff --git a/v2/web/markdown.tsx b/v2/web/markdown.tsx index e29e267..fb2e0d3 100644 --- a/v2/web/markdown.tsx +++ b/v2/web/markdown.tsx @@ -20,7 +20,7 @@ import type { RenderTreeCodeFence, AlertKind, } from './ipc'; -import { IS_DARK } from './css'; +import { colorScheme } from './css'; import * as log from './log'; import { Mermaid } from './components/Mermaid'; @@ -28,6 +28,12 @@ class MermaidRenderer { private initialized = false; private id = 0; + constructor() { + colorScheme.addListener(() => { + this.initialized = false; + }); + } + resetId(): void { this.id = 0; } @@ -36,7 +42,7 @@ class MermaidRenderer { if (this.initialized) { return; } - const theme = IS_DARK ? 'dark' : 'default'; + const theme = colorScheme.isDark ? 'dark' : 'default'; mermaid.initialize({ startOnLoad: false, theme }); log.debug('Initialized mermaid renderer', theme); this.initialized = true;