Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Next Next commit
Users badges
  • Loading branch information
aine-etke committed Nov 21, 2024
commit 9e3021ba5db237b5d14cf6841c09e54ccf2b2f9e
36 changes: 36 additions & 0 deletions docs/user-badges.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# User Badges

To help with identifying users with certain roles or permissions, we have implemented a badge system.
These badges are displayed on the user's avatar and have a handy tooltip that explains what the badge means.

## Available Badges

### 🧙‍ You

This badge is displayed on your user's avatar.
Tooltip for this badge will contain additional information, e.g.: `You (Admin)`.

### 👑 Admin

This badge is displayed on homeserver admins' avatars.
Tooltip for this badge is `Admin`.

### 🛡️ Appservice/System-managed

This badge is displayed on users that are managed by an appservices (or system), [more details](./system-users.md).
Tooltip for this badge will contain additional information, e.g.: `System-managed (Bot)`.

### 🤖 Bot

This badge is displayed on bots' avatars (users with the `user_type` set to `bot`).
Tooltip for this badge is `Bot`.

### 📞 Support

This badge is displayed on users that are part of the support team (users with the `user_type` set to `support`).
Tooltip for this badge is `Support`.

### 👤 Regular User

This badge is displayed on regular users' avatars.
Tooltip for this badge is `Regular User`.
59 changes: 57 additions & 2 deletions src/components/AvatarField.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { get } from "lodash";
import { Avatar, AvatarProps } from "@mui/material";
import { FieldProps, useRecordContext } from "react-admin";
import { Avatar, AvatarProps, Badge, Tooltip } from "@mui/material";
import { FieldProps, useRecordContext, useTranslate } from "react-admin";
import { useState, useEffect, useCallback } from "react";
import { fetchAuthenticatedMedia } from "../utils/fetchMedia";
import { isMXID, isASManaged } from "./mxid";
import storage from "../storage";

const AvatarField = ({ source, ...rest }: AvatarProps & FieldProps) => {
const { alt, classes, sizes, sx, variant } = rest;
Expand Down Expand Up @@ -45,6 +47,59 @@ const AvatarField = ({ source, ...rest }: AvatarProps & FieldProps) => {
letter = record.displayname[0].toUpperCase();
}

// hacky way to determine the user type
let badge = "";
let tooltip = "";
if (isMXID(record?.id)) {
const translate = useTranslate();
switch (record?.user_type) {
case "bot":
badge = "🤖";
tooltip = translate("resources.users.badge.bot");
break;
case "support":
badge = "📞";
tooltip = translate("resources.users.badge.support");
break;
default:
badge = "👤";
tooltip = translate("resources.users.badge.regular");
break;
}
if (record?.admin) {
badge = "👑";
tooltip = translate("resources.users.badge.admin");
}
if (isASManaged(record?.name)) {
badge = "🛡️";
tooltip = `${translate("resources.users.badge.system_managed")} (${tooltip})`;
}
if (storage.getItem("user_id") === record?.id) {
badge = "🧙‍";
tooltip = `${translate("resources.users.badge.you")} (${tooltip})`;
}
}

// if there is a badge, wrap the Avatar in a Badge and a Tooltip
if (badge) {
return (
<Tooltip title={tooltip}>
<Badge
badgeContent={badge}
overlap="circular"
sx={{ "& .MuiBadge-badge": { width: "10px" } }} // we deliberately set a very small width here, to make the badge actually circular
anchorOrigin={{
vertical: "bottom",
horizontal: "right",
}}
>
<Avatar alt={alt} classes={classes} sizes={sizes} src={src} sx={sx} variant={variant}>
{letter}
</Avatar>
</Badge>
</Tooltip>);
}

return (<Avatar alt={alt} classes={classes} sizes={sizes} src={src} sx={sx} variant={variant}>
{letter}
</Avatar>);
Expand Down
9 changes: 9 additions & 0 deletions src/components/mxid.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import { Identifier } from "ra-core";
import { GetConfig } from "./config";

const mxidPattern = /^@[^@:]+:[^@:]+$/;

/*
* Check if id is a valid Matrix ID (user)
* @param id The ID to check
* @returns Whether the ID is a valid Matrix ID
*/
export const isMXID = (id: string | Identifier): boolean => mxidPattern.test(id as string);

/**
* Check if a user is managed by an application service
* @param id The user ID to check
Expand Down
8 changes: 8 additions & 0 deletions src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@ const de: SynapseTranslationMessages = {
modify_managed_user_error: "Das Ändern eines vom System verwalteten Benutzers ist nicht zulässig.",
username_available: "Benutzername verfügbar",
},
badge: {
you: "Sie",
bot: "Bot",
admin: "Administrator",
support: "Unterstützung",
regular: "Normaler Benutzer",
system_managed: "Systemverwalteter Benutzer",
},
action: {
erase: "Lösche Benutzerdaten",
erase_avatar: "Avatar löschen",
Expand Down
8 changes: 8 additions & 0 deletions src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ const en: SynapseTranslationMessages = {
overwrite_cancel: "Cancel",
overwrite_confirm: "Overwrite",
},
badge: {
you: "You",
bot: "Bot",
admin: "Admin",
support: "Support",
regular: "Regular User",
system_managed: "System-managed",
},
limits: {
messages_per_second: "Messages per second",
messages_per_second_text: "The number of actions that can be performed in a second.",
Expand Down
8 changes: 8 additions & 0 deletions src/i18n/fa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,14 @@ const fa: SynapseTranslationMessages = {
modify_managed_user_error: "لا يُسمح بتغيير المستخدم الذي يديره النظام.",
username_available: "نام کاربری موجود",
},
badge: {
you: "شما",
bot: "ربات",
admin: "مدیر",
support: "پشتیبان",
regular: "کاربر عادی",
system_managed: "مدیریت سیستم",
},
action: {
erase: "پاک کردن اطلاعات کاربر",
erase_avatar: "محو الصورة الرمزية",
Expand Down
8 changes: 8 additions & 0 deletions src/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,14 @@ const fr: SynapseTranslationMessages = {
modify_managed_user_error: "La modification d'un utilisateur géré par le système n'est pas autorisée.",
username_available: "Nom d'utilisateur disponible",
},
badge: {
you: "Vous",
bot: "Bot",
admin: "Admin",
support: "Support",
regular: "Utilisateur régulier",
system_managed: "Géré par le système",
},
action: {
erase: "Effacer les données de l'utilisateur",
erase_avatar: "Effacer l'avatar",
Expand Down
8 changes: 8 additions & 0 deletions src/i18n/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ interface SynapseTranslationMessages extends TranslationMessages {
overwrite_cancel: string;
overwrite_confirm: string;
};
badge: {
you: string;
bot: string;
admin: string;
support: string;
regular: string;
system_managed: string;
}
limits: {
messages_per_second: string;
messages_per_second_text: string;
Expand Down
8 changes: 8 additions & 0 deletions src/i18n/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@ const it: SynapseTranslationMessages = {
modify_managed_user_error: "La modifica di un utente gestito dal sistema non è consentita.",
username_available: "Nome utente disponibile",
},
badge: {
you: "Tu",
bot: "Bot",
admin: "Amministratore",
support: "Supporto",
regular: "Utente normale",
system_managed: "Gestito dal sistema",
},
action: {
erase: "Cancella i dati dell'utente",
erase_avatar: "Cancella l'avatar dell'utente",
Expand Down
Loading