React to theme changes in widget mode

This commit is contained in:
Robin
2024-12-17 19:42:04 -05:00
parent 53fff37d5d
commit 5d8804d7e8
3 changed files with 73 additions and 14 deletions

View File

@@ -5,17 +5,46 @@ SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
import { useLayoutEffect, useRef } from "react";
import { useEffect, useLayoutEffect, useRef, useState } from "react";
import { WidgetApiToWidgetAction } from "matrix-widget-api";
import { type IThemeChangeActionRequest } from "matrix-widget-api/lib/interfaces/ThemeChangeAction";
import { useUrlParams } from "./UrlParams";
import { getUrlParams } from "./UrlParams";
import { widget } from "./widget";
export const useTheme = (): void => {
const { theme: themeName } = useUrlParams();
const [requestedTheme, setRequestedTheme] = useState(
() => getUrlParams().theme,
);
const previousTheme = useRef<string | null>(document.body.classList.item(0));
useEffect(() => {
if (widget) {
const onThemeChange = (
ev: CustomEvent<IThemeChangeActionRequest>,
): void => {
ev.preventDefault();
if ("name" in ev.detail.data && typeof ev.detail.data.name === "string")
setRequestedTheme(ev.detail.data.name);
widget!.api.transport.reply(ev.detail, {});
};
widget.lazyActions.on(WidgetApiToWidgetAction.ThemeChange, onThemeChange);
return (): void => {
widget!.lazyActions.off(
WidgetApiToWidgetAction.ThemeChange,
onThemeChange,
);
};
}
}, []);
useLayoutEffect(() => {
// If the url does not contain a theme props we default to "dark".
const theme = themeName?.includes("light") ? "light" : "dark";
const themeHighContrast = themeName?.includes("high-contrast") ? "-hc" : "";
// If no theme has been explicitly requested we default to dark
const theme = requestedTheme?.includes("light") ? "light" : "dark";
const themeHighContrast = requestedTheme?.includes("high-contrast")
? "-hc"
: "";
const themeString = "cpd-theme-" + theme + themeHighContrast;
if (themeString !== previousTheme.current) {
document.body.classList.remove(
@@ -28,5 +57,5 @@ export const useTheme = (): void => {
previousTheme.current = themeString;
}
document.body.classList.remove("no-theme");
}, [previousTheme, themeName]);
}, [previousTheme, requestedTheme]);
};