diff --git a/README.md b/README.md
index 66543e8..b10040f 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,7 @@ The following changes are already implemented:
* [Add `Contact support` menu item](https://github.com/etkecc/synapse-admin/pull/45)
* [Provide options to delete media and redact events on user erase](https://github.com/etkecc/synapse-admin/pull/49)
* [Authenticated Media support](https://github.com/etkecc/synapse-admin/pull/51)
+* [Better media preview/download](https://github.com/etkecc/synapse-admin/pull/53)
_the list will be updated as new changes are added_
diff --git a/src/components/media.tsx b/src/components/media.tsx
index 050c6ec..d1e73f4 100644
--- a/src/components/media.tsx
+++ b/src/components/media.tsx
@@ -1,7 +1,6 @@
import { get } from "lodash";
import { useState } from "react";
-import Typography from "@mui/material/Typography";
import BlockIcon from "@mui/icons-material/Block";
import IconCancel from "@mui/icons-material/Cancel";
import ClearIcon from "@mui/icons-material/Clear";
@@ -9,10 +8,9 @@ import DeleteSweepIcon from "@mui/icons-material/DeleteSweep";
import FileOpenIcon from "@mui/icons-material/FileOpen";
import LockIcon from "@mui/icons-material/Lock";
import LockOpenIcon from "@mui/icons-material/LockOpen";
-import IconButton from '@mui/material/IconButton';
-import CloseIcon from '@mui/icons-material/Close';
-import ZoomInIcon from '@mui/icons-material/ZoomIn';
-import { Box, Dialog, DialogContent, DialogContentText, DialogTitle, Tooltip, Link } from "@mui/material";
+import DownloadIcon from '@mui/icons-material/Download';
+import DownloadingIcon from '@mui/icons-material/Downloading';
+import { Grid2 as Grid, Box, Dialog, DialogContent, DialogContentText, DialogTitle, Tooltip, Link } from "@mui/material";
import { alpha, useTheme } from "@mui/material/styles";
import {
BooleanInput,
@@ -314,17 +312,10 @@ export const QuarantineMediaButton = (props: ButtonProps) => {
);
};
-export const ViewMediaButton = ({ mxcURL, label, mimetype }) => {
- if (!mimetype.startsWith("image/")) {
- return (
- <>
-
- {label}
-
- >
- );
- }
+export const ViewMediaButton = ({ mxcURL, label, uploadName, mimetype }) => {
const translate = useTranslate();
+ const [loading, setLoading] = useState(false);
+ const isImage = mimetype && mimetype.startsWith("image/");
const openFileInNewTab = (blobURL: string) => {
const anchorElement = document.createElement("a");
@@ -336,27 +327,54 @@ export const ViewMediaButton = ({ mxcURL, label, mimetype }) => {
setTimeout(() => URL.revokeObjectURL(blobURL), 10);
};
- const previewFile = async () => {
+ const downloadFile = async (blobURL: string) => {
+ console.log("downloadFile", blobURL, uploadName);
+ const anchorElement = document.createElement("a");
+ anchorElement.href = blobURL;
+ anchorElement.download = uploadName;
+ document.body.appendChild(anchorElement);
+ anchorElement.click();
+ document.body.removeChild(anchorElement);
+ setTimeout(() => URL.revokeObjectURL(blobURL), 10);;
+ };
+
+ const handleFile = async (preview: boolean) => {
+ setLoading(true);
const response = await fetchAuthenticatedMedia(mxcURL, "original");
const blob = await response.blob();
const blobURL = URL.createObjectURL(blob);
- openFileInNewTab(blobURL);
+ if (preview) {
+ openFileInNewTab(blobURL);
+ } else {
+ downloadFile(blobURL);
+ }
+ setLoading(false);
};
return (
<>
-
+
-
+ {isImage && (
+
+ )}
- {label}
+
+ {label}
>
);
@@ -374,9 +392,10 @@ export const MediaIDField = ({ source }) => {
return null;
}
+ const uploadName = decodeURIComponent(get(record, "upload_name")?.toString());
const mxcURL = `mxc://${homeserver}/${mediaID}`;
- return ;
+ return ;
};
export const ReportMediaContent = ({ source }) => {
@@ -390,5 +409,7 @@ export const ReportMediaContent = ({ source }) => {
return null;
}
- return ;
+ const uploadName = decodeURIComponent(get(record, "event_json.content.body")?.toString());
+
+ return ;
};