Sync the scrobber with the current progress

This commit is contained in:
Zoe Roux 2024-01-22 22:50:26 +01:00
parent 6b006e78e5
commit 797ea13982
2 changed files with 75 additions and 21 deletions

View File

@ -152,6 +152,7 @@ export const Hover = ({
{isLoading ? <Skeleton {...css({ width: rem(15), height: rem(2) })} /> : name} {isLoading ? <Skeleton {...css({ width: rem(15), height: rem(2) })} /> : name}
</H2> </H2>
<ProgressBar chapters={chapters} /> <ProgressBar chapters={chapters} />
<BottomScrubber url={url}/>
<View <View
{...css({ {...css({
flexDirection: "row", flexDirection: "row",
@ -173,7 +174,6 @@ export const Hover = ({
}} }}
/> />
</View> </View>
<BottomScrubber url={url}/>
</View> </View>
</View> </View>
</View> </View>

View File

@ -19,12 +19,15 @@
*/ */
import { useFetch, QueryIdentifier, imageFn } from "@kyoo/models"; import { useFetch, QueryIdentifier, imageFn } from "@kyoo/models";
import { FastImage } from "@kyoo/primitives"; import { FastImage, P, imageBorderRadius, tooltip, ts } from "@kyoo/primitives";
import { Platform, View } from "react-native"; import { Platform, View } from "react-native";
import { percent, useYoshiki, vh } from "yoshiki/native"; import { percent, useYoshiki, px, vh } from "yoshiki/native";
import { ErrorView } from "../../fetch"; import { ErrorView } from "../../fetch";
import { useMemo } from "react"; import { useMemo } from "react";
import { CssObject } from "yoshiki/src/web/generator"; import { CssObject } from "yoshiki/src/web/generator";
import { useAtomValue } from "jotai";
import { durationAtom, progressAtom } from "../state";
import { toTimerString } from "./left-buttons";
type Thumb = { to: number; url: string; x: number; y: number; width: number; height: number }; type Thumb = { to: number; url: string; x: number; y: number; width: number; height: number };
@ -64,27 +67,78 @@ export const BottomScrubber = ({ url }: { url: string }) => {
return ret; return ret;
}, [data]); }, [data]);
const progress = useAtomValue(progressAtom);
const duration = useAtomValue(durationAtom);
if (error) return <ErrorView error={error} />; if (error) return <ErrorView error={error} />;
const width = info?.[0]?.width ?? 0;
return ( return (
<View {...css({ flexDirection: "row", width: percent(100) })}> <View {...css({ overflow: "hidden" })}>
{info.map((thumb) => ( <View
<FastImage {...css(
key={thumb.to} { flexDirection: "row" },
src={thumb.url} {
alt="" style: {
width={thumb.width} transform: `translateX(calc(${
height={thumb.height} (progress / duration) * -width * info.length - width / 2
style={ }px + 50%))`,
Platform.OS === "web" },
? ({ },
objectFit: "none", )}
objectPosition: `${-thumb.x}px ${-thumb.y}px`, >
} as CssObject) {info.map((thumb) => (
: undefined <FastImage
} key={thumb.to}
/> src={thumb.url}
))} alt=""
width={thumb.width}
height={thumb.height}
style={
Platform.OS === "web"
? ({
objectFit: "none",
objectPosition: `${-thumb.x}px ${-thumb.y}px`,
flexShrink: 0,
} as CssObject)
: undefined
}
/>
))}
</View>
<View
{...css({
position: "absolute",
top: 0,
bottom: 0,
left: percent(50),
right: percent(50),
width: px(3),
bg: (theme) => theme.colors.white,
})}
/>
<View
{...css({
position: "absolute",
top: 0,
bottom: 0,
left: 0,
right: 0,
alignItems: "center",
})}
>
<P
{...css({
textAlign: "center",
color: (theme) => theme.colors.white,
bg: (theme) => theme.darkOverlay,
padding: ts(0.5),
borderRadius: imageBorderRadius,
})}
>
{toTimerString(progress)}
</P>
</View>
</View> </View>
); );
}; };