Add voice + speed to indexedDB and config context
This commit is contained in:
parent
55919310a5
commit
e830957598
3 changed files with 30 additions and 9 deletions
|
|
@ -5,6 +5,7 @@ import {
|
|||
ListboxOptions,
|
||||
} from '@headlessui/react';
|
||||
import { ChevronUpDownIcon } from '@/components/icons/Icons';
|
||||
import { useConfig } from '@/contexts/ConfigContext';
|
||||
|
||||
const speedOptions = [
|
||||
{ value: 0.5, label: '0.5x' },
|
||||
|
|
@ -22,11 +23,16 @@ export const SpeedControl = ({ speed, setSpeedAndRestart }: {
|
|||
speed: number;
|
||||
setSpeedAndRestart: (speed: number) => void;
|
||||
}) => {
|
||||
const { voiceSpeed } = useConfig();
|
||||
|
||||
// Use voiceSpeed as the source of truth
|
||||
const currentSpeed = voiceSpeed;
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<Listbox value={speed} onChange={setSpeedAndRestart}>
|
||||
<Listbox value={currentSpeed} onChange={setSpeedAndRestart}>
|
||||
<ListboxButton className="flex items-center space-x-1 bg-transparent text-foreground text-sm focus:outline-none cursor-pointer hover:bg-offbase rounded pl-2 pr-1 py-1">
|
||||
<span>{speed}x</span>
|
||||
<span>{currentSpeed}x</span>
|
||||
<ChevronUpDownIcon className="h-3 w-3" />
|
||||
</ListboxButton>
|
||||
<ListboxOptions className="absolute bottom-full mb-1 w-24 overflow-auto rounded-lg bg-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||
|
|
|
|||
|
|
@ -5,17 +5,23 @@ import {
|
|||
ListboxOptions,
|
||||
} from '@headlessui/react';
|
||||
import { ChevronUpDownIcon } from '@/components/icons/Icons';
|
||||
import { useConfig } from '@/contexts/ConfigContext';
|
||||
|
||||
export const VoicesControl = ({ voice, availableVoices, setVoiceAndRestart }: {
|
||||
voice: string;
|
||||
availableVoices: string[];
|
||||
setVoiceAndRestart: (voice: string) => void;
|
||||
}) => {
|
||||
const { voice: configVoice } = useConfig();
|
||||
|
||||
// Use configVoice as the source of truth
|
||||
const currentVoice = configVoice;
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<Listbox value={voice} onChange={setVoiceAndRestart}>
|
||||
<Listbox value={currentVoice} onChange={setVoiceAndRestart}>
|
||||
<ListboxButton className="flex items-center space-x-1 bg-transparent text-foreground text-sm focus:outline-none cursor-pointer hover:bg-offbase rounded pl-2 pr-1 py-1">
|
||||
<span>{voice}</span>
|
||||
<span>{currentVoice}</span>
|
||||
<ChevronUpDownIcon className="h-3 w-3" />
|
||||
</ListboxButton>
|
||||
<ListboxOptions className="absolute bottom-full mb-1 w-32 overflow-auto rounded-lg bg-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||
|
|
|
|||
|
|
@ -61,7 +61,14 @@ interface TTSContextType {
|
|||
const TTSContext = createContext<TTSContextType | undefined>(undefined);
|
||||
|
||||
export function TTSProvider({ children }: { children: React.ReactNode }) {
|
||||
const { apiKey: openApiKey, baseUrl: openApiBaseUrl, isLoading: configIsLoading } = useConfig();
|
||||
const {
|
||||
apiKey: openApiKey,
|
||||
baseUrl: openApiBaseUrl,
|
||||
isLoading: configIsLoading,
|
||||
voiceSpeed,
|
||||
voice: configVoice,
|
||||
updateConfigKey
|
||||
} = useConfig();
|
||||
|
||||
// Move openai initialization to a ref to avoid breaking hooks rules
|
||||
const openaiRef = useRef<OpenAI | null>(null);
|
||||
|
|
@ -75,8 +82,8 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
|
|||
const [activeHowl, setActiveHowl] = useState<Howl | null>(null);
|
||||
const [audioQueue] = useState<AudioBuffer[]>([]);
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
const [speed, setSpeed] = useState(1);
|
||||
const [voice, setVoice] = useState('alloy');
|
||||
const [speed, setSpeed] = useState(voiceSpeed);
|
||||
const [voice, setVoice] = useState(configVoice);
|
||||
const [availableVoices, setAvailableVoices] = useState<string[]>([]);
|
||||
|
||||
const [currDocPage, setCurrDocPage] = useState<number>(1);
|
||||
|
|
@ -422,6 +429,7 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
|
|||
|
||||
const setSpeedAndRestart = useCallback((newSpeed: number) => {
|
||||
setSpeed(newSpeed);
|
||||
updateConfigKey('voiceSpeed', newSpeed);
|
||||
// Clear the audio cache since it contains audio at the old speed
|
||||
audioCacheRef.current.clear();
|
||||
|
||||
|
|
@ -431,10 +439,11 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
|
|||
setCurrentIndex(currentIdx);
|
||||
setIsPlaying(true);
|
||||
}
|
||||
}, [isPlaying, currentIndex, stop]);
|
||||
}, [isPlaying, currentIndex, stop, updateConfigKey]);
|
||||
|
||||
const setVoiceAndRestart = useCallback((newVoice: string) => {
|
||||
setVoice(newVoice);
|
||||
updateConfigKey('voice', newVoice);
|
||||
// Clear the audio cache since it contains audio with the old voice
|
||||
audioCacheRef.current.clear();
|
||||
|
||||
|
|
@ -444,7 +453,7 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
|
|||
setCurrentIndex(currentIdx);
|
||||
setIsPlaying(true);
|
||||
}
|
||||
}, [isPlaying, currentIndex, stop]);
|
||||
}, [isPlaying, currentIndex, stop, updateConfigKey]);
|
||||
|
||||
const value = {
|
||||
isPlaying,
|
||||
|
|
|
|||
Loading…
Reference in a new issue