104 lines
3.0 KiB
TypeScript
104 lines
3.0 KiB
TypeScript
import { useCallback, useEffect, useState } from "react";
|
|
import api from "@/shared/api/axios";
|
|
import { ApiResponse, unwrap } from "@/shared/api/types";
|
|
|
|
export interface SubtitleStyleOption {
|
|
id: string;
|
|
label: string;
|
|
font_family?: string;
|
|
font_file?: string;
|
|
font_size?: number;
|
|
highlight_color?: string;
|
|
normal_color?: string;
|
|
stroke_color?: string;
|
|
stroke_size?: number;
|
|
letter_spacing?: number;
|
|
bottom_margin?: number;
|
|
is_default?: boolean;
|
|
}
|
|
|
|
export interface TitleStyleOption {
|
|
id: string;
|
|
label: string;
|
|
font_family?: string;
|
|
font_file?: string;
|
|
font_size?: number;
|
|
color?: string;
|
|
stroke_color?: string;
|
|
stroke_size?: number;
|
|
letter_spacing?: number;
|
|
font_weight?: number;
|
|
top_margin?: number;
|
|
is_default?: boolean;
|
|
}
|
|
|
|
interface UseTitleSubtitleStylesOptions {
|
|
isAuthLoading: boolean;
|
|
|
|
setSelectedSubtitleStyleId: React.Dispatch<React.SetStateAction<string>>;
|
|
setSelectedTitleStyleId: React.Dispatch<React.SetStateAction<string>>;
|
|
}
|
|
|
|
export const useTitleSubtitleStyles = ({
|
|
isAuthLoading,
|
|
|
|
setSelectedSubtitleStyleId,
|
|
setSelectedTitleStyleId,
|
|
}: UseTitleSubtitleStylesOptions) => {
|
|
const [subtitleStyles, setSubtitleStyles] = useState<SubtitleStyleOption[]>([]);
|
|
const [titleStyles, setTitleStyles] = useState<TitleStyleOption[]>([]);
|
|
|
|
const refreshSubtitleStyles = useCallback(async () => {
|
|
try {
|
|
const { data: res } = await api.get<ApiResponse<{ styles: SubtitleStyleOption[] }>>(
|
|
'/api/assets/subtitle-styles'
|
|
);
|
|
const payload = unwrap(res);
|
|
const styles: SubtitleStyleOption[] = payload.styles || [];
|
|
setSubtitleStyles(styles);
|
|
|
|
setSelectedSubtitleStyleId((prev) => {
|
|
if (prev && styles.some((s) => s.id === prev)) return prev;
|
|
const defaultStyle = styles.find((s) => s.is_default) || styles[0];
|
|
return defaultStyle?.id || "";
|
|
});
|
|
} catch (error) {
|
|
console.error("获取字幕样式失败:", error);
|
|
}
|
|
}, [setSelectedSubtitleStyleId]);
|
|
|
|
const refreshTitleStyles = useCallback(async () => {
|
|
try {
|
|
const { data: res } = await api.get<ApiResponse<{ styles: TitleStyleOption[] }>>(
|
|
'/api/assets/title-styles'
|
|
);
|
|
const payload = unwrap(res);
|
|
const styles: TitleStyleOption[] = payload.styles || [];
|
|
setTitleStyles(styles);
|
|
|
|
setSelectedTitleStyleId((prev) => {
|
|
if (prev && styles.some((s) => s.id === prev)) return prev;
|
|
const defaultStyle = styles.find((s) => s.is_default) || styles[0];
|
|
return defaultStyle?.id || "";
|
|
});
|
|
} catch (error) {
|
|
console.error("获取标题样式失败:", error);
|
|
}
|
|
}, [setSelectedTitleStyleId]);
|
|
|
|
useEffect(() => {
|
|
if (isAuthLoading) return;
|
|
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
refreshSubtitleStyles();
|
|
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
refreshTitleStyles();
|
|
}, [isAuthLoading, refreshSubtitleStyles, refreshTitleStyles]);
|
|
|
|
return {
|
|
subtitleStyles,
|
|
titleStyles,
|
|
refreshSubtitleStyles,
|
|
refreshTitleStyles,
|
|
};
|
|
};
|