import classNames from "classnames"; import { useCallback, useEffect, useRef, 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 { useProgressBar } from "@/hooks/useProgressBar"; import { useSubtitleStore } from "@/stores/subtitles"; export function ColorOption(props: { color: string; active?: boolean; onClick: () => void; }) { return ( ); } export function CaptionSetting(props: { textTransformer?: (s: string) => string; value: number; onChange?: (val: number) => void; max: number; label: string; min: number; decimalsAllowed?: number; controlButtons?: boolean; }) { const inputRef = useRef(null); const ref = useRef(null); const currentPercentage = (props.value - props.min) / (props.max - props.min); const commit = useCallback( (percentage) => { const range = props.max - props.min; const newPercentage = Math.min(Math.max(percentage, 0), 1); props.onChange?.(props.min + range * newPercentage); }, [props] ); const { dragging, dragPercentage, dragMouseDown } = useProgressBar( ref, commit, true ); const [isFocused, setIsFocused] = useState(false); const [inputValue, setInputValue] = useState(""); useEffect(() => { function listener(e: KeyboardEvent) { if (e.key === "Enter" && isFocused) { inputRef.current?.blur(); } } window.addEventListener("keydown", listener); return () => { window.removeEventListener("keydown", listener); }; }, [isFocused]); const inputClasses = `tabbable py-1 bg-video-context-inputBg rounded text-white cursor-text ${ props.controlButtons ? "text-center px-4 w-24" : "px-3 text-left w-20" }`; const arrowButtonClasses = "tabbable hover:text-white transition-colors duration-100 w-full h-full flex justify-center items-center hover:bg-video-context-buttonOverInputHover rounded"; const textTransformer = props.textTransformer ?? ((s) => s); return (
{props.label}
{/* Actual progress bar */}
{isFocused ? ( { (e.target as HTMLInputElement).select(); }} onBlur={(e) => { setIsFocused(false); const num = Number((e.target as HTMLInputElement).value); if (!Number.isNaN(num)) props.onChange?.( (props.decimalsAllowed ?? 0) === 0 ? Math.round(num) : num ); }} ref={inputRef} onChange={(e) => setInputValue((e.target as HTMLInputElement).value) } /> ) : (
{ if ((evt.target as HTMLButtonElement).closest(".actions")) return; setInputValue(props.value.toFixed(props.decimalsAllowed ?? 0)); setIsFocused(true); }} > {props.controlButtons ? ( <>
) : null}
)}
); } export const colors = ["#ffffff", "#80b1fa", "#e2e535"]; export function CaptionSettingsView({ id }: { id: string }) { const { t } = useTranslation(); const router = useOverlayRouter(id); const styling = useSubtitleStore((s) => s.styling); const overrideCasing = useSubtitleStore((s) => s.overrideCasing); const delay = useSubtitleStore((s) => s.delay); const setOverrideCasing = useSubtitleStore((s) => s.setOverrideCasing); const setDelay = useSubtitleStore((s) => s.setDelay); const updateStyling = useSubtitleStore((s) => s.updateStyling); return ( <> router.navigate("/captions")}> Custom captions setDelay(v)} value={delay} textTransformer={(s) => `${s}s`} decimalsAllowed={1} controlButtons />
{t("player.menus.captions.settings.fixCapitals")}
setOverrideCasing(!overrideCasing)} />
updateStyling({ backgroundOpacity: v / 100 })} value={styling.backgroundOpacity * 100} textTransformer={(s) => `${s}%`} /> `${s}%`} onChange={(v) => updateStyling({ size: v / 100 })} value={styling.size * 100} />
{t("settings.captions.colorLabel")}
{colors.map((v) => ( updateStyling({ color: v })} color={v} active={styling.color === v} key={v} /> ))}
); }