Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1c717d5
make dialog windows full screen on mobile
aine-etke Mar 20, 2026
25dbeb8
improve user delete button (show icon-only on mobile); truncate foote…
aine-etke Mar 20, 2026
388b1bd
make tabs scrollable
aine-etke Mar 20, 2026
6404f08
fix horizontal scroll and container sizing on view/edit pages; center…
aine-etke Mar 21, 2026
f05508a
replace all plain datagrids with configurable options
aine-etke Mar 21, 2026
021374f
add mobile-friendly user list; add user account status icons to the m…
aine-etke Mar 21, 2026
6a5c806
hide some filters by default
aine-etke Mar 21, 2026
9b6aee9
make etke.cc components mobile-frinedly
aine-etke Mar 21, 2026
9d92d4c
make rooms list mobile-friendly
aine-etke Mar 21, 2026
017bc22
make user media stats list mobile-friendly; add human-readable media …
aine-etke Mar 21, 2026
9637fbd
make room directory mobile-friendly
aine-etke Mar 21, 2026
aa31b6b
make destinations table mobile-friendly
aine-etke Mar 21, 2026
30768df
make registration tokens mobile friendly
aine-etke Mar 21, 2026
b58d50e
make user devices list mobile-friendly
aine-etke Mar 21, 2026
84b46a9
make user connections mobile friendly
aine-etke Mar 21, 2026
ea37a1a
make user media list mobile-friendly
aine-etke Mar 21, 2026
c048c40
make user joined rooms list mobile-friendly
aine-etke Mar 21, 2026
f27f4cb
make user memberships mobile-friendly
aine-etke Mar 21, 2026
aad81e0
make user pushers mobile-friendly
aine-etke Mar 21, 2026
b2f9aa0
make user account data mobile-friendly
aine-etke Mar 21, 2026
65073f3
make room members list configurable
aine-etke Mar 21, 2026
3f8374d
make rooms media list mobile-friendly
aine-etke Mar 21, 2026
5e0bc81
make room state events mobile-friendly
aine-etke Mar 21, 2026
c0794c4
make rooms forward extremities mobile-friendly
aine-etke Mar 21, 2026
ba2a69a
improve display of long IDs and names on mobile
aine-etke Mar 21, 2026
d25a088
optimize login page for mobile
aine-etke Mar 21, 2026
f074bac
fix lint
aine-etke Mar 21, 2026
250740a
update readme
aine-etke Mar 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ The following changes are already implemented:
* 💬 [Add room messages viewer with filters and jump-to-date](https://github.com/etkecc/synapse-admin/commit/60818ca3604aef61e2b5abc0d92e14771bb53637)
* 🏗️ [Add Room hierarchy tab](https://github.com/etkecc/synapse-admin/commit/566b7148b5cb3e2fab55078621ba2cb4203b21a1)
* ⚙️ [Add control of admin flags for Matrix Client-Server APIs](https://github.com/etkecc/synapse-admin/commit/b272cc11945d8e6adabb3cfe4904ad0ac063549d)
* 📱 [Optimize UI for mobile](https://github.com/etkecc/synapse-admin/pull/1104)

#### exclusive for [etke.cc](https://etke.cc) customers

Expand Down
4 changes: 2 additions & 2 deletions src/auth-callback-error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const AuthCallbackErrorView = ({ message, onBack }: { message: string; onBack: (
)}
<Card className="card">
<Box className="avatar">
<Avatar sx={{ width: "120px", height: "120px" }} src={logoUrl} />
<Avatar sx={{ width: { xs: "80px", sm: "120px" }, height: { xs: "80px", sm: "120px" } }} src={logoUrl} />
</Box>
<Box className="hint">{translate("synapseadmin.auth.welcome", { name: welcomeTo })}</Box>
<Box className="form">
Expand All @@ -52,7 +52,7 @@ const AuthCallbackErrorView = ({ message, onBack }: { message: string; onBack: (
</Typography>
</Box>
<CardActions className="actions">
<Button size="small" variant="contained" type="button" color="primary" onClick={onBack} fullWidth>
<Button variant="contained" type="button" color="primary" onClick={onBack} fullWidth>
{translate("ra.action.back")}
</Button>
</CardActions>
Expand Down
14 changes: 11 additions & 3 deletions src/components/BlockRoomButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
DialogTitle,
TextField,
} from "@mui/material";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useEffect, useState } from "react";
import {
Button,
Expand All @@ -30,6 +32,8 @@ import { SynapseDataProvider } from "../providers/types";
* Block requires confirmation modal, unblock is direct.
*/
export const BlockRoomButton = () => {
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"));
const record = useRecordContext();
const [open, setOpen] = useState(false);
const [blocked, setBlocked] = useState<boolean | null>(null);
Expand Down Expand Up @@ -110,7 +114,7 @@ export const BlockRoomButton = () => {
<Button label="resources.rooms.action.block.label" onClick={() => setOpen(true)} disabled={loading}>
<BlockIcon />
</Button>
<Dialog open={open} onClose={() => setOpen(false)} maxWidth="sm" fullWidth>
<Dialog open={open} onClose={() => setOpen(false)} maxWidth="sm" fullWidth fullScreen={fullScreen}>
<DialogTitle>{translate("resources.rooms.action.block.title", { room: roomName })}</DialogTitle>
<DialogContent>
<DialogContentText>{translate("resources.rooms.action.block.content")}</DialogContentText>
Expand Down Expand Up @@ -138,6 +142,8 @@ export const BlockRoomButton = () => {
* Bulk block/unblock buttons for room lists (main room list + joined_rooms).
*/
export const BlockRoomBulkButton = () => {
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"));
const { selectedIds } = useListContext();
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -170,7 +176,7 @@ export const BlockRoomBulkButton = () => {
<Button label="resources.rooms.action.block.label" onClick={() => setOpen(true)} disabled={loading}>
<BlockIcon />
</Button>
<Dialog open={open} onClose={() => setOpen(false)} maxWidth="sm" fullWidth>
<Dialog open={open} onClose={() => setOpen(false)} maxWidth="sm" fullWidth fullScreen={fullScreen}>
<DialogTitle>
{translate("resources.rooms.action.block.title_bulk", { smart_count: selectedIds.length })}
</DialogTitle>
Expand Down Expand Up @@ -234,6 +240,8 @@ export const UnblockRoomBulkButton = () => {
* Toolbar button above the main room list to block a room by ID.
*/
export const BlockRoomByIdButton = () => {
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"));
const [open, setOpen] = useState(false);
const [roomId, setRoomId] = useState("");
const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -268,7 +276,7 @@ export const BlockRoomByIdButton = () => {
<Button label="resources.rooms.action.block.label" onClick={() => setOpen(true)}>
<BlockIcon />
</Button>
<Dialog open={open} onClose={() => setOpen(false)} maxWidth="sm" fullWidth>
<Dialog open={open} onClose={() => setOpen(false)} maxWidth="sm" fullWidth fullScreen={fullScreen}>
<DialogTitle>{translate("resources.rooms.action.block.title_by_id")}</DialogTitle>
<DialogContent>
<DialogContentText sx={{ mb: 2 }}>{translate("resources.rooms.action.block.content")}</DialogContentText>
Expand Down
6 changes: 5 additions & 1 deletion src/components/DeleteRoomButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
DialogContentText,
DialogTitle,
} from "@mui/material";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { Fragment, useCallback, useEffect, useRef, useState } from "react";
import {
Button,
Expand Down Expand Up @@ -37,6 +39,8 @@ interface DeleteRoomButtonProps {
const resourceName = "rooms";

const DeleteRoomButton: React.FC<DeleteRoomButtonProps> = props => {
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"));
const translate = useTranslate();
const [open, setOpen] = useState(false);
const [block, setBlock] = useState(false);
Expand Down Expand Up @@ -163,7 +167,7 @@ const DeleteRoomButton: React.FC<DeleteRoomButtonProps> = props => {
>
<ActionDelete />
</Button>
<Dialog open={open} onClose={handleDialogClose}>
<Dialog open={open} onClose={handleDialogClose} maxWidth="sm" fullWidth fullScreen={fullScreen}>
<DialogTitle>{translate(props.confirmTitle)}</DialogTitle>
<DialogContent>
<DialogContentText>{translate(props.confirmContent)}</DialogContentText>
Expand Down
27 changes: 13 additions & 14 deletions src/components/DeleteUserButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@ import ActionCheck from "@mui/icons-material/CheckCircle";
import ActionDelete from "@mui/icons-material/Delete";
import AlertError from "@mui/icons-material/ErrorOutline";
import {
Button,
Button as MuiButton,
CircularProgress,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
} from "@mui/material";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { Fragment, useCallback, useEffect, useRef, useState } from "react";
import {
Button,
SimpleForm,
BooleanInput,
useTranslate,
Expand All @@ -35,6 +38,8 @@ interface DeleteUserButtonProps {
const resourceName = "users";

const DeleteUserButton: React.FC<DeleteUserButtonProps> = props => {
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"));
const translate = useTranslate();
const [open, setOpen] = useState(false);
const [deleteMedia, setDeleteMedia] = useState(false);
Expand Down Expand Up @@ -159,22 +164,16 @@ const DeleteUserButton: React.FC<DeleteUserButtonProps> = props => {
return (
<Fragment>
<Button
label="ra.action.delete"
onClick={handleDialogOpen}
disabled={loading}
className={"ra-delete-button"}
key="button"
size="small"
sx={{
"&.MuiButton-sizeSmall": {
lineHeight: 1.5,
},
}}
color={"error"}
startIcon={<ActionDelete />}
>
{translate("ra.action.delete")}
<ActionDelete />
</Button>
<Dialog open={open} onClose={handleDialogClose}>
<Dialog open={open} onClose={handleDialogClose} maxWidth="sm" fullWidth fullScreen={fullScreen}>
<DialogTitle>{translate(props.confirmTitle)}</DialogTitle>
<DialogContent>
<DialogContentText>{translate(props.confirmContent)}</DialogContentText>
Expand Down Expand Up @@ -209,18 +208,18 @@ const DeleteUserButton: React.FC<DeleteUserButtonProps> = props => {
)}
</DialogContent>
<DialogActions>
<Button onClick={handleDialogClose} startIcon={<AlertError />}>
<MuiButton onClick={handleDialogClose} startIcon={<AlertError />}>
{translate("ra.action.cancel")}
</Button>
<Button
</MuiButton>
<MuiButton
disabled={loading}
onClick={handleConfirm}
className={"ra-confirm RaConfirm-confirmPrimary"}
autoFocus
startIcon={loading ? <CircularProgress size={16} /> : <ActionCheck />}
>
{translate("ra.action.confirm")}
</Button>
</MuiButton>
</DialogActions>
</Dialog>
</Fragment>
Expand Down
14 changes: 10 additions & 4 deletions src/components/DeviceCreateButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Button as MuiButton, Dialog, DialogActions, DialogContent, DialogTitle,
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useState } from "react";
import { Button, useNotify, useRecordContext, useRefresh, useTranslate } from "react-admin";
import { useNotify, useRecordContext, useRefresh, useTranslate } from "react-admin";

import { jsonClient } from "../providers/httpClients";
import { invalidateManyRefCache } from "../providers/resourceMap";
Expand Down Expand Up @@ -50,9 +50,15 @@ const DeviceCreateButton = () => {

return (
<>
<Button label="resources.devices.action.create.label" onClick={() => setOpen(true)}>
<AddIcon />
</Button>
<MuiButton
variant="outlined"
size="small"
startIcon={<AddIcon />}
onClick={() => setOpen(true)}
fullWidth={fullScreen}
>
{translate("resources.devices.action.create.label")}
</MuiButton>
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth fullScreen={fullScreen}>
<DialogTitle>{translate("resources.devices.action.create.title")}</DialogTitle>
<DialogContent>
Expand Down
35 changes: 19 additions & 16 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,26 @@ const Footer = ({ logoSrc = "./images/logo.webp" }: { logoSrc?: string }) => {
<Avatar src={logoSrc} sx={{ width: "1rem", height: "1rem", display: "inline-block", verticalAlign: "sub" }} />{" "}
<Link href="https://github.com/etkecc/synapse-admin" target="_blank" sx={{ color: "inherit" }}>
Synapse Admin {version}
</Link>{" "}
by{" "}
<Link
href="https://etke.cc/?utm_source=synapse-admin&utm_medium=footer&utm_campaign=synapse-admin"
target="_blank"
sx={{ color: "inherit" }}
>
etke.cc
</Link>{" "}
(originally developed by Awesome Technologies Innovationslabor GmbH).{" "}
<Link
sx={{ fontWeight: "bold", color: "inherit" }}
href="https://matrix.to/#/#synapse-admin:etke.cc"
target="_blank"
>
#synapse-admin:etke.cc
</Link>
<Box component="span" sx={{ display: { xs: "none", sm: "inline" } }}>
{" "}
by{" "}
<Link
href="https://etke.cc/?utm_source=synapse-admin&utm_medium=footer&utm_campaign=synapse-admin"
target="_blank"
sx={{ color: "inherit" }}
>
etke.cc
</Link>{" "}
(originally developed by Awesome Technologies Innovationslabor GmbH).{" "}
<Link
sx={{ fontWeight: "bold", color: "inherit" }}
href="https://matrix.to/#/#synapse-admin:etke.cc"
target="_blank"
>
#synapse-admin:etke.cc
</Link>
</Box>
</Box>
);
};
Expand Down
8 changes: 6 additions & 2 deletions src/components/LoginAsUserButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ import {
TextField,
Typography,
} from "@mui/material";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useState } from "react";
import { Button, useDataProvider, useLocale, useNotify, useRecordContext, useTranslate } from "react-admin";

import { SynapseDataProvider } from "../providers/types";

export const LoginAsUserButton = () => {
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"));
const record = useRecordContext();
const [open, setOpen] = useState(false);
const [resultOpen, setResultOpen] = useState(false);
Expand Down Expand Up @@ -74,7 +78,7 @@ export const LoginAsUserButton = () => {
<Button label="resources.users.action.login_as.label" onClick={handleOpen} disabled={loading}>
<LoginIcon />
</Button>
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth>
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth fullScreen={fullScreen}>
<DialogTitle>{translate("resources.users.action.login_as.title")}</DialogTitle>
<DialogContent>
<DialogContentText sx={{ mb: 2 }}>
Expand Down Expand Up @@ -110,7 +114,7 @@ export const LoginAsUserButton = () => {
</MuiButton>
</DialogActions>
</Dialog>
<Dialog open={resultOpen} onClose={handleResultClose} maxWidth="sm" fullWidth>
<Dialog open={resultOpen} onClose={handleResultClose} maxWidth="sm" fullWidth fullScreen={fullScreen}>
<DialogTitle>{translate("resources.users.action.login_as.result_title", { user: record.id })}</DialogTitle>
<DialogContent>
<TextField
Expand Down
1 change: 1 addition & 0 deletions src/components/LoginFormBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ const LoginFormBox = styled(Box, {
[`& .card`]: {
width: "100%",
marginTop: "0",
marginBottom: "2rem",
},
},
[`& .avatar`]: {
Expand Down
6 changes: 5 additions & 1 deletion src/components/PurgeHistoryButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ import {
FormControlLabel,
TextField,
} from "@mui/material";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useCallback, useEffect, useRef, useState } from "react";
import { Button, useDataProvider, useNotify, useRecordContext, useTranslate } from "react-admin";

import { SynapseDataProvider } from "../providers/types";

export const PurgeHistoryButton = () => {
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"));
const record = useRecordContext();
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -105,7 +109,7 @@ export const PurgeHistoryButton = () => {
<Button label="resources.rooms.action.purge_history.label" onClick={() => setOpen(true)}>
<HistoryIcon />
</Button>
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth>
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth fullScreen={fullScreen}>
<DialogTitle>{translate("resources.rooms.action.purge_history.title", { roomName })}</DialogTitle>
<DialogContent>
<DialogContentText sx={{ mb: 2 }}>
Expand Down
10 changes: 8 additions & 2 deletions src/components/QuarantineAllMediaButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
DialogContentText,
DialogTitle,
} from "@mui/material";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useState } from "react";
import { Button, useDataProvider, useNotify, useRecordContext, useTranslate } from "react-admin";

Expand All @@ -19,6 +21,8 @@ import { SynapseDataProvider } from "../providers/types";
* Shows a confirmation dialog before proceeding.
*/
export const QuarantineRoomMediaButton = () => {
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"));
const record = useRecordContext();
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -60,7 +64,7 @@ export const QuarantineRoomMediaButton = () => {
<Button label="resources.rooms.action.quarantine_all.label" onClick={() => setOpen(true)}>
<BlockIcon />
</Button>
<Dialog open={open} onClose={() => setOpen(false)} maxWidth="sm" fullWidth>
<Dialog open={open} onClose={() => setOpen(false)} maxWidth="sm" fullWidth fullScreen={fullScreen}>
<DialogTitle>{translate("resources.rooms.action.quarantine_all.title", { roomName })}</DialogTitle>
<DialogContent>
<DialogContentText>{translate("resources.rooms.action.quarantine_all.content")}</DialogContentText>
Expand Down Expand Up @@ -88,6 +92,8 @@ export const QuarantineRoomMediaButton = () => {
* Shows a confirmation dialog before proceeding.
*/
export const QuarantineUserMediaButton = () => {
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"));
const record = useRecordContext();
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -129,7 +135,7 @@ export const QuarantineUserMediaButton = () => {
<Button label="resources.users.action.quarantine_all.label" onClick={() => setOpen(true)}>
<BlockIcon />
</Button>
<Dialog open={open} onClose={() => setOpen(false)} maxWidth="sm" fullWidth>
<Dialog open={open} onClose={() => setOpen(false)} maxWidth="sm" fullWidth fullScreen={fullScreen}>
<DialogTitle>{translate("resources.users.action.quarantine_all.title", { userName })}</DialogTitle>
<DialogContent>
<DialogContentText>{translate("resources.users.action.quarantine_all.content")}</DialogContentText>
Expand Down
Loading
Loading