Integrate React Query for data management and enhance Debug Preferences
- Added React Query for managing API calls related to assistants and voices. - Introduced `useAssistantsQuery` and `useVoicesQuery` hooks for fetching data. - Implemented mutations for creating, updating, and deleting voices using React Query. - Integrated a global `QueryClient` for managing query states and configurations. - Refactored components to utilize the new query hooks, improving data handling and performance. - Added a Zustand store for managing debug preferences, including WebSocket URL and audio settings.
This commit is contained in:
@@ -2,7 +2,13 @@ import React, { useEffect, useMemo, useState, useRef } from 'react';
|
||||
import { Search, Mic2, Play, Pause, Upload, Filter, Plus, Volume2, Pencil, Trash2 } from 'lucide-react';
|
||||
import { Button, Input, Select, TableHeader, TableRow, TableHead, TableCell, Dialog, Badge, LibraryPageShell, TableStatusRow, LibraryActionCell } from '../components/UI';
|
||||
import { Voice } from '../types';
|
||||
import { createVoice, deleteVoice, fetchVoices, previewVoice, updateVoice } from '../services/backendApi';
|
||||
import { previewVoice } from '../services/backendApi';
|
||||
import {
|
||||
useCreateVoiceMutation,
|
||||
useDeleteVoiceMutation,
|
||||
useUpdateVoiceMutation,
|
||||
useVoicesQuery,
|
||||
} from '../services/queries';
|
||||
|
||||
const OPENAI_COMPATIBLE_DEFAULT_MODEL = 'FunAudioLLM/CosyVoice2-0.5B';
|
||||
const OPENAI_COMPATIBLE_DEFAULT_VOICE = 'FunAudioLLM/CosyVoice2-0.5B:anna';
|
||||
@@ -19,7 +25,6 @@ const buildOpenAICompatibleVoiceKey = (rawId: string, model: string): string =>
|
||||
};
|
||||
|
||||
export const VoiceLibraryPage: React.FC = () => {
|
||||
const [voices, setVoices] = useState<Voice[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const [vendorFilter, setVendorFilter] = useState<string>('all');
|
||||
const [genderFilter, setGenderFilter] = useState<'all' | 'Male' | 'Female'>('all');
|
||||
@@ -29,24 +34,15 @@ export const VoiceLibraryPage: React.FC = () => {
|
||||
const [isCloneModalOpen, setIsCloneModalOpen] = useState(false);
|
||||
const [isAddModalOpen, setIsAddModalOpen] = useState(false);
|
||||
const [editingVoice, setEditingVoice] = useState<Voice | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [playLoadingId, setPlayLoadingId] = useState<string | null>(null);
|
||||
const audioRef = useRef<HTMLAudioElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const loadVoices = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
setVoices(await fetchVoices());
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setVoices([]);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
loadVoices();
|
||||
}, []);
|
||||
const voicesQuery = useVoicesQuery();
|
||||
const voices = voicesQuery.data || [];
|
||||
const isLoading = voicesQuery.isLoading;
|
||||
const createVoiceMutation = useCreateVoiceMutation();
|
||||
const updateVoiceMutation = useUpdateVoiceMutation();
|
||||
const deleteVoiceMutation = useDeleteVoiceMutation();
|
||||
|
||||
const vendorOptions = useMemo(
|
||||
() => Array.from(new Set(voices.map((v) => String(v.vendor || '').trim()).filter(Boolean))).sort(),
|
||||
@@ -100,22 +96,19 @@ export const VoiceLibraryPage: React.FC = () => {
|
||||
};
|
||||
|
||||
const handleAddSuccess = async (newVoice: Voice) => {
|
||||
const created = await createVoice(newVoice);
|
||||
setVoices((prev) => [created, ...prev]);
|
||||
await createVoiceMutation.mutateAsync(newVoice);
|
||||
setIsAddModalOpen(false);
|
||||
setIsCloneModalOpen(false);
|
||||
};
|
||||
|
||||
const handleUpdateSuccess = async (id: string, data: Voice) => {
|
||||
const updated = await updateVoice(id, data);
|
||||
setVoices((prev) => prev.map((voice) => (voice.id === id ? updated : voice)));
|
||||
await updateVoiceMutation.mutateAsync({ id, data });
|
||||
setEditingVoice(null);
|
||||
};
|
||||
|
||||
const handleDelete = async (id: string) => {
|
||||
if (!confirm('确认删除该声音吗?该操作不可恢复。')) return;
|
||||
await deleteVoice(id);
|
||||
setVoices((prev) => prev.filter((voice) => voice.id !== id));
|
||||
await deleteVoiceMutation.mutateAsync(id);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user