Files
ViGent2/frontend/src/hooks/useHomePersistence.ts
Kevin Wong 22ea3dd0db 更新
2026-02-04 16:54:59 +08:00

254 lines
8.4 KiB
TypeScript

import { useEffect, useState } from "react";
const TITLE_MAX_LENGTH = 15;
const clampTitle = (value: string) => value.slice(0, TITLE_MAX_LENGTH);
interface RefAudio {
id: string;
name: string;
path: string;
ref_text: string;
duration_sec: number;
created_at: number;
}
interface UseHomePersistenceOptions {
isAuthLoading: boolean;
storageKey: string;
text: string;
setText: React.Dispatch<React.SetStateAction<string>>;
videoTitle: string;
setVideoTitle: React.Dispatch<React.SetStateAction<string>>;
enableSubtitles: boolean;
setEnableSubtitles: React.Dispatch<React.SetStateAction<boolean>>;
ttsMode: 'edgetts' | 'voiceclone';
setTtsMode: React.Dispatch<React.SetStateAction<'edgetts' | 'voiceclone'>>;
voice: string;
setVoice: React.Dispatch<React.SetStateAction<string>>;
selectedMaterial: string;
setSelectedMaterial: React.Dispatch<React.SetStateAction<string>>;
selectedSubtitleStyleId: string;
setSelectedSubtitleStyleId: React.Dispatch<React.SetStateAction<string>>;
selectedTitleStyleId: string;
setSelectedTitleStyleId: React.Dispatch<React.SetStateAction<string>>;
subtitleFontSize: number;
setSubtitleFontSize: React.Dispatch<React.SetStateAction<number>>;
titleFontSize: number;
setTitleFontSize: React.Dispatch<React.SetStateAction<number>>;
setSubtitleSizeLocked: React.Dispatch<React.SetStateAction<boolean>>;
setTitleSizeLocked: React.Dispatch<React.SetStateAction<boolean>>;
selectedBgmId: string;
setSelectedBgmId: React.Dispatch<React.SetStateAction<string>>;
bgmVolume: number;
setBgmVolume: React.Dispatch<React.SetStateAction<number>>;
enableBgm: boolean;
setEnableBgm: React.Dispatch<React.SetStateAction<boolean>>;
selectedVideoId: string | null;
setSelectedVideoId: React.Dispatch<React.SetStateAction<string | null>>;
selectedRefAudio: RefAudio | null;
}
export const useHomePersistence = ({
isAuthLoading,
storageKey,
text,
setText,
videoTitle,
setVideoTitle,
enableSubtitles,
setEnableSubtitles,
ttsMode,
setTtsMode,
voice,
setVoice,
selectedMaterial,
setSelectedMaterial,
selectedSubtitleStyleId,
setSelectedSubtitleStyleId,
selectedTitleStyleId,
setSelectedTitleStyleId,
subtitleFontSize,
setSubtitleFontSize,
titleFontSize,
setTitleFontSize,
setSubtitleSizeLocked,
setTitleSizeLocked,
selectedBgmId,
setSelectedBgmId,
bgmVolume,
setBgmVolume,
enableBgm,
setEnableBgm,
selectedVideoId,
setSelectedVideoId,
selectedRefAudio,
}: UseHomePersistenceOptions) => {
const [isRestored, setIsRestored] = useState(false);
useEffect(() => {
if (isAuthLoading) return;
const savedText = localStorage.getItem(`vigent_${storageKey}_text`);
const savedTitle = localStorage.getItem(`vigent_${storageKey}_title`);
const savedSubtitles = localStorage.getItem(`vigent_${storageKey}_subtitles`);
const savedTtsMode = localStorage.getItem(`vigent_${storageKey}_ttsMode`);
const savedVoice = localStorage.getItem(`vigent_${storageKey}_voice`);
const savedMaterial = localStorage.getItem(`vigent_${storageKey}_material`);
const savedSubtitleStyle = localStorage.getItem(`vigent_${storageKey}_subtitleStyle`);
const savedTitleStyle = localStorage.getItem(`vigent_${storageKey}_titleStyle`);
const savedSubtitleFontSize = localStorage.getItem(`vigent_${storageKey}_subtitleFontSize`);
const savedTitleFontSize = localStorage.getItem(`vigent_${storageKey}_titleFontSize`);
const savedBgmId = localStorage.getItem(`vigent_${storageKey}_bgmId`);
const savedSelectedVideoId = localStorage.getItem(`vigent_${storageKey}_selectedVideoId`);
const savedBgmVolume = localStorage.getItem(`vigent_${storageKey}_bgmVolume`);
const savedEnableBgm = localStorage.getItem(`vigent_${storageKey}_enableBgm`);
setText(savedText || "大家好,欢迎来到我的频道,今天给大家分享一些有趣的内容。");
setVideoTitle(savedTitle ? clampTitle(savedTitle) : "");
setEnableSubtitles(savedSubtitles !== null ? savedSubtitles === 'true' : true);
setTtsMode((savedTtsMode as 'edgetts' | 'voiceclone') || 'edgetts');
setVoice(savedVoice || "zh-CN-YunxiNeural");
if (savedMaterial) setSelectedMaterial(savedMaterial);
if (savedSubtitleStyle) setSelectedSubtitleStyleId(savedSubtitleStyle);
if (savedTitleStyle) setSelectedTitleStyleId(savedTitleStyle);
if (savedSubtitleFontSize) {
const parsed = parseInt(savedSubtitleFontSize, 10);
if (!Number.isNaN(parsed)) {
setSubtitleFontSize(parsed);
setSubtitleSizeLocked(true);
}
}
if (savedTitleFontSize) {
const parsed = parseInt(savedTitleFontSize, 10);
if (!Number.isNaN(parsed)) {
setTitleFontSize(parsed);
setTitleSizeLocked(true);
}
}
if (savedBgmId) setSelectedBgmId(savedBgmId);
if (savedBgmVolume) setBgmVolume(parseFloat(savedBgmVolume));
if (savedEnableBgm !== null) setEnableBgm(savedEnableBgm === 'true');
if (savedSelectedVideoId) setSelectedVideoId(savedSelectedVideoId);
setIsRestored(true);
}, [
isAuthLoading,
setBgmVolume,
setEnableBgm,
setEnableSubtitles,
setSelectedBgmId,
setSelectedMaterial,
setSelectedSubtitleStyleId,
setSelectedTitleStyleId,
setSelectedVideoId,
setSubtitleFontSize,
setSubtitleSizeLocked,
setText,
setTitleFontSize,
setTitleSizeLocked,
setTtsMode,
setVideoTitle,
setVoice,
storageKey,
]);
useEffect(() => {
if (!isRestored) return;
const timeout = setTimeout(() => {
localStorage.setItem(`vigent_${storageKey}_text`, text);
}, 300);
return () => clearTimeout(timeout);
}, [text, storageKey, isRestored]);
useEffect(() => {
if (!isRestored) return;
const timeout = setTimeout(() => {
localStorage.setItem(`vigent_${storageKey}_title`, videoTitle);
}, 300);
return () => clearTimeout(timeout);
}, [videoTitle, storageKey, isRestored]);
useEffect(() => {
if (isRestored) localStorage.setItem(`vigent_${storageKey}_subtitles`, String(enableSubtitles));
}, [enableSubtitles, storageKey, isRestored]);
useEffect(() => {
if (isRestored) localStorage.setItem(`vigent_${storageKey}_ttsMode`, ttsMode);
}, [ttsMode, storageKey, isRestored]);
useEffect(() => {
if (isRestored) localStorage.setItem(`vigent_${storageKey}_voice`, voice);
}, [voice, storageKey, isRestored]);
useEffect(() => {
if (isRestored && selectedMaterial) {
localStorage.setItem(`vigent_${storageKey}_material`, selectedMaterial);
}
}, [selectedMaterial, storageKey, isRestored]);
useEffect(() => {
if (isRestored && selectedSubtitleStyleId) {
localStorage.setItem(`vigent_${storageKey}_subtitleStyle`, selectedSubtitleStyleId);
}
}, [selectedSubtitleStyleId, storageKey, isRestored]);
useEffect(() => {
if (isRestored && selectedTitleStyleId) {
localStorage.setItem(`vigent_${storageKey}_titleStyle`, selectedTitleStyleId);
}
}, [selectedTitleStyleId, storageKey, isRestored]);
useEffect(() => {
if (isRestored) {
localStorage.setItem(`vigent_${storageKey}_subtitleFontSize`, String(subtitleFontSize));
}
}, [subtitleFontSize, storageKey, isRestored]);
useEffect(() => {
if (isRestored) {
localStorage.setItem(`vigent_${storageKey}_titleFontSize`, String(titleFontSize));
}
}, [titleFontSize, storageKey, isRestored]);
useEffect(() => {
if (isRestored) {
localStorage.setItem(`vigent_${storageKey}_bgmId`, selectedBgmId);
}
}, [selectedBgmId, storageKey, isRestored]);
useEffect(() => {
if (!isRestored) return;
const timeout = setTimeout(() => {
localStorage.setItem(`vigent_${storageKey}_bgmVolume`, String(bgmVolume));
}, 300);
return () => clearTimeout(timeout);
}, [bgmVolume, storageKey, isRestored]);
useEffect(() => {
if (isRestored) {
localStorage.setItem(`vigent_${storageKey}_enableBgm`, String(enableBgm));
}
}, [enableBgm, storageKey, isRestored]);
useEffect(() => {
if (!isRestored) return;
if (selectedVideoId) {
localStorage.setItem(`vigent_${storageKey}_selectedVideoId`, selectedVideoId);
} else {
localStorage.removeItem(`vigent_${storageKey}_selectedVideoId`);
}
}, [selectedVideoId, storageKey, isRestored]);
useEffect(() => {
if (isRestored && selectedRefAudio) {
localStorage.setItem(`vigent_${storageKey}_refAudioId`, selectedRefAudio.id);
}
}, [selectedRefAudio, storageKey, isRestored]);
return { isRestored };
};