Re-add caption delay

This commit is contained in:
Jip Fr 2023-10-23 16:30:20 +02:00
parent e41d1fdb3f
commit e569b5ba32
4 changed files with 30 additions and 6 deletions

View File

@ -51,7 +51,7 @@ function SettingsOverlay({ id }: { id: string }) {
<CaptionsView id={id} /> <CaptionsView id={id} />
</Menu.CardWithScrollable> </Menu.CardWithScrollable>
</OverlayPage> </OverlayPage>
<OverlayPage id={id} path="/captions/settings" width={343} height={360}> <OverlayPage id={id} path="/captions/settings" width={343} height={430}>
<Menu.Card> <Menu.Card>
<CaptionSettingsView id={id} /> <CaptionSettingsView id={id} />
</Menu.Card> </Menu.Card>

View File

@ -40,6 +40,7 @@ function CaptionSetting(props: {
max: number; max: number;
label: string; label: string;
min: number; min: number;
decimalsAllowed?: number;
}) { }) {
const inputRef = useRef<HTMLInputElement | null>(null); const inputRef = useRef<HTMLInputElement | null>(null);
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
@ -131,7 +132,10 @@ function CaptionSetting(props: {
onBlur={(e) => { onBlur={(e) => {
setIsFocused(false); setIsFocused(false);
const num = Number((e.target as HTMLInputElement).value); const num = Number((e.target as HTMLInputElement).value);
if (!Number.isNaN(num)) props.onChange?.(Math.round(num)); if (!Number.isNaN(num))
props.onChange?.(
(props.decimalsAllowed ?? 0) === 0 ? Math.round(num) : num
);
}} }}
ref={inputRef} ref={inputRef}
onChange={(e) => onChange={(e) =>
@ -142,13 +146,13 @@ function CaptionSetting(props: {
<button <button
className={inputClasses} className={inputClasses}
onClick={() => { onClick={() => {
setInputValue(Math.floor(props.value).toString()); setInputValue(props.value.toFixed(props.decimalsAllowed ?? 0));
setIsFocused(true); setIsFocused(true);
}} }}
type="button" type="button"
tabIndex={0} tabIndex={0}
> >
{textTransformer(Math.floor(props.value).toString())} {textTransformer(props.value.toFixed(props.decimalsAllowed ?? 0))}
</button> </button>
)} )}
</div> </div>
@ -163,7 +167,9 @@ export function CaptionSettingsView({ id }: { id: string }) {
const router = useOverlayRouter(id); const router = useOverlayRouter(id);
const styling = useSubtitleStore((s) => s.styling); const styling = useSubtitleStore((s) => s.styling);
const overrideCasing = useSubtitleStore((s) => s.overrideCasing); const overrideCasing = useSubtitleStore((s) => s.overrideCasing);
const delay = useSubtitleStore((s) => s.delay);
const setOverrideCasing = useSubtitleStore((s) => s.setOverrideCasing); const setOverrideCasing = useSubtitleStore((s) => s.setOverrideCasing);
const setDelay = useSubtitleStore((s) => s.setDelay);
const updateStyling = useSubtitleStore((s) => s.updateStyling); const updateStyling = useSubtitleStore((s) => s.updateStyling);
return ( return (
@ -172,6 +178,15 @@ export function CaptionSettingsView({ id }: { id: string }) {
Custom captions Custom captions
</Menu.BackLink> </Menu.BackLink>
<Menu.Section className="space-y-6"> <Menu.Section className="space-y-6">
<CaptionSetting
label="Caption delay"
max={10}
min={-10}
onChange={(v) => setDelay(v)}
value={delay}
textTransformer={(s) => `${s}s`}
decimalsAllowed={1}
/>
<CaptionSetting <CaptionSetting
label="Text size" label="Text size"
max={200} max={200}

View File

@ -70,6 +70,7 @@ export function SubtitleRenderer() {
const srtData = usePlayerStore((s) => s.caption.selected?.srtData); const srtData = usePlayerStore((s) => s.caption.selected?.srtData);
const styling = useSubtitleStore((s) => s.styling); const styling = useSubtitleStore((s) => s.styling);
const overrideCasing = useSubtitleStore((s) => s.overrideCasing); const overrideCasing = useSubtitleStore((s) => s.overrideCasing);
const delay = useSubtitleStore((s) => s.delay);
const parsedCaptions = useMemo( const parsedCaptions = useMemo(
() => (srtData ? parseSubtitles(srtData) : []), () => (srtData ? parseSubtitles(srtData) : []),
@ -79,9 +80,9 @@ export function SubtitleRenderer() {
const visibileCaptions = useMemo( const visibileCaptions = useMemo(
() => () =>
parsedCaptions.filter(({ start, end }) => parsedCaptions.filter(({ start, end }) =>
captionIsVisible(start, end, 0, videoTime) captionIsVisible(start, end, delay, videoTime)
), ),
[parsedCaptions, videoTime] [parsedCaptions, videoTime, delay]
); );
return ( return (

View File

@ -24,9 +24,11 @@ export interface SubtitleStore {
lastSelectedLanguage: string | null; lastSelectedLanguage: string | null;
styling: SubtitleStyling; styling: SubtitleStyling;
overrideCasing: boolean; overrideCasing: boolean;
delay: number;
updateStyling(newStyling: Partial<SubtitleStyling>): void; updateStyling(newStyling: Partial<SubtitleStyling>): void;
setLanguage(language: string | null): void; setLanguage(language: string | null): void;
setOverrideCasing(enabled: boolean): void; setOverrideCasing(enabled: boolean): void;
setDelay(delay: number): void;
} }
// TODO add migration from previous stored settings // TODO add migration from previous stored settings
@ -36,6 +38,7 @@ export const useSubtitleStore = create(
enabled: false, enabled: false,
lastSelectedLanguage: null, lastSelectedLanguage: null,
overrideCasing: false, overrideCasing: false,
delay: 0,
styling: { styling: {
color: "#ffffff", color: "#ffffff",
backgroundOpacity: 0.5, backgroundOpacity: 0.5,
@ -62,6 +65,11 @@ export const useSubtitleStore = create(
s.overrideCasing = enabled; s.overrideCasing = enabled;
}); });
}, },
setDelay(delay) {
set((s) => {
s.delay = delay;
});
},
})), })),
{ {
name: "__MW::subtitles", name: "__MW::subtitles",