mirror of
https://github.com/movie-web/movie-web.git
synced 2024-11-13 13:05:06 +01:00
Re-add caption delay
This commit is contained in:
parent
e41d1fdb3f
commit
e569b5ba32
@ -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>
|
||||||
|
@ -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}
|
||||||
|
@ -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 (
|
||||||
|
@ -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",
|
||||||
|
Loading…
Reference in New Issue
Block a user