72 lines
1.9 KiB
TypeScript
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);
|