2021-05-27 11:20:34 +03:00
|
|
|
import * as React from "react";
|
|
|
|
import * as Styles from "~/common/styles";
|
|
|
|
import * as Strings from "~/common/strings";
|
|
|
|
|
|
|
|
import { AspectRatio } from "~/components/system";
|
|
|
|
import { useInView } from "~/common/hooks";
|
|
|
|
import { Blurhash } from "react-blurhash";
|
|
|
|
import { isBlurhashValid } from "blurhash";
|
|
|
|
|
|
|
|
import { css } from "@emotion/react";
|
2021-07-14 13:14:33 +03:00
|
|
|
import ObjectPreviewPrimitive from "./ObjectPreviewPrimitive";
|
2021-05-27 11:20:34 +03:00
|
|
|
|
|
|
|
const STYLES_PLACEHOLDER_ABSOLUTE = css`
|
|
|
|
position: absolute;
|
|
|
|
top: 0%;
|
|
|
|
left: 0%;
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
`;
|
|
|
|
const STYLES_FLUID_CONTAINER = css`
|
|
|
|
position: relative;
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
`;
|
|
|
|
|
|
|
|
const STYLES_IMAGE = css`
|
|
|
|
object-fit: cover;
|
2021-07-20 13:19:40 +03:00
|
|
|
height: 100%;
|
|
|
|
width: 100%;
|
2021-05-27 11:20:34 +03:00
|
|
|
`;
|
|
|
|
|
|
|
|
const ImagePlaceholder = ({ blurhash }) => (
|
|
|
|
<div css={STYLES_PLACEHOLDER_ABSOLUTE}>
|
|
|
|
<div css={[Styles.CONTAINER_CENTERED, STYLES_FLUID_CONTAINER]}>
|
2021-07-20 13:19:40 +03:00
|
|
|
<AspectRatio ratio={1}>
|
2021-05-27 11:20:34 +03:00
|
|
|
<div>
|
|
|
|
<Blurhash
|
|
|
|
hash={blurhash}
|
|
|
|
height="100%"
|
|
|
|
width="100%"
|
|
|
|
resolutionX={32}
|
|
|
|
resolutionY={32}
|
|
|
|
punch={1}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</AspectRatio>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
|
2021-07-20 13:19:40 +03:00
|
|
|
export default function ImageObjectPreview({
|
|
|
|
url,
|
|
|
|
file,
|
|
|
|
//NOTE(amine): ImageObjectPreview is used to display cover image for other objects, so we need to pass the tag down
|
|
|
|
tag,
|
|
|
|
...props
|
|
|
|
}) {
|
2021-05-27 11:20:34 +03:00
|
|
|
const previewerRef = React.useRef();
|
|
|
|
const [isLoading, setLoading] = React.useState(true);
|
|
|
|
const handleOnLoaded = () => setLoading(false);
|
|
|
|
|
|
|
|
const { isInView } = useInView({
|
|
|
|
ref: previewerRef,
|
|
|
|
});
|
|
|
|
|
|
|
|
const { type, coverImage } = file.data;
|
2021-07-20 13:19:40 +03:00
|
|
|
const imgTag = type.split("/")[1];
|
2021-05-27 11:20:34 +03:00
|
|
|
|
|
|
|
const blurhash = React.useMemo(() => {
|
|
|
|
return file.data.blurhash && isBlurhashValid(file.data.blurhash)
|
|
|
|
? file.data.blurhash
|
|
|
|
: coverImage?.data.blurhash && isBlurhashValid(coverImage?.data.blurhash)
|
|
|
|
? coverImage?.data.blurhash
|
|
|
|
: null;
|
|
|
|
}, [file]);
|
|
|
|
|
|
|
|
const shouldShowPlaceholder = isLoading && blurhash;
|
|
|
|
|
2021-07-28 20:50:49 +03:00
|
|
|
const imageUrl = coverImage
|
|
|
|
? coverImage?.data?.url || Strings.getURLfromCID(coverImage?.cid)
|
|
|
|
: url;
|
2021-05-27 11:20:34 +03:00
|
|
|
|
|
|
|
return (
|
2021-07-20 13:19:40 +03:00
|
|
|
<ObjectPreviewPrimitive file={file} tag={tag || imgTag} isImage {...props}>
|
2021-05-27 11:20:34 +03:00
|
|
|
<div ref={previewerRef} css={[Styles.CONTAINER_CENTERED, STYLES_FLUID_CONTAINER]}>
|
|
|
|
{isInView && (
|
2021-07-20 13:19:40 +03:00
|
|
|
<img
|
|
|
|
css={STYLES_IMAGE}
|
|
|
|
src={imageUrl}
|
|
|
|
alt={`${file.name} preview`}
|
|
|
|
onLoad={handleOnLoaded}
|
|
|
|
/>
|
2021-05-27 11:20:34 +03:00
|
|
|
)}
|
|
|
|
{shouldShowPlaceholder && <ImagePlaceholder blurhash={blurhash} />}
|
|
|
|
</div>
|
2021-07-14 13:14:33 +03:00
|
|
|
</ObjectPreviewPrimitive>
|
2021-05-27 11:20:34 +03:00
|
|
|
);
|
|
|
|
}
|