diff --git a/src/components/player/atoms/settings/PlaybackSettingsView.tsx b/src/components/player/atoms/settings/PlaybackSettingsView.tsx index cae00fb7..4735b5fd 100644 --- a/src/components/player/atoms/settings/PlaybackSettingsView.tsx +++ b/src/components/player/atoms/settings/PlaybackSettingsView.tsx @@ -1,8 +1,9 @@ import classNames from "classnames"; -import { useCallback, useEffect, useMemo } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Toggle } from "@/components/buttons/Toggle"; +import { Icon, Icons } from "@/components/Icon"; import { Menu } from "@/components/player/internals/ContextMenu"; import { useOverlayRouter } from "@/hooks/useOverlayRouter"; import { usePlayerStore } from "@/stores/player/store"; @@ -16,27 +17,159 @@ function ButtonList(props: { onClick: (v: any) => void; disabled?: boolean; }) { + const [editingIndex, setEditingIndex] = useState(null); + const [customValue, setCustomValue] = useState(""); + const [isCustomSpeed, setIsCustomSpeed] = useState(false); + + // Check if current speed is a custom value (not in preset options) + useEffect(() => { + if (!props.options.includes(props.selected)) { + setIsCustomSpeed(true); + } else { + setIsCustomSpeed(false); + } + }, [props.selected, props.options]); + + const handleButtonClick = useCallback( + (option: number, index: number) => { + if (editingIndex === index) { + // Already in edit mode, do nothing + return; + } + + // If clicking the custom speed button, enter edit mode + if (isCustomSpeed && option === props.selected) { + setEditingIndex(0); + setCustomValue(option.toString()); + return; + } + + props.onClick(option); + setIsCustomSpeed(false); + }, + [editingIndex, props, isCustomSpeed], + ); + + const handleDoubleClick = useCallback( + (option: number, index: number) => { + if (props.disabled) return; + + setEditingIndex(index); + setCustomValue(option.toString()); + }, + [props.disabled], + ); + + const handleCustomValueChange = useCallback( + (e: React.ChangeEvent) => { + setCustomValue(e.target.value); + }, + [], + ); + + const handleCustomValueKeyDown = useCallback( + (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + const value = parseFloat(customValue); + if (!Number.isNaN(value) && value > 0 && value <= 5) { + props.onClick(value); + setEditingIndex(null); + setIsCustomSpeed(true); + } + } else if (e.key === "Escape") { + setEditingIndex(null); + } + }, + [customValue, props], + ); + + const handleInputBlur = useCallback(() => { + setEditingIndex(null); + }, []); + + const handleResetCustomSpeed = useCallback(() => { + setIsCustomSpeed(false); + props.onClick(1); // Reset to default speed (1x) + }, [props]); + return (
- {props.options.map((option) => { - return ( - - ); - })} + {isCustomSpeed ? ( + // Show only the custom speed button when a custom speed is set + + + )} + + ) : ( + // Show all preset options when no custom speed is set + props.options.map((option, index) => { + const isEditing = editingIndex === index; + return ( + + ); + }) + )}
); }