'init'
This commit is contained in:
154
app/components/MessageAttachments/MessageImage.tsx
Normal file
154
app/components/MessageAttachments/MessageImage.tsx
Normal file
@@ -0,0 +1,154 @@
|
||||
import { useRosettaColors } from "@/app/hooks/useRosettaColors";
|
||||
import { DeliveredMessageState } from "@/app/providers/DialogProvider/DialogProvider";
|
||||
import { useImageViewer } from "@/app/providers/ImageViewerProvider/useImageViewer";
|
||||
import { AspectRatio, Box, Flex, Overlay, Portal, Text } from "@mantine/core";
|
||||
import { IconArrowDown, IconCircleX, IconFlameFilled } from "@tabler/icons-react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { AttachmentProps } from "./MessageAttachments";
|
||||
import { blurhashToBase64Image, isMessageDeliveredByTime } from "@/app/utils/utils";
|
||||
import { AnimatedRoundedProgress } from "../AnimatedRoundedProgress/AnimatedRoundedProgress";
|
||||
import { ImageToView } from "@/app/providers/ImageViewerProvider/ImageViewerProvider";
|
||||
import { DownloadStatus, useAttachment } from "@/app/providers/AttachmentProvider/useAttachment";
|
||||
|
||||
export function MessageImage(props: AttachmentProps) {
|
||||
const colors = useRosettaColors();
|
||||
const {
|
||||
downloadPercentage,
|
||||
uploadedPercentage,
|
||||
download,
|
||||
downloadStatus,
|
||||
getBlob,
|
||||
getPreview} = useAttachment(props.attachment, props.chacha_key_plain);
|
||||
const mainRef = useRef<HTMLDivElement>(null);
|
||||
const error = downloadStatus == DownloadStatus.ERROR;
|
||||
const { open } = useImageViewer();
|
||||
const preview = getPreview();
|
||||
const [blob, setBlob] = useState(props.attachment.blob);
|
||||
const [loadedImage, setLoadedImage] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
constructBlob();
|
||||
}, [downloadStatus]);
|
||||
|
||||
const constructBlob = async () => {
|
||||
let blob = await getBlob();
|
||||
setBlob(blob);
|
||||
}
|
||||
|
||||
const openImageViewer = () => {
|
||||
const images: ImageToView[] = [{
|
||||
src: blob,
|
||||
caption: props.text,
|
||||
timestamp: props.timestamp
|
||||
}];
|
||||
|
||||
open(images, 0);
|
||||
}
|
||||
|
||||
const onClick = () => {
|
||||
if (downloadStatus == DownloadStatus.DOWNLOADED) {
|
||||
openImageViewer();
|
||||
return;
|
||||
}
|
||||
if (downloadStatus == DownloadStatus.NOT_DOWNLOADED) {
|
||||
download();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<AspectRatio onClick={onClick} ref={mainRef} style={{
|
||||
minWidth: 200,
|
||||
minHeight: 220,
|
||||
maxWidth: 200,
|
||||
maxHeight: 220,
|
||||
borderRadius: 8,
|
||||
cursor: 'pointer',
|
||||
userSelect: 'none'
|
||||
}} pos={'relative'}>
|
||||
{blob != "" && (
|
||||
<img style={{
|
||||
minHeight: 220,
|
||||
width: '100%',
|
||||
borderRadius: 8,
|
||||
objectFit: 'cover',
|
||||
backgroundColor: '#FFFFFF',
|
||||
border: '1px solid ' + colors.borderColor,
|
||||
display: loadedImage ? 'block' : 'none'
|
||||
}} src={blob} onLoad={() => setLoadedImage(true)}></img>)}
|
||||
{((downloadStatus != DownloadStatus.DOWNLOADED && downloadStatus != DownloadStatus.PENDING) || !loadedImage) && preview.length >= 20 && (
|
||||
<>
|
||||
<img style={{
|
||||
minHeight: 220,
|
||||
width: '100%',
|
||||
borderRadius: 8,
|
||||
objectFit: 'cover',
|
||||
border: '1px solid ' + colors.borderColor
|
||||
}} src={/*block render???*/blurhashToBase64Image(preview, 200, 220)}></img>
|
||||
<Portal target={mainRef.current!}>
|
||||
<Flex direction={'column'} pos={'absolute'} justify={'center'} top={0} h={'100%'} align={'center'} gap={'xs'}>
|
||||
{!error && (
|
||||
<Box style={{
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.3)',
|
||||
borderRadius: 50,
|
||||
height: 40,
|
||||
width: 40,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}>
|
||||
{downloadPercentage > 0 ? (
|
||||
<AnimatedRoundedProgress size={40} value={downloadPercentage} color="white"></AnimatedRoundedProgress>
|
||||
) : (
|
||||
<IconArrowDown size={25} color={'white'} />
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
{error && (
|
||||
<Box p={'xs'} style={{
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.3)',
|
||||
borderRadius: 8,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
gap: 4
|
||||
}}>
|
||||
<Text size={'xs'} c={'white'}>
|
||||
Image expired
|
||||
</Text>
|
||||
<IconFlameFilled size={15} style={{
|
||||
fontSmooth: 'always'
|
||||
}} color={'white'} />
|
||||
</Box>
|
||||
)}
|
||||
</Flex>
|
||||
</Portal>
|
||||
</>
|
||||
)}
|
||||
|
||||
{(props.delivered == DeliveredMessageState.WAITING && uploadedPercentage > 0 && isMessageDeliveredByTime(props.timestamp || 0, props.attachments.length)) &&
|
||||
<Portal target={mainRef.current!}>
|
||||
<Flex direction={'column'} pos={'absolute'} justify={'center'} top={0} h={'100%'} align={'center'} gap={'xs'}>
|
||||
<Box style={{
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.3)',
|
||||
borderRadius: 50,
|
||||
height: 40,
|
||||
width: 40,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}>
|
||||
<AnimatedRoundedProgress size={40} value={uploadedPercentage > 95 ? 95 : uploadedPercentage}></AnimatedRoundedProgress>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Portal>}
|
||||
{(props.delivered == DeliveredMessageState.ERROR || (props.delivered != DeliveredMessageState.DELIVERED &&
|
||||
!isMessageDeliveredByTime(props.timestamp || 0, props.attachments.length)
|
||||
)) && (
|
||||
<Overlay center h={'100%'} radius={8} color="#000" opacity={0.85}>
|
||||
<IconCircleX size={40} color={colors.error} />
|
||||
</Overlay>
|
||||
)}
|
||||
</AspectRatio>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user