diff --git a/src/components/EventReports.jsx b/src/components/EventReports.jsx
index 0f0810d..6ee3baf 100644
--- a/src/components/EventReports.jsx
+++ b/src/components/EventReports.jsx
@@ -15,6 +15,7 @@ import {
useRecordContext,
useTranslate,
} from "react-admin";
+import { MXCField } from "./media";
import PageviewIcon from "@mui/icons-material/Pageview";
import ReportIcon from "@mui/icons-material/Warning";
import ViewListIcon from "@mui/icons-material/ViewList";
@@ -89,6 +90,8 @@ export const ReportShow = props => {
+
+
diff --git a/src/components/media.jsx b/src/components/media.jsx
index cc06a0b..1da27b9 100644
--- a/src/components/media.jsx
+++ b/src/components/media.jsx
@@ -1,4 +1,5 @@
import React, { useState } from "react";
+import get from "lodash/get";
import {
BooleanInput,
Button,
@@ -14,10 +15,12 @@ import {
useRefresh,
useTranslate,
} from "react-admin";
+import { Link } from "react-router-dom";
import BlockIcon from "@mui/icons-material/Block";
import ClearIcon from "@mui/icons-material/Clear";
import DeleteSweepIcon from "@mui/icons-material/DeleteSweep";
import {
+ Box,
Dialog,
DialogContent,
DialogContentText,
@@ -27,7 +30,9 @@ import {
import IconCancel from "@mui/icons-material/Cancel";
import LockIcon from "@mui/icons-material/Lock";
import LockOpenIcon from "@mui/icons-material/LockOpen";
+import FileOpenIcon from "@mui/icons-material/FileOpen";
import { alpha, useTheme } from "@mui/material/styles";
+import { getMediaUrl } from "../synapse/synapse";
const DeleteMediaDialog = ({ open, loading, onClose, onSubmit }) => {
const translate = useTranslate();
@@ -333,3 +338,49 @@ export const QuarantineMediaButton = props => {
>
);
};
+
+export const ViewMediaButton = ({ media_id, label }) => {
+ const translate = useTranslate();
+ const url = getMediaUrl(media_id);
+ return (
+
+
+
+
+
+
+ {label}
+
+ );
+};
+
+export const MediaIDField = ({ source }) => {
+ const homeserver = localStorage.getItem("home_server");
+ const record = useRecordContext();
+ if (!record) return null;
+
+ const src = get(record, source)?.toString();
+ if (!src) return null;
+
+ return ;
+};
+
+export const MXCField = ({ source }) => {
+ const record = useRecordContext();
+ if (!record) return null;
+
+ const src = get(record, source)?.toString();
+ if (!src) return null;
+
+ const media_id = src.replace("mxc://", "");
+
+ return ;
+};
diff --git a/src/components/users.jsx b/src/components/users.jsx
index f1744cc..683482d 100644
--- a/src/components/users.jsx
+++ b/src/components/users.jsx
@@ -51,7 +51,11 @@ import { Link } from "react-router-dom";
import AvatarField from "./AvatarField";
import { ServerNoticeButton, ServerNoticeBulkButton } from "./ServerNotices";
import { DeviceRemoveButton } from "./devices";
-import { ProtectMediaButton, QuarantineMediaButton } from "./media";
+import {
+ MediaIDField,
+ ProtectMediaButton,
+ QuarantineMediaButton,
+} from "./media";
const choices_medium = [
{ id: "email", name: "resources.users.email" },
@@ -449,13 +453,13 @@ export const UserEdit = props => {
sort={{ field: "created_ts", order: "DESC" }}
>
+
-
diff --git a/src/i18n/de.js b/src/i18n/de.js
index c7d8014..bd5f2a6 100644
--- a/src/i18n/de.js
+++ b/src/i18n/de.js
@@ -208,6 +208,9 @@ const de = {
format: "Nachrichtenformat",
formatted_body: "Formatierter Nachrichteninhalt",
algorithm: "Verschlüsselungsalgorithmus",
+ info: {
+ mimetype: "Typ",
+ },
},
},
},
@@ -256,6 +259,9 @@ const de = {
created_ts: "Erstellt",
last_access_ts: "Letzter Zugriff",
},
+ action: {
+ open: "Mediendatei in neuem Fenster öffnen",
+ },
},
delete_media: {
name: "Medien",
diff --git a/src/i18n/en.js b/src/i18n/en.js
index af5c58a..27a6d17 100644
--- a/src/i18n/en.js
+++ b/src/i18n/en.js
@@ -205,6 +205,10 @@ const en = {
format: "format",
formatted_body: "formatted content",
algorithm: "algorithm",
+ url: "URL",
+ info: {
+ mimetype: "Type",
+ },
},
},
},
@@ -253,6 +257,9 @@ const en = {
created_ts: "Created",
last_access_ts: "Last access",
},
+ action: {
+ open: "Open media file in new window",
+ },
},
delete_media: {
name: "Media",
diff --git a/src/synapse/synapse.js b/src/synapse/synapse.js
index ddd4136..915144c 100644
--- a/src/synapse/synapse.js
+++ b/src/synapse/synapse.js
@@ -53,3 +53,8 @@ export const getSupportedLoginFlows = async baseUrl => {
const response = await fetchUtils.fetchJson(loginFlowsUrl, { method: "GET" });
return response.json.flows;
};
+
+export const getMediaUrl = media_id => {
+ const baseUrl = localStorage.getItem("base_url");
+ return `${baseUrl}/_matrix/media/v1/download/${media_id}?allow_redirect=true`;
+};