Add chapters on bottom scrubber, set video progress only on seek end

This commit is contained in:
Zoe Roux 2024-01-28 19:31:15 +01:00
parent 90498eb117
commit 1df8d6589a
3 changed files with 19 additions and 7 deletions

View File

@ -65,6 +65,7 @@ export const hoverAtom = atom((get) =>
[!get(playAtom), ...Object.values(get(hoverReasonAtom))].includes(true), [!get(playAtom), ...Object.values(get(hoverReasonAtom))].includes(true),
); );
export const seekingAtom = atom(false); export const seekingAtom = atom(false);
export const seekProgressAtom = atom<number | null>(null);
export const Hover = ({ export const Hover = ({
isLoading, isLoading,
@ -163,7 +164,7 @@ export const Hover = ({
)} )}
<ProgressBar chapters={chapters} url={url} /> <ProgressBar chapters={chapters} url={url} />
{showBottomSeeker ? ( {showBottomSeeker ? (
<BottomScrubber url={url} /> <BottomScrubber url={url} chapters={chapters} />
) : ( ) : (
<View <View
{...css({ {...css({
@ -329,25 +330,28 @@ const ProgressBar = ({ url, chapters }: { url: string; chapters?: Chapter[] }) =
const setPlay = useSetAtom(playAtom); const setPlay = useSetAtom(playAtom);
const [hoverProgress, setHoverProgress] = useState<number | null>(null); const [hoverProgress, setHoverProgress] = useState<number | null>(null);
const [layout, setLayout] = useState({ x: 0, y: 0, width: 0, height: 0 }); const [layout, setLayout] = useState({ x: 0, y: 0, width: 0, height: 0 });
const [seekProgress, setSeekProgress] = useAtom(seekProgressAtom);
const setSeeking = useSetAtom(seekingAtom); const setSeeking = useSetAtom(seekingAtom);
return ( return (
<> <>
<Slider <Slider
progress={progress} progress={seekProgress ?? progress}
startSeek={() => { startSeek={() => {
setPlay(false); setPlay(false);
setSeeking(true); setSeeking(true);
}} }}
endSeek={() => { endSeek={() => {
setSeeking(false); setSeeking(false);
setProgress(seekProgress!);
setSeekProgress(null);
setTimeout(() => setPlay(true), 10); setTimeout(() => setPlay(true), 10);
}} }}
onHover={(progress, layout) => { onHover={(progress, layout) => {
setHoverProgress(progress); setHoverProgress(progress);
setLayout(layout); setLayout(layout);
}} }}
setProgress={setProgress} setProgress={(progress) => setSeekProgress(progress)}
subtleProgress={buffered} subtleProgress={buffered}
max={duration} max={duration}
markers={chapters?.map((x) => x.startTime)} markers={chapters?.map((x) => x.startTime)}

View File

@ -23,10 +23,11 @@ import { Sprite, P, imageBorderRadius, ts } from "@kyoo/primitives";
import { View, Platform } from "react-native"; import { View, Platform } from "react-native";
import { percent, useYoshiki, px, Theme, useForceRerender } from "yoshiki/native"; import { percent, useYoshiki, px, Theme, useForceRerender } from "yoshiki/native";
import { ErrorView } from "../../fetch"; import { ErrorView } from "../../fetch";
import { useMemo, useState } from "react"; import { useMemo } from "react";
import { useAtomValue } from "jotai"; import { useAtomValue } from "jotai";
import { durationAtom, progressAtom } from "../state"; import { durationAtom } from "../state";
import { toTimerString } from "./left-buttons"; import { toTimerString } from "./left-buttons";
import { seekProgressAtom } from "./hover";
type Thumb = { type Thumb = {
from: number; from: number;
@ -147,17 +148,18 @@ export const ScrubberTooltip = ({
}; };
let scrubberWidth = 0; let scrubberWidth = 0;
export const BottomScrubber = ({ url }: { url: string }) => { export const BottomScrubber = ({ url, chapters }: { url: string; chapters?: Chapter[] }) => {
const { css } = useYoshiki(); const { css } = useYoshiki();
const { info, error, stats } = useScrubber(url); const { info, error, stats } = useScrubber(url);
const rerender = useForceRerender(); const rerender = useForceRerender();
const progress = useAtomValue(progressAtom); const progress = useAtomValue(seekProgressAtom) ?? 0;
const duration = useAtomValue(durationAtom) ?? 1; const duration = useAtomValue(durationAtom) ?? 1;
if (error) return <ErrorView error={error} />; if (error) return <ErrorView error={error} />;
const width = stats?.width ?? 1; const width = stats?.width ?? 1;
const chapter = chapters?.findLast((x) => x.startTime <= progress && progress < x.endTime);
return ( return (
<View {...css({ overflow: "hidden" })}> <View {...css({ overflow: "hidden" })}>
<View <View
@ -231,6 +233,7 @@ export const BottomScrubber = ({ url }: { url: string }) => {
})} })}
> >
{toTimerString(progress)} {toTimerString(progress)}
{chapter && `\n${chapter.name}`}
</P> </P>
</View> </View>
</View> </View>

View File

@ -206,7 +206,12 @@ func (h *Handler) GetInfo(c echo.Context) error {
if err != nil { if err != nil {
return err return err
} }
// Run extractors to have them in cache
h.extractor.RunExtractor(ret.Path, ret.Sha, &ret.Subtitles) h.extractor.RunExtractor(ret.Path, ret.Sha, &ret.Subtitles)
h.thumbnails.ExtractThumbnail(
ret.Path,
fmt.Sprintf("%s/%s/thumbnails.png", resource, slug),
)
return c.JSON(http.StatusOK, ret) return c.JSON(http.StatusOK, ret)
} }