Files
jrshikoku/lib/theme/useThemeColors.tsx

72 lines
1.9 KiB
TypeScript

import React, { createContext, useContext, FC, PropsWithChildren, useMemo, useState, useEffect, useCallback } from "react";
import { useColorScheme } from "react-native";
import {
lightColors,
darkColors,
fixedColors,
type ThemeColorScheme,
} from "./colors";
import { AS } from "@/storageControl";
import { STORAGE_KEYS } from "@/constants";
export type ColorThemePref = "light" | "system" | "dark";
type ThemeContextValue = {
colors: ThemeColorScheme;
fixed: typeof fixedColors;
isDark: boolean;
colorTheme: ColorThemePref;
setColorTheme: (v: ColorThemePref) => void;
};
const ThemeContext = createContext<ThemeContextValue>({
colors: lightColors,
fixed: fixedColors,
isDark: false,
colorTheme: "light",
setColorTheme: () => {},
});
export const AppThemeProvider: FC<PropsWithChildren> = ({ children }) => {
const systemScheme = useColorScheme();
const [colorTheme, setColorThemeState] = useState<ColorThemePref>("light");
useEffect(() => {
AS.getItem(STORAGE_KEYS.COLOR_THEME)
.then((v: string) => {
if (v === "light" || v === "system" || v === "dark") {
setColorThemeState(v);
}
})
.catch(() => {});
}, []);
const setColorTheme = useCallback((v: ColorThemePref) => {
setColorThemeState(v);
AS.setItem(STORAGE_KEYS.COLOR_THEME, v);
}, []);
const isDark =
colorTheme === "dark" ? true
: colorTheme === "light" ? false
: systemScheme === "dark";
const value = useMemo<ThemeContextValue>(
() => ({
colors: isDark ? darkColors : lightColors,
fixed: fixedColors,
isDark,
colorTheme,
setColorTheme,
}),
[isDark, colorTheme, setColorTheme]
);
return (
<ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
);
};
/** テーマカラーを取得するフック */
export const useThemeColors = () => useContext(ThemeContext);