Add x and y props to image

This commit is contained in:
Zoe Roux 2024-01-25 09:39:37 +01:00
parent 5efcfb8b61
commit ec90862262
3 changed files with 59 additions and 26 deletions

View File

@ -18,6 +18,8 @@
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>. * along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { ComponentProps } from "react";
import { View } from "react-native";
import FImage from "react-native-fast-image"; import FImage from "react-native-fast-image";
export const FastImage = ({ export const FastImage = ({
@ -25,6 +27,10 @@ export const FastImage = ({
alt, alt,
width, width,
height, height,
x,
y,
rows,
columns,
style, style,
...props ...props
}: { }: {
@ -32,18 +38,31 @@ export const FastImage = ({
alt: string; alt: string;
width: number | string; width: number | string;
height: number | string; height: number | string;
x: number;
y: number;
rows: number;
columns: number;
style?: object; style?: object;
}) => { }) => {
return ( return (
<FImage <View style={{ width, height, overflow: "hidden", flexGrow: 0, flexShrink: 0 }}>
source={{ <FImage
uri: src, source={{
priority: FImage.priority.low, uri: src,
}} priority: FImage.priority.low,
accessibilityLabel={alt} }}
resizeMode={FImage.resizeMode.cover} accessibilityLabel={alt}
style={style} resizeMode={FImage.resizeMode.cover}
{...props} style={[
/> {
width: width * columns,
height: height * rows,
transform: `translate(${-x}px, ${-y}px)`,
},
style,
]}
{...props}
/>
</View>
); );
}; };

View File

@ -24,11 +24,17 @@ export const FastImage = ({
src, src,
alt, alt,
style, style,
x,
y,
...props ...props
}: { }: {
src: string; src: string;
alt: string; alt: string;
style?: object; style?: object;
width: number | string;
height: number | string;
x: number;
y: number;
}) => { }) => {
return ( return (
<NextImage <NextImage
@ -37,7 +43,7 @@ export const FastImage = ({
alt={alt!} alt={alt!}
// Don't use next's server to reprocess images, they are already optimized by kyoo. // Don't use next's server to reprocess images, they are already optimized by kyoo.
unoptimized={true} unoptimized={true}
style={style} style={{ objectFit: "none", objectPosition: `${-x}px ${-y}px`, ...style }}
{...props} {...props}
/> />
); );

View File

@ -23,11 +23,12 @@ import { FastImage, P, imageBorderRadius, tooltip, ts } from "@kyoo/primitives";
import { Platform, View } from "react-native"; import { Platform, View } from "react-native";
import { percent, useYoshiki, px, 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 { ComponentProps, useEffect, useMemo } from "react";
import { CssObject } from "yoshiki/src/web/generator"; import { CssObject } from "yoshiki/src/web/generator";
import { useAtomValue } from "jotai"; import { useAtomValue } from "jotai";
import { durationAtom, progressAtom } from "../state"; import { durationAtom, playAtom, progressAtom } from "../state";
import { toTimerString } from "./left-buttons"; import { toTimerString } from "./left-buttons";
import { useSetAtom } from "jotai";
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 };
@ -67,7 +68,19 @@ export const useScrubber = (url: string) => {
return ret; return ret;
}, [data]); }, [data]);
return { info, error } as const; const last = info?.[info.length - 1];
return {
info,
error,
stats: last
? {
rows: last.y / last.height + 1,
columns: Math.max(...info.map((x) => x.x)) / last.width + 1,
width: last.width,
height: last.height,
}
: null,
} as const;
}; };
useScrubber.query = (url: string): QueryIdentifier<string> => ({ useScrubber.query = (url: string): QueryIdentifier<string> => ({
@ -80,14 +93,14 @@ useScrubber.query = (url: string): QueryIdentifier<string> => ({
export const BottomScrubber = ({ url }: { url: string }) => { export const BottomScrubber = ({ url }: { url: string }) => {
const { css } = useYoshiki(); const { css } = useYoshiki();
const { info, error } = useScrubber(url); const { info, error, stats } = useScrubber(url);
const progress = useAtomValue(progressAtom); const progress = useAtomValue(progressAtom);
const duration = useAtomValue(durationAtom); const duration = useAtomValue(durationAtom) ?? 1;
if (error) return <ErrorView error={error} />; if (error) return <ErrorView error={error} />;
const width = info?.[0]?.width ?? 0; const width = stats?.width ?? 1;
return ( return (
<View {...css({ overflow: "hidden" })}> <View {...css({ overflow: "hidden" })}>
<View <View
@ -109,15 +122,10 @@ export const BottomScrubber = ({ url }: { url: string }) => {
alt="" alt=""
width={thumb.width} width={thumb.width}
height={thumb.height} height={thumb.height}
style={ x={thumb.x}
Platform.OS === "web" y={thumb.y}
? ({ columns={stats?.columns}
objectFit: "none", rows={stats?.rows}
objectPosition: `${-thumb.x}px ${-thumb.y}px`,
flexShrink: 0,
} as CssObject)
: undefined
}
/> />
))} ))}
</View> </View>