58 lines
1.5 KiB
TypeScript
58 lines
1.5 KiB
TypeScript
// Copyright 2022 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
import { useState, useEffect } from 'react';
|
|
|
|
import { ThemeType } from '../types/Util';
|
|
|
|
// Note that this hook is used in non-main windows (e.g. "About" and
|
|
// "Debug Log" windows), and thus can't access redux state.
|
|
export const useTheme = (): ThemeType => {
|
|
const [theme, updateTheme] = useState(ThemeType.light);
|
|
|
|
// Storybook support
|
|
const { SignalContext } = window;
|
|
|
|
useEffect(() => {
|
|
const abortController = new AbortController();
|
|
|
|
const { signal } = abortController;
|
|
|
|
async function applyTheme() {
|
|
let newTheme = await SignalContext.Settings.themeSetting.getValue();
|
|
if (newTheme === 'system') {
|
|
newTheme = SignalContext.nativeThemeListener.getSystemTheme();
|
|
}
|
|
|
|
if (signal.aborted) {
|
|
return;
|
|
}
|
|
|
|
if (newTheme === 'dark') {
|
|
updateTheme(ThemeType.dark);
|
|
} else {
|
|
updateTheme(ThemeType.light);
|
|
}
|
|
}
|
|
|
|
async function loop() {
|
|
while (!signal.aborted) {
|
|
// eslint-disable-next-line no-await-in-loop
|
|
await applyTheme();
|
|
|
|
// eslint-disable-next-line no-await-in-loop
|
|
await SignalContext.Settings.waitForChange();
|
|
}
|
|
}
|
|
|
|
SignalContext.nativeThemeListener.subscribe(applyTheme);
|
|
void loop();
|
|
|
|
return () => {
|
|
abortController.abort();
|
|
SignalContext.nativeThemeListener.unsubscribe(applyTheme);
|
|
};
|
|
}, [updateTheme, SignalContext.Settings, SignalContext.nativeThemeListener]);
|
|
|
|
return theme;
|
|
};
|