diff --git a/components.json b/components.json index 218b7d3af0..c4f4502719 100644 --- a/components.json +++ b/components.json @@ -5,5 +5,7 @@ "src/components/views/rooms/Autocomplete.tsx": "src/components/views/rooms/Autocomplete.tsx", "src/components/views/rooms/RoomTile.tsx": "src/components/views/rooms/RoomTile.tsx", "src/components/views/elements/RoomName.tsx": "src/components/views/elements/RoomName.tsx", - "src/editor/commands.tsx": "src/editor/commands.tsx" + "src/components/views/dialogs/spotlight/PublicRoomResultDetails.tsx": "src/components/views/dialogs/spotlight/PublicRoomResultDetails.tsx", + "src/editor/commands.tsx": "src/editor/commands.tsx", + "src/hooks/useRoomName.ts": "src/hooks/useRoomName.ts" } diff --git a/res/css/superhero/custom.css b/res/css/superhero/custom.css index 12a8221bcc..4276a1fb54 100644 --- a/res/css/superhero/custom.css +++ b/res/css/superhero/custom.css @@ -1,9 +1,10 @@ +.sh_RoomTokenGatedRoom { + align-items: center; + display: flex; +} + .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/src/components/views/dialogs/spotlight/PublicRoomResultDetails.tsx b/src/components/views/dialogs/spotlight/PublicRoomResultDetails.tsx new file mode 100644 index 0000000000..5ff12ffa72 --- /dev/null +++ b/src/components/views/dialogs/spotlight/PublicRoomResultDetails.tsx @@ -0,0 +1,71 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { IPublicRoomsChunkRoom } from "matrix-js-sdk/src/matrix"; +import { linkifyAndSanitizeHtml } from "matrix-react-sdk/src/HtmlUtils"; +import { _t } from "matrix-react-sdk/src/languageHandler"; +import React from "react"; + +import RoomName from "../../elements/RoomName"; + +const MAX_NAME_LENGTH = 80; +const MAX_TOPIC_LENGTH = 800; + +interface Props { + room: IPublicRoomsChunkRoom; + labelId: string; + descriptionId: string; + detailsId: string; +} + +export function PublicRoomResultDetails({ room, labelId, descriptionId, detailsId }: Props): JSX.Element { + let topic = room.topic || ""; + // Additional truncation based on line numbers is done via CSS, + // but to ensure that the DOM is not polluted with a huge string + // we give it a hard limit before rendering. + if (topic.length > MAX_TOPIC_LENGTH) { + topic = `${topic.substring(0, MAX_TOPIC_LENGTH)}...`; + } + + return ( +
+
+ + + + + {room.canonical_alias ?? room.room_id} + +
+
+ + {_t("spotlight_dialog|count_of_members", { + count: room.num_joined_members, + })} + + {topic && ( + <> +  ยท  + + + )} +
+
+ ); +} diff --git a/src/components/views/elements/RoomName.tsx b/src/components/views/elements/RoomName.tsx index 5d67b244e4..5a7b4cd837 100644 --- a/src/components/views/elements/RoomName.tsx +++ b/src/components/views/elements/RoomName.tsx @@ -14,31 +14,44 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { useEffect, useState } from "react"; -import { Room, RoomEvent } from "matrix-js-sdk/src/matrix"; -import { useTypedEventEmitter } from "matrix-react-sdk/src/hooks/useEventEmitter"; +import { IPublicRoomsChunkRoom, Room } from "matrix-js-sdk/src/matrix"; +import React, { useCallback, useMemo } from "react"; -import { getRoomName } from "../../../hooks/useTokengatedRoom"; +import { Icon as TokenGatedRoomIcon } from "../../../../res/themes/superhero/img/icons/tokengated-room.svg"; +import { isTokenGatedRoom, useRoomName } from "../../../hooks/useRoomName"; interface IProps { - room?: Room; - children?(name: string): JSX.Element; + room?: Room | IPublicRoomsChunkRoom; + children?(name: JSX.Element): JSX.Element; + maxLength?: number; } -/** - * @deprecated use `useRoomName.ts` instead - */ -const RoomName = ({ room, children }: IProps): JSX.Element => { - const [name, setName] = useState(getRoomName(room)); - useTypedEventEmitter(room, RoomEvent.Name, () => { - setName(getRoomName(room)); - }); - useEffect(() => { - setName(getRoomName(room)); +export const RoomName = ({ room, children, maxLength }: IProps): JSX.Element => { + const roomName = useRoomName(room); + + const isVerifiedRoom = useMemo(() => { + return isTokenGatedRoom(room); }, [room]); - if (children) return children(name ?? ""); - return <>{name || ""}; + const truncatedRoomName = useMemo(() => { + if (maxLength && roomName.length > maxLength) { + return `${roomName.substring(0, maxLength)}...`; + } + return roomName; + }, [roomName, maxLength]); + + const renderRoomName = useCallback( + () => ( + + {isVerifiedRoom && } + {truncatedRoomName} + + ), + [truncatedRoomName, isVerifiedRoom], + ); + + if (children) return children(renderRoomName()); + return renderRoomName(); }; export default RoomName; diff --git a/src/components/views/rooms/CustomRoomName.tsx b/src/components/views/rooms/CustomRoomName.tsx deleted file mode 100644 index a1ae324cb2..0000000000 --- a/src/components/views/rooms/CustomRoomName.tsx +++ /dev/null @@ -1,18 +0,0 @@ -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 12e966c2be..de9fcbbd2c 100644 --- a/src/components/views/rooms/RoomTile.tsx +++ b/src/components/views/rooms/RoomTile.tsx @@ -17,7 +17,7 @@ limitations under the License. import classNames from "classnames"; import { Room, RoomEvent } from "matrix-js-sdk/src/matrix"; -import React, { createRef } from "react"; +import React, { ReactElement, createRef } from "react"; import { getKeyBindingsManager } from "matrix-react-sdk/src/KeyBindingsManager"; import { MatrixClientPeg } from "matrix-react-sdk/src/MatrixClientPeg"; import PosthogTrackers from "matrix-react-sdk/src/PosthogTrackers"; @@ -43,7 +43,6 @@ import defaultDispatcher from "matrix-react-sdk/src/dispatcher/dispatcher"; import { ActionPayload } from "matrix-react-sdk/src/dispatcher/payloads"; import { ViewRoomPayload } from "matrix-react-sdk/src/dispatcher/payloads/ViewRoomPayload"; import { _t } from "matrix-react-sdk/src/languageHandler"; -import type { Call } from "matrix-react-sdk/src/models/Call"; import SettingsStore from "matrix-react-sdk/src/settings/SettingsStore"; import { UIComponent } from "matrix-react-sdk/src/settings/UIFeature"; import { CallStore, CallStoreEvent } from "matrix-react-sdk/src/stores/CallStore"; @@ -59,8 +58,10 @@ 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"; + +import type { Call } from "matrix-react-sdk/src/models/Call"; +import { RoomName } from "../elements/RoomName"; +import { getRoomName } from "../../../hooks/useRoomName"; interface Props { room: Room; @@ -358,16 +359,16 @@ export class RoomTile extends React.PureComponent { {...contextMenuBelow(this.state.generalMenuPosition)} onFinished={this.onCloseGeneralMenu} room={this.props.room} - onPostFavoriteClick={(ev: ButtonEvent) => + onPostFavoriteClick={(ev: ButtonEvent): void => PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuFavouriteToggle", ev) } - onPostInviteClick={(ev: ButtonEvent) => + onPostInviteClick={(ev: ButtonEvent): void => PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuInviteItem", ev) } - onPostSettingsClick={(ev: ButtonEvent) => + onPostSettingsClick={(ev: ButtonEvent): void => PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuSettingsItem", ev) } - onPostLeaveClick={(ev: ButtonEvent) => + onPostLeaveClick={(ev: ButtonEvent): void => PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuLeaveItem", ev) } /> @@ -435,7 +436,7 @@ export class RoomTile extends React.PureComponent { const titleContainer = this.props.isMinimized ? null : (
- +
{subtitle}
@@ -478,7 +479,7 @@ export class RoomTile extends React.PureComponent { return ( - {({ onFocus, isActive, ref }) => ( + {({ onFocus, isActive, ref }): ReactElement => (