diff --git a/res/css/superhero/custom.css b/res/css/superhero/custom.css new file mode 100644 index 0000000000..12a8221bcc --- /dev/null +++ b/res/css/superhero/custom.css @@ -0,0 +1,9 @@ +.sh_RoomTokenGatedRoomIcon { + width: 16px; + height: 16px; + margin-right: 4px; +} +.mx_RoomTile .mx_RoomTile_titleContainer .mx_RoomTile_title { + align-items: center; + display: flex; +} diff --git a/res/themes/superhero/img/icons/tokengated-room.svg b/res/themes/superhero/img/icons/tokengated-room.svg new file mode 100644 index 0000000000..d69c4e31c3 --- /dev/null +++ b/res/themes/superhero/img/icons/tokengated-room.svg @@ -0,0 +1,6 @@ + + + + diff --git a/src/components/views/rooms/CustomRoomName.tsx b/src/components/views/rooms/CustomRoomName.tsx new file mode 100644 index 0000000000..a1ae324cb2 --- /dev/null +++ b/src/components/views/rooms/CustomRoomName.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import { Room } from "matrix-js-sdk/src/matrix"; + +import { Icon as TokenGatedRoomIcon } from "../../../../res/themes/superhero/img/icons/tokengated-room.svg"; +import { useTokenGatedRoom } from "../../../hooks/useTokengatedRoom"; + +export interface CustomRoomNameProps { + room: Room; +} +export const CustomRoomName: React.FC = ({ room }) => { + const { roomName, isVerifiedRoom } = useTokenGatedRoom(room); + return ( + <> + {isVerifiedRoom && } + {roomName} + + ); +}; diff --git a/src/components/views/rooms/RoomTile.tsx b/src/components/views/rooms/RoomTile.tsx index c77b85e695..12e966c2be 100644 --- a/src/components/views/rooms/RoomTile.tsx +++ b/src/components/views/rooms/RoomTile.tsx @@ -59,6 +59,8 @@ import { MessagePreview, MessagePreviewStore } from "matrix-react-sdk/src/stores import { DefaultTagID, TagID } from "matrix-react-sdk/src/stores/room-list/models"; import { isKnockDenied } from "matrix-react-sdk/src/utils/membership"; import { useHasRoomLiveVoiceBroadcast } from "matrix-react-sdk/src/voice-broadcast"; +import { CustomRoomName } from "./CustomRoomName"; +import { getRoomName } from "../../../hooks/useTokengatedRoom"; interface Props { room: Room; @@ -399,10 +401,7 @@ export class RoomTile extends React.PureComponent { mx_RoomTile_minimized: this.props.isMinimized, }); - let name = this.props.room.name; - if (typeof name !== "string") name = ""; - name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon - + const name = getRoomName(this.props.room); let badge: React.ReactNode; if (!this.props.isMinimized && this.notificationState) { // aria-hidden because we summarise the unread count/highlight status in a manual aria-label below @@ -436,7 +435,7 @@ export class RoomTile extends React.PureComponent { const titleContainer = this.props.isMinimized ? null : (
- {name} +
{subtitle}
diff --git a/src/hooks/useTokenGatedRoom.tsx b/src/hooks/useTokenGatedRoom.tsx new file mode 100644 index 0000000000..452ff48370 --- /dev/null +++ b/src/hooks/useTokenGatedRoom.tsx @@ -0,0 +1,27 @@ +import { Room } from "matrix-js-sdk/src/matrix"; +import { useMemo } from "react"; + +export function getRoomName(room: Room): string { + return (room?.name || "") + .replace(":", ":\u200b") // add a zero-width space to allow linewrapping after the colon (matrix defaults) + .replace("[TG]", ""); +} + +export function isTokenGatedRoom(room: Room): boolean { + return room?.name?.includes("[TG]"); +} + +export function useTokenGatedRoom(room: Room): any { + const roomName = useMemo(() => { + return getRoomName(room); + }, [room]); + + const isVerifiedRoom = useMemo(() => { + return isTokenGatedRoom(room); + }, [room]); + + return { + roomName, + isVerifiedRoom, + }; +} diff --git a/src/vector/index.ts b/src/vector/index.ts index 10f7a627b6..a9f653b5de 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -33,6 +33,7 @@ import "setimmediate"; // in webpack.config.js require("gfm.css/gfm.css"); require("katex/dist/katex.css"); +require("../../res/css/superhero/custom.css"); /** * This require is necessary only for purposes of CSS hot-reload, as otherwise