1
0
Fork 0
pingvin-share/frontend/src/components/share/FilePreview.tsx

186 lines
4.6 KiB
TypeScript
Raw Normal View History

2024-02-05 16:11:49 +01:00
import {
Button,
Center,
Stack,
Text,
Title,
useMantineTheme,
} from "@mantine/core";
2023-03-14 12:09:21 +01:00
import { modals } from "@mantine/modals";
import Link from "next/link";
import React, { Dispatch, SetStateAction, useEffect, useState } from "react";
import { FormattedMessage } from "react-intl";
2023-03-14 16:08:57 +01:00
import api from "../../services/api.service";
import Markdown from "markdown-to-jsx";
2023-03-14 12:09:21 +01:00
2024-03-22 01:35:55 +01:00
const webroot = process.env.WEBROOT || "";
2024-03-21 19:26:57 +01:00
2023-03-14 12:09:21 +01:00
const FilePreviewContext = React.createContext<{
shareId: string;
fileId: string;
mimeType: string;
setIsNotSupported: Dispatch<SetStateAction<boolean>>;
}>({
shareId: "",
fileId: "",
mimeType: "",
setIsNotSupported: () => {},
});
const FilePreview = ({
shareId,
fileId,
mimeType,
}: {
shareId: string;
fileId: string;
mimeType: string;
}) => {
const [isNotSupported, setIsNotSupported] = useState(false);
2024-03-21 19:26:57 +01:00
if (isNotSupported) return <UnSupportedFile />;
2024-03-22 12:17:32 +01:00
2023-03-14 12:09:21 +01:00
return (
<Stack>
<FilePreviewContext.Provider
value={{ shareId, fileId, mimeType, setIsNotSupported }}
>
<FileDecider />
</FilePreviewContext.Provider>
<Button
variant="subtle"
component={Link}
onClick={() => modals.closeAll()}
target="_blank"
2024-03-22 01:35:55 +01:00
href={`${webroot}/api/shares/${shareId}/files/${fileId}?download=false`}
2023-03-14 12:09:21 +01:00
>
View original file
{/* Add translation? */}
2023-03-14 12:09:21 +01:00
</Button>
</Stack>
);
};
const FileDecider = () => {
const { mimeType, setIsNotSupported } = React.useContext(FilePreviewContext);
if (mimeType == "application/pdf") {
return <PdfPreview />;
} else if (mimeType.startsWith("video/")) {
return <VideoPreview />;
} else if (mimeType.startsWith("image/")) {
return <ImagePreview />;
} else if (mimeType.startsWith("audio/")) {
return <AudioPreview />;
2023-03-14 16:08:57 +01:00
} else if (mimeType.startsWith("text/")) {
2023-03-14 12:09:21 +01:00
return <TextPreview />;
} else {
setIsNotSupported(true);
return null;
}
};
const AudioPreview = () => {
const { shareId, fileId, setIsNotSupported } =
React.useContext(FilePreviewContext);
return (
<Center style={{ minHeight: 200 }}>
<Stack align="center" spacing={10} style={{ width: "100%" }}>
<audio controls style={{ width: "100%" }}>
<source
src={`/api/shares/${shareId}/files/${fileId}?download=false`}
onError={() => setIsNotSupported(true)}
/>
</audio>
</Stack>
</Center>
);
};
const VideoPreview = () => {
const { shareId, fileId, setIsNotSupported } =
React.useContext(FilePreviewContext);
return (
<video width="100%" controls>
<source
src={`/api/shares/${shareId}/files/${fileId}?download=false`}
onError={() => setIsNotSupported(true)}
/>
</video>
);
};
const ImagePreview = () => {
const { shareId, fileId, setIsNotSupported } =
React.useContext(FilePreviewContext);
return (
// eslint-disable-next-line @next/next/no-img-element
<img
src={`/api/shares/${shareId}/files/${fileId}?download=false`}
alt={`${fileId}_preview`}
width="100%"
onError={() => setIsNotSupported(true)}
/>
);
};
const TextPreview = () => {
const { shareId, fileId } = React.useContext(FilePreviewContext);
2024-02-05 16:11:49 +01:00
const [text, setText] = useState<string>("");
const { colorScheme } = useMantineTheme();
2023-03-14 12:09:21 +01:00
useEffect(() => {
2023-05-09 08:45:30 +02:00
api
.get(`/shares/${shareId}/files/${fileId}?download=false`)
.then((res) => setText(res.data ?? "Preview couldn't be fetched."));
2024-02-05 16:11:49 +01:00
}, [shareId, fileId]);
const options = {
overrides: {
pre: {
props: {
style: {
2024-02-05 16:11:49 +01:00
backgroundColor:
colorScheme == "dark"
? "rgba(50, 50, 50, 0.5)"
: "rgba(220, 220, 220, 0.5)",
padding: "0.75em",
whiteSpace: "pre-wrap",
2024-02-05 16:11:49 +01:00
},
},
},
table: {
props: {
2024-02-05 16:11:49 +01:00
className: "md",
},
},
},
};
2023-03-14 12:09:21 +01:00
2024-02-05 16:11:49 +01:00
return <Markdown options={options}>{text}</Markdown>;
2023-03-14 12:09:21 +01:00
};
const PdfPreview = () => {
const { shareId, fileId } = React.useContext(FilePreviewContext);
if (typeof window !== "undefined") {
window.location.href = `/api/shares/${shareId}/files/${fileId}?download=false`;
}
return null;
};
const UnSupportedFile = () => {
return (
<Center style={{ minHeight: 200 }}>
<Stack align="center" spacing={10}>
<Title order={3}>
<FormattedMessage id="share.modal.file-preview.error.not-supported.title" />
</Title>
2023-03-14 12:09:21 +01:00
<Text>
<FormattedMessage id="share.modal.file-preview.error.not-supported.description" />
2023-03-14 12:09:21 +01:00
</Text>
</Stack>
</Center>
);
};
export default FilePreview;