Skip to content

Commit e830957

Browse files
committed
Add voice + speed to indexedDB and config context
1 parent 5591931 commit e830957

File tree

3 files changed

+30
-9
lines changed

3 files changed

+30
-9
lines changed

src/components/player/SpeedControl.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ListboxOptions,
66
} from '@headlessui/react';
77
import { ChevronUpDownIcon } from '@/components/icons/Icons';
8+
import { useConfig } from '@/contexts/ConfigContext';
89

910
const speedOptions = [
1011
{ value: 0.5, label: '0.5x' },
@@ -22,11 +23,16 @@ export const SpeedControl = ({ speed, setSpeedAndRestart }: {
2223
speed: number;
2324
setSpeedAndRestart: (speed: number) => void;
2425
}) => {
26+
const { voiceSpeed } = useConfig();
27+
28+
// Use voiceSpeed as the source of truth
29+
const currentSpeed = voiceSpeed;
30+
2531
return (
2632
<div className="relative">
27-
<Listbox value={speed} onChange={setSpeedAndRestart}>
33+
<Listbox value={currentSpeed} onChange={setSpeedAndRestart}>
2834
<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">
29-
<span>{speed}x</span>
35+
<span>{currentSpeed}x</span>
3036
<ChevronUpDownIcon className="h-3 w-3" />
3137
</ListboxButton>
3238
<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">

src/components/player/VoicesControl.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,23 @@ import {
55
ListboxOptions,
66
} from '@headlessui/react';
77
import { ChevronUpDownIcon } from '@/components/icons/Icons';
8+
import { useConfig } from '@/contexts/ConfigContext';
89

910
export const VoicesControl = ({ voice, availableVoices, setVoiceAndRestart }: {
1011
voice: string;
1112
availableVoices: string[];
1213
setVoiceAndRestart: (voice: string) => void;
1314
}) => {
15+
const { voice: configVoice } = useConfig();
16+
17+
// Use configVoice as the source of truth
18+
const currentVoice = configVoice;
19+
1420
return (
1521
<div className="relative">
16-
<Listbox value={voice} onChange={setVoiceAndRestart}>
22+
<Listbox value={currentVoice} onChange={setVoiceAndRestart}>
1723
<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">
18-
<span>{voice}</span>
24+
<span>{currentVoice}</span>
1925
<ChevronUpDownIcon className="h-3 w-3" />
2026
</ListboxButton>
2127
<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">

src/contexts/TTSContext.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,14 @@ interface TTSContextType {
6161
const TTSContext = createContext<TTSContextType | undefined>(undefined);
6262

6363
export function TTSProvider({ children }: { children: React.ReactNode }) {
64-
const { apiKey: openApiKey, baseUrl: openApiBaseUrl, isLoading: configIsLoading } = useConfig();
64+
const {
65+
apiKey: openApiKey,
66+
baseUrl: openApiBaseUrl,
67+
isLoading: configIsLoading,
68+
voiceSpeed,
69+
voice: configVoice,
70+
updateConfigKey
71+
} = useConfig();
6572

6673
// Move openai initialization to a ref to avoid breaking hooks rules
6774
const openaiRef = useRef<OpenAI | null>(null);
@@ -75,8 +82,8 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
7582
const [activeHowl, setActiveHowl] = useState<Howl | null>(null);
7683
const [audioQueue] = useState<AudioBuffer[]>([]);
7784
const [isProcessing, setIsProcessing] = useState(false);
78-
const [speed, setSpeed] = useState(1);
79-
const [voice, setVoice] = useState('alloy');
85+
const [speed, setSpeed] = useState(voiceSpeed);
86+
const [voice, setVoice] = useState(configVoice);
8087
const [availableVoices, setAvailableVoices] = useState<string[]>([]);
8188

8289
const [currDocPage, setCurrDocPage] = useState<number>(1);
@@ -422,6 +429,7 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
422429

423430
const setSpeedAndRestart = useCallback((newSpeed: number) => {
424431
setSpeed(newSpeed);
432+
updateConfigKey('voiceSpeed', newSpeed);
425433
// Clear the audio cache since it contains audio at the old speed
426434
audioCacheRef.current.clear();
427435

@@ -431,10 +439,11 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
431439
setCurrentIndex(currentIdx);
432440
setIsPlaying(true);
433441
}
434-
}, [isPlaying, currentIndex, stop]);
442+
}, [isPlaying, currentIndex, stop, updateConfigKey]);
435443

436444
const setVoiceAndRestart = useCallback((newVoice: string) => {
437445
setVoice(newVoice);
446+
updateConfigKey('voice', newVoice);
438447
// Clear the audio cache since it contains audio with the old voice
439448
audioCacheRef.current.clear();
440449

@@ -444,7 +453,7 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
444453
setCurrentIndex(currentIdx);
445454
setIsPlaying(true);
446455
}
447-
}, [isPlaying, currentIndex, stop]);
456+
}, [isPlaying, currentIndex, stop, updateConfigKey]);
448457

449458
const value = {
450459
isPlaying,

0 commit comments

Comments
 (0)