scroll to active episode and caption, fix last provider being nonactive. caption delays mobile friendly input, bigger range caption delay range

Co-authored-by: Jip Frijlink <JipFr@users.noreply.github.com>
This commit is contained in:
mrjvs 2023-10-23 21:03:50 +02:00
parent ace10dde78
commit a2968d3bf8
9 changed files with 95 additions and 44 deletions

View File

@ -64,7 +64,7 @@ const iconList: Record<Icons, string> = {
chevronDown: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg>`,
chevronUp: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-up"><polyline points="18 15 12 9 6 15"></polyline></svg>`,
chevronRight: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg>`,
chevronLeft: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-left"><polyline points="15 18 9 12 15 6"></polyline></svg>`,
chevronLeft: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-left"><polyline points="15 18 9 12 15 6"></polyline></svg>`,
clapperBoard: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M326.1 160l127.4-127.4C451.7 32.39 449.9 32 448 32h-86.06l-128 128H326.1zM166.1 160l128-128H201.9l-128 128H166.1zM497.7 56.19L393.9 160H512V96C512 80.87 506.5 67.15 497.7 56.19zM134.1 32H64C28.65 32 0 60.65 0 96v64h6.062L134.1 32zM0 416c0 35.35 28.65 64 64 64h384c35.35 0 64-28.65 64-64V192H0V416z"/></svg>`,
film: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M463.1 32h-416C21.49 32-.0001 53.49-.0001 80v352c0 26.51 21.49 48 47.1 48h416c26.51 0 48-21.49 48-48v-352C511.1 53.49 490.5 32 463.1 32zM111.1 408c0 4.418-3.582 8-8 8H55.1c-4.418 0-8-3.582-8-8v-48c0-4.418 3.582-8 8-8h47.1c4.418 0 8 3.582 8 8L111.1 408zM111.1 280c0 4.418-3.582 8-8 8H55.1c-4.418 0-8-3.582-8-8v-48c0-4.418 3.582-8 8-8h47.1c4.418 0 8 3.582 8 8V280zM111.1 152c0 4.418-3.582 8-8 8H55.1c-4.418 0-8-3.582-8-8v-48c0-4.418 3.582-8 8-8h47.1c4.418 0 8 3.582 8 8L111.1 152zM351.1 400c0 8.836-7.164 16-16 16H175.1c-8.836 0-16-7.164-16-16v-96c0-8.838 7.164-16 16-16h160c8.836 0 16 7.162 16 16V400zM351.1 208c0 8.836-7.164 16-16 16H175.1c-8.836 0-16-7.164-16-16v-96c0-8.838 7.164-16 16-16h160c8.836 0 16 7.162 16 16V208zM463.1 408c0 4.418-3.582 8-8 8h-47.1c-4.418 0-7.1-3.582-7.1-8l0-48c0-4.418 3.582-8 8-8h47.1c4.418 0 8 3.582 8 8V408zM463.1 280c0 4.418-3.582 8-8 8h-47.1c-4.418 0-8-3.582-8-8v-48c0-4.418 3.582-8 8-8h47.1c4.418 0 8 3.582 8 8V280zM463.1 152c0 4.418-3.582 8-8 8h-47.1c-4.418 0-8-3.582-8-8l0-48c0-4.418 3.582-8 7.1-8h47.1c4.418 0 8 3.582 8 8V152z"/></svg>`,
dragon: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M18.43 255.8L192 224L100.8 292.6C90.67 302.8 97.8 320 112 320h222.7c-9.499-26.5-14.75-54.5-14.75-83.38V194.2L200.3 106.8C176.5 90.88 145 92.75 123.3 111.2l-117.5 116.4C-6.562 238 2.436 258 18.43 255.8zM575.2 289.9l-100.7-50.25c-16.25-8.125-26.5-24.75-26.5-43V160h63.99l28.12 22.62C546.1 188.6 554.2 192 562.7 192h30.1c11.1 0 23.12-6.875 28.5-17.75l14.37-28.62c5.374-10.87 4.25-23.75-2.999-33.5l-74.49-99.37C552.1 4.75 543.5 0 533.5 0H296C288.9 0 285.4 8.625 290.4 13.62L351.1 64L292.4 88.75c-5.874 3-5.874 11.37 0 14.37L351.1 128l-.0011 108.6c0 72 35.99 139.4 95.99 179.4c-195.6 6.75-344.4 41-434.1 60.88c-8.124 1.75-13.87 9-13.87 17.38C.0463 504 8.045 512 17.79 512h499.1c63.24 0 119.6-47.5 122.1-110.8C642.3 354 617.1 310.9 575.2 289.9zM489.1 66.25l45.74 11.38c-2.75 11-12.5 18.88-24.12 18.25C497.7 95.25 484.8 83.38 489.1 66.25z"/></svg>`,

View File

@ -123,7 +123,7 @@ function EpisodesView({
content = <CenteredText>Loading...</CenteredText>;
else if (loadingState.value) {
content = (
<Menu.Section className="pb-6">
<Menu.ScrollToActiveSection className="pb-6">
{loadingState.value.season.episodes.length === 0 ? (
<Menu.TextDisplay title="No episodes found">
There are no episodes in this season, check back later!
@ -173,7 +173,7 @@ function EpisodesView({
</Menu.Link>
);
})}
</Menu.Section>
</Menu.ScrollToActiveSection>
);
}

View File

@ -77,12 +77,11 @@ function CaptionSetting(props: {
};
}, [isFocused]);
function setNewValue(value: number) {
props.onChange?.(Math.min(Math.max(value, props.min), props.max));
}
const inputClasses =
"px-3 py-1 bg-video-context-inputBg rounded w-20 text-left text-white cursor-text";
const inputClasses = `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 =
"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 (
@ -161,7 +160,7 @@ function CaptionSetting(props: {
<button
className={classNames(
inputClasses,
props.controlButtons ? "pr-8 relative" : undefined
props.controlButtons ? "relative" : undefined
)}
type="button"
tabIndex={0}
@ -171,32 +170,36 @@ function CaptionSetting(props: {
)}
</button>
{props.controlButtons ? (
<div className="actions w-6 h-full absolute right-0 top-0 flex items-center flex-col">
<button
type="button"
onClick={
() =>
setNewValue(
props.value + 1 / 10 ** (props.decimalsAllowed ?? 0)
) // Add depending on the decimalsAllowed. If there's 1 decimal allowed, add 0.1. For 2, add 0.01, etc.
}
className="hover:text-white transition-colors duration-100"
>
<Icon icon={Icons.CHEVRON_UP} />
</button>
<button
type="button"
onClick={
() =>
setNewValue(
props.value - 1 / 10 ** (props.decimalsAllowed ?? 0)
) // Remove depending on the decimalsAllowed. If there's 1 decimal allowed, add 0.1. For 2, add 0.01, etc.
}
className="hover:text-white transition-colors duration-100"
>
<Icon icon={Icons.CHEVRON_DOWN} />
</button>
</div>
<>
<div className="actions w-6 h-full absolute left-0 top-0 grid grid-cols-1 items-center justify-center">
<button
type="button"
onClick={
() =>
props.onChange?.(
props.value - 1 / 10 ** (props.decimalsAllowed ?? 0)
) // Remove depending on the decimalsAllowed. If there's 1 decimal allowed, add 0.1. For 2, add 0.01, etc.
}
className={arrowButtonClasses}
>
<Icon icon={Icons.CHEVRON_LEFT} />
</button>
</div>
<div className="actions w-6 h-full absolute right-0 top-0 grid grid-cols-1 items-center justify-center">
<button
type="button"
onClick={
() =>
props.onChange?.(
props.value + 1 / 10 ** (props.decimalsAllowed ?? 0)
) // Add depending on the decimalsAllowed. If there's 1 decimal allowed, add 0.1. For 2, add 0.01, etc.
}
className={arrowButtonClasses}
>
<Icon icon={Icons.CHEVRON_RIGHT} />
</button>
</div>
</>
) : null}
</div>
)}

View File

@ -42,7 +42,10 @@ export function CaptionOption(props: {
error={props.error}
onClick={props.onClick}
>
<span className="flex items-center">
<span
data-active-link={props.selected ? true : undefined}
className="flex items-center"
>
<span data-code={props.countryCode} className="mr-3">
<FlagIcon countryCode={countryCode} />
</span>
@ -167,12 +170,15 @@ export function CaptionsView({ id }: { id: string }) {
<Input value={searchQuery} onInput={setSearchQuery} />
</div>
</div>
<Menu.Section className="!pt-1 mt-2 pb-3">
<Menu.ScrollToActiveSection
loaded={req.loading}
className="!pt-1 mt-2 pb-3"
>
<CaptionOption onClick={() => disable()} selected={!lang}>
Off
</CaptionOption>
{content}
</Menu.Section>
</Menu.ScrollToActiveSection>
</>
);
}

View File

@ -74,7 +74,11 @@ export function Link(props: {
if (!props.onClick) {
return (
<div className={classes} style={styles}>
<div
className={classes}
style={styles}
data-active-link={props.active ? true : undefined}
>
{content}
</div>
);
@ -86,6 +90,7 @@ export function Link(props: {
className={classes}
style={styles}
onClick={props.onClick}
data-active-link={props.active ? true : undefined}
>
{content}
</button>

View File

@ -1,4 +1,5 @@
import classNames from "classnames";
import { useEffect, useRef } from "react";
export function SectionTitle(props: {
children: React.ReactNode;
@ -26,3 +27,36 @@ export function Section(props: {
</div>
);
}
export function ScrollToActiveSection(props: {
children: React.ReactNode;
className?: string;
loaded?: boolean;
}) {
const scrollingContainer = useRef<HTMLDivElement>(null);
useEffect(() => {
const active =
scrollingContainer.current?.querySelector("[data-active-link]");
const boxRect = scrollingContainer.current?.getBoundingClientRect();
const activeLinkRect = active?.getBoundingClientRect();
if (!activeLinkRect || !boxRect) return;
const activeYPos = activeLinkRect.top - boxRect.top;
scrollingContainer.current?.scrollTo(
0,
activeYPos - boxRect.height / 2 + activeLinkRect.height / 2
);
}, [props.loaded]);
return (
<div
ref={scrollingContainer}
className={classNames("pt-4 space-y-1", props.className)}
>
{props.children}
</div>
);
}

View File

@ -41,9 +41,11 @@ export function ScrapingPart(props: ScrapingProps) {
const currentProvider = sourceOrder.find(
(s) => sources[s.id].status === "pending"
);
const currentProviderIndex =
sourceOrder.findIndex((provider) => currentProvider?.id === provider.id) ??
sourceOrder.length - 1;
let currentProviderIndex = sourceOrder.findIndex(
(provider) => currentProvider?.id === provider.id
);
if (currentProviderIndex === -1)
currentProviderIndex = sourceOrder.length - 1;
return (
<div className="h-full w-full relative" ref={containerRef}>

View File

@ -67,7 +67,7 @@ export const useSubtitleStore = create(
},
setDelay(delay) {
set((s) => {
s.delay = delay;
s.delay = Math.max(Math.min(500, delay), -500);
});
},
})),

View File

@ -148,6 +148,7 @@ module.exports = {
buttonFocus: "#202836",
flagBg: "#202836",
inputBg: "#202836",
buttonOverInputHover: "#283040",
inputPlaceholder: "#374A56",
cardBorder: "#1B262E",
slider: "#8787A8",