36 lines
1.2 KiB
TypeScript
36 lines
1.2 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
|
|
export const RD_THEMES = ["paper", "sepia", "night"] as const;
|
|
export type RdTheme = (typeof RD_THEMES)[number];
|
|
export const RD_THEME_LABEL: Record<RdTheme, string> = { paper: "纸", sepia: "米", night: "夜" };
|
|
export const FONT_SIZES = [16, 18, 20, 22, 25, 28];
|
|
|
|
const KEY = "reader-prefs";
|
|
|
|
export interface ReaderPrefs {
|
|
theme: RdTheme;
|
|
sizeIdx: number;
|
|
}
|
|
|
|
export function useReaderPrefs() {
|
|
const [prefs, setPrefs] = useState<ReaderPrefs>(() => {
|
|
try {
|
|
const p = JSON.parse(localStorage.getItem(KEY) ?? "") as ReaderPrefs;
|
|
if (RD_THEMES.includes(p.theme) && Number.isInteger(p.sizeIdx) && p.sizeIdx >= 0 && p.sizeIdx < FONT_SIZES.length)
|
|
return p;
|
|
} catch {
|
|
/* 首次使用或存了坏值 */
|
|
}
|
|
return { theme: "sepia", sizeIdx: 2 };
|
|
});
|
|
useEffect(() => localStorage.setItem(KEY, JSON.stringify(prefs)), [prefs]);
|
|
|
|
return {
|
|
prefs,
|
|
fontSize: FONT_SIZES[prefs.sizeIdx],
|
|
setTheme: (theme: RdTheme) => setPrefs((p) => ({ ...p, theme })),
|
|
bump: (d: number) =>
|
|
setPrefs((p) => ({ ...p, sizeIdx: Math.min(FONT_SIZES.length - 1, Math.max(0, p.sizeIdx + d)) })),
|
|
};
|
|
}
|