insomnia/packages/insomnia-app/app/ui/hooks/theme.ts
2021-08-10 23:57:13 +00:00

84 lines
2.5 KiB
TypeScript

import { ChangeEvent, useCallback, useState } from 'react';
import { useSelector } from 'react-redux';
import { useAsync } from 'react-use';
import { unreachableCase } from 'ts-assert-unreachable';
import * as models from '../../models';
import { ThemeSettings } from '../../models/settings';
import { ColorScheme, getThemes } from '../../plugins';
import { applyColorScheme, PluginTheme } from '../../plugins/misc';
import { selectSettings } from '../redux/selectors';
export const useThemes = () => {
const {
lightTheme,
darkTheme,
autoDetectColorScheme,
theme,
pluginConfig,
} = useSelector(selectSettings);
const [themes, setThemes] = useState<PluginTheme[]>([]);
useAsync(async () => {
const pluginThemes = await getThemes();
setThemes(pluginThemes.map(({ theme }) => theme));
// eslint-disable-next-line react-hooks/exhaustive-deps -- Reload themes if pluginConfig changes
}, [pluginConfig]);
// Check if the theme is active
const isActiveDark = useCallback(({ name }: PluginTheme) => name === darkTheme, [darkTheme]);
const isActiveLight = useCallback(({ name }: PluginTheme) => name === lightTheme, [lightTheme]);
const isActive = useCallback((pluginTheme : PluginTheme) => {
if (autoDetectColorScheme) {
return isActiveLight(pluginTheme) || isActiveDark(pluginTheme);
}
return pluginTheme.name === theme;
}, [autoDetectColorScheme, isActiveDark, isActiveLight, theme]);
// Apply the theme and update settings
const apply = useCallback(async (patch: Partial<ThemeSettings>) => {
applyColorScheme({
theme,
autoDetectColorScheme,
darkTheme,
lightTheme,
...patch,
});
await models.settings.patch(patch);
}, [autoDetectColorScheme, darkTheme, lightTheme, theme]);
const changeAutoDetect = useCallback(({ target: { checked } }: ChangeEvent<HTMLInputElement>) => apply({ autoDetectColorScheme: checked }), [apply]);
// Activate the theme for the selected color scheme
const activate = useCallback(async (themeName: string, colorScheme: ColorScheme) => {
switch (colorScheme) {
case 'light':
await apply({ lightTheme: themeName });
break;
case 'dark':
await apply({ darkTheme: themeName });
break;
case 'default':
await apply({ theme: themeName });
break;
default:
unreachableCase(colorScheme);
}
}, [apply]);
return {
themes,
isActive,
isActiveLight,
isActiveDark,
activate,
changeAutoDetect,
autoDetectColorScheme,
};
};