Change speed menu to slider
This commit is contained in:
parent
0da77fffbf
commit
61953a761a
1 changed files with 46 additions and 41 deletions
|
|
@ -1,55 +1,60 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import {
|
import { Input, Popover, PopoverButton, PopoverPanel } from '@headlessui/react';
|
||||||
Listbox,
|
|
||||||
ListboxButton,
|
|
||||||
ListboxOption,
|
|
||||||
ListboxOptions,
|
|
||||||
} from '@headlessui/react';
|
|
||||||
import { ChevronUpDownIcon } from '@/components/icons/Icons';
|
import { ChevronUpDownIcon } from '@/components/icons/Icons';
|
||||||
import { useConfig } from '@/contexts/ConfigContext';
|
import { useConfig } from '@/contexts/ConfigContext';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
const speedOptions = [
|
|
||||||
{ value: 0.5, label: '0.5x' },
|
|
||||||
{ value: 0.75, label: '0.75x' },
|
|
||||||
{ value: 1, label: '1x' },
|
|
||||||
{ value: 1.25, label: '1.25x' },
|
|
||||||
{ value: 1.5, label: '1.5x' },
|
|
||||||
{ value: 1.75, label: '1.75x' },
|
|
||||||
{ value: 2, label: '2x' },
|
|
||||||
{ value: 2.5, label: '2.5x' },
|
|
||||||
{ value: 3, label: '3x' },
|
|
||||||
];
|
|
||||||
|
|
||||||
export const SpeedControl = ({ setSpeedAndRestart }: {
|
export const SpeedControl = ({ setSpeedAndRestart }: {
|
||||||
setSpeedAndRestart: (speed: number) => void;
|
setSpeedAndRestart: (speed: number) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { voiceSpeed } = useConfig();
|
const { voiceSpeed } = useConfig();
|
||||||
|
const [localSpeed, setLocalSpeed] = useState(voiceSpeed);
|
||||||
|
|
||||||
// Use voiceSpeed as the source of truth
|
// Sync local speed with global state
|
||||||
const currentSpeed = voiceSpeed;
|
useEffect(() => {
|
||||||
|
setLocalSpeed(voiceSpeed);
|
||||||
|
}, [voiceSpeed]);
|
||||||
|
|
||||||
|
// Handler for slider change (updates local state only)
|
||||||
|
const handleSpeedChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setLocalSpeed(parseFloat(event.target.value));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Handler for slider release
|
||||||
|
const handleSpeedChangeComplete = useCallback(() => {
|
||||||
|
if (localSpeed !== voiceSpeed) {
|
||||||
|
setSpeedAndRestart(localSpeed);
|
||||||
|
}
|
||||||
|
}, [localSpeed, voiceSpeed, setSpeedAndRestart]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<Popover className="relative">
|
||||||
<Listbox value={currentSpeed} onChange={setSpeedAndRestart}>
|
<PopoverButton className="flex items-center space-x-0.5 sm:space-x-1 bg-transparent text-foreground text-xs sm:text-sm focus:outline-none cursor-pointer hover:bg-offbase rounded pl-1.5 sm:pl-2 pr-0.5 sm:pr-1 py-0.5 sm:py-1">
|
||||||
<ListboxButton className="flex items-center space-x-0.5 sm:space-x-1 bg-transparent text-foreground text-xs sm:text-sm focus:outline-none cursor-pointer hover:bg-offbase rounded pl-1.5 sm:pl-2 pr-0.5 sm:pr-1 py-0.5 sm:py-1">
|
<span>{Number.isInteger(localSpeed) ? localSpeed.toString() : localSpeed.toFixed(1)}x</span>
|
||||||
<span>{currentSpeed}x</span>
|
<ChevronUpDownIcon className="h-2.5 w-2.5 sm:h-3 sm:w-3" />
|
||||||
<ChevronUpDownIcon className="h-2.5 w-2.5 sm:h-3 sm:w-3" />
|
</PopoverButton>
|
||||||
</ListboxButton>
|
<PopoverPanel anchor="top" className="absolute z-50 bg-base p-3 rounded-md shadow-lg border border-offbase">
|
||||||
<ListboxOptions anchor='top start' className="absolute z-50 w-20 sm:w-24 overflow-auto rounded-lg bg-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
|
<div className="flex flex-col space-y-2">
|
||||||
{speedOptions.map((option) => (
|
<div className="flex justify-between">
|
||||||
<ListboxOption
|
<span className="text-xs">0.5x</span>
|
||||||
key={option.value}
|
<span className="text-xs font-bold">{Number.isInteger(localSpeed) ? localSpeed.toString() : localSpeed.toFixed(1)}x</span>
|
||||||
value={option.value}
|
<span className="text-xs">3x</span>
|
||||||
className={({ active, selected }) =>
|
</div>
|
||||||
`relative cursor-pointer select-none py-0.5 px-1.5 sm:py-2 sm:px-3 ${active ? 'bg-offbase' : ''} ${selected ? 'font-medium' : ''}`
|
<Input
|
||||||
}
|
type="range"
|
||||||
>
|
min="0.5"
|
||||||
<span className='text-xs sm:text-sm'>{option.label}</span>
|
max="3"
|
||||||
</ListboxOption>
|
step="0.1"
|
||||||
))}
|
value={localSpeed}
|
||||||
</ListboxOptions>
|
onChange={handleSpeedChange}
|
||||||
</Listbox>
|
onMouseUp={handleSpeedChangeComplete}
|
||||||
</div>
|
onKeyUp={handleSpeedChangeComplete}
|
||||||
|
onTouchEnd={handleSpeedChangeComplete}
|
||||||
|
className="w-full bg-offbase rounded-lg appearance-none cursor-pointer accent-accent [&::-webkit-slider-runnable-track]:bg-offbase [&::-webkit-slider-runnable-track]:rounded-lg [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-accent [&::-moz-range-track]:bg-offbase [&::-moz-range-track]:rounded-lg [&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-accent"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</PopoverPanel>
|
||||||
|
</Popover>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue