mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-09-16 05:10:42 -07:00
perf(settings): persist generation sliders on release, not per pointer-move
Both sliders on the generation settings page were calling update() — which is a React Query mutation that PATCHes /settings/generation — inside onValueChange. Dragging the chunk-limit slider from 800 to 3000 fired a request per pointer-move pixel, and a mid-drag failure plus optimistic rollback would leave persisted state visibly out of sync with the thumb position. Local state now mirrors each slider during a drag and the persist happens once on Radix's onValueCommit (pointer-up / keyboard-release). useEffects keep the local state in sync if the persisted value changes out-of-band — another window editing the same setting still updates the slider position cleanly.
This commit is contained in:
@@ -14,10 +14,17 @@ export function GenerationPage() {
|
||||
const platform = usePlatform();
|
||||
const serverUrl = useServerStore((state) => state.serverUrl);
|
||||
const { settings, update } = useGenerationSettings();
|
||||
const maxChunkChars = settings?.max_chunk_chars ?? 800;
|
||||
const crossfadeMs = settings?.crossfade_ms ?? 50;
|
||||
const persistedMaxChunkChars = settings?.max_chunk_chars ?? 800;
|
||||
const persistedCrossfadeMs = settings?.crossfade_ms ?? 50;
|
||||
const normalizeAudio = settings?.normalize_audio ?? true;
|
||||
const autoplayOnGenerate = settings?.autoplay_on_generate ?? true;
|
||||
// Slider mirrors persist on commit (pointer-up / keyboard-release) only —
|
||||
// onValueChange would fire a PATCH for every pointer-move pixel and round-
|
||||
// trip mid-drag failures could leave persisted state out of sync with UI.
|
||||
const [maxChunkChars, setMaxChunkChars] = useState(persistedMaxChunkChars);
|
||||
const [crossfadeMs, setCrossfadeMs] = useState(persistedCrossfadeMs);
|
||||
useEffect(() => setMaxChunkChars(persistedMaxChunkChars), [persistedMaxChunkChars]);
|
||||
useEffect(() => setCrossfadeMs(persistedCrossfadeMs), [persistedCrossfadeMs]);
|
||||
const [opening, setOpening] = useState(false);
|
||||
const [generationsPath, setGenerationsPath] = useState<string | null>(null);
|
||||
|
||||
@@ -64,7 +71,8 @@ export function GenerationPage() {
|
||||
<Slider
|
||||
id="maxChunkChars"
|
||||
value={[maxChunkChars]}
|
||||
onValueChange={([value]) => update({ max_chunk_chars: value })}
|
||||
onValueChange={([value]) => setMaxChunkChars(value)}
|
||||
onValueCommit={([value]) => update({ max_chunk_chars: value })}
|
||||
min={100}
|
||||
max={5000}
|
||||
step={50}
|
||||
@@ -86,7 +94,8 @@ export function GenerationPage() {
|
||||
<Slider
|
||||
id="crossfadeMs"
|
||||
value={[crossfadeMs]}
|
||||
onValueChange={([value]) => update({ crossfade_ms: value })}
|
||||
onValueChange={([value]) => setCrossfadeMs(value)}
|
||||
onValueCommit={([value]) => update({ crossfade_ms: value })}
|
||||
min={0}
|
||||
max={200}
|
||||
step={10}
|
||||
|
||||
Reference in New Issue
Block a user