telegram-files/web/src/hooks/use-settings.tsx
2024-12-22 20:00:13 +08:00

79 lines
2.1 KiB
TypeScript

"use client";
import React, { createContext, type ReactNode, useContext } from "react";
import useSWR from "swr";
import { type SettingKey, SettingKeys, type Settings } from "@/lib/types";
import { request } from "@/lib/api";
import { toast } from "@/hooks/use-toast";
interface SettingsContextType {
isLoading: boolean;
settings?: Settings;
setSetting: (key: SettingKey, value: string) => Promise<void>;
updateSettings: (updates?: Partial<Settings>) => Promise<void>;
}
const SettingsContext = createContext<SettingsContextType | undefined>(
undefined,
);
interface SettingsProviderProps {
children: ReactNode;
keys?: SettingKey[];
}
export const SettingsProvider: React.FC<SettingsProviderProps> = ({
children,
keys = [...SettingKeys],
}) => {
const {
data: settings,
isLoading,
mutate,
} = useSWR(
keys,
(keys) =>
request(`/settings?keys=${keys.join(",")}`).then(
(data) => data as Settings,
),
{
revalidateOnFocus: false,
},
);
// 更新配置项方法
const updateSettings = async (updates?: Partial<Settings>) => {
await request("/settings/create", {
body: updates ? JSON.stringify(updates) : JSON.stringify(settings),
method: "POST",
});
// 更新缓存
if (updates) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
await mutate((current) => ({ ...current, ...updates }), false);
}
toast({ title: "Success", description: "Settings updated" });
};
const setSetting = async (key: SettingKey, value: string) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
await mutate((current) => ({ ...current, [key]: value }), false);
};
return (
<SettingsContext.Provider
value={{ isLoading, settings: settings, setSetting, updateSettings }}
>
{children}
</SettingsContext.Provider>
);
};
export const useSettings = (): SettingsContextType => {
const context = useContext(SettingsContext);
if (!context) {
throw new Error("useSettings must be used within a SettingsProvider");
}
return context;
};