Room header UI updates (#11507)
* Fix performance issues with useRoomMembers With the current implementation it would create a new function, with leading: true, rendering the whole throttling useless * Add public room indicator * Format room members count better * Add public room test * Add search to room summary card * Update settings UI * Update snapshot * Remove default title attribute
This commit is contained in:
parent
30d997e21c
commit
d551469543
32 changed files with 176 additions and 112 deletions
|
@ -57,6 +57,7 @@ interface RoomlessProps extends BaseProps {
|
|||
interface RoomProps extends BaseProps {
|
||||
room: Room;
|
||||
permalinkCreator: RoomPermalinkCreator;
|
||||
onSearchClick?: () => void;
|
||||
}
|
||||
|
||||
type Props = XOR<RoomlessProps, RoomProps>;
|
||||
|
@ -293,6 +294,7 @@ export default class RightPanel extends React.Component<Props, IState> {
|
|||
onClose={this.onClose}
|
||||
// whenever RightPanel is passed a room it is passed a permalinkcreator
|
||||
permalinkCreator={this.props.permalinkCreator!}
|
||||
onSearchClick={this.props.onSearchClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2443,6 +2443,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
resizeNotifier={this.props.resizeNotifier}
|
||||
permalinkCreator={this.permalinkCreator}
|
||||
e2eStatus={this.state.e2eStatus}
|
||||
onSearchClick={this.onSearchClick}
|
||||
/>
|
||||
) : undefined;
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ const BaseAvatar: React.FC<IProps> = (props) => {
|
|||
const {
|
||||
name,
|
||||
idName,
|
||||
title = "",
|
||||
title,
|
||||
url,
|
||||
urls,
|
||||
size = "40px",
|
||||
|
|
|
@ -58,6 +58,7 @@ interface IProps {
|
|||
room: Room;
|
||||
permalinkCreator: RoomPermalinkCreator;
|
||||
onClose(): void;
|
||||
onSearchClick?: () => void;
|
||||
}
|
||||
|
||||
interface IAppsSectionProps {
|
||||
|
@ -272,7 +273,7 @@ const onRoomSettingsClick = (ev: ButtonEvent): void => {
|
|||
PosthogTrackers.trackInteraction("WebRightPanelRoomInfoSettingsButton", ev);
|
||||
};
|
||||
|
||||
const RoomSummaryCard: React.FC<IProps> = ({ room, permalinkCreator, onClose }) => {
|
||||
const RoomSummaryCard: React.FC<IProps> = ({ room, permalinkCreator, onClose, onSearchClick }) => {
|
||||
const cli = useContext(MatrixClientContext);
|
||||
|
||||
const onShareRoomClick = (): void => {
|
||||
|
@ -342,6 +343,14 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, permalinkCreator, onClose })
|
|||
{_t("common|people")}
|
||||
<span className="mx_BaseCard_Button_sublabel">{memberCount}</span>
|
||||
</Button>
|
||||
<Button
|
||||
className="mx_RoomSummaryCard_icon_search"
|
||||
onClick={() => {
|
||||
onSearchClick?.();
|
||||
}}
|
||||
>
|
||||
{_t("Search")}
|
||||
</Button>
|
||||
{!isVideoRoom && (
|
||||
<Button className="mx_RoomSummaryCard_icon_files" onClick={onRoomFilesClick}>
|
||||
{_t("Files")}
|
||||
|
|
|
@ -22,18 +22,18 @@ import { Icon as ThreadsIcon } from "@vector-im/compound-design-tokens/icons/thr
|
|||
import { Icon as NotificationsIcon } from "@vector-im/compound-design-tokens/icons/notifications-solid.svg";
|
||||
import { Icon as VerifiedIcon } from "@vector-im/compound-design-tokens/icons/verified.svg";
|
||||
import { Icon as ErrorIcon } from "@vector-im/compound-design-tokens/icons/error.svg";
|
||||
import { Icon as PublicIcon } from "@vector-im/compound-design-tokens/icons/public.svg";
|
||||
import { CallType } from "matrix-js-sdk/src/webrtc/call";
|
||||
import { EventType, type Room } from "matrix-js-sdk/src/matrix";
|
||||
import { EventType, JoinRule, type Room } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { useRoomName } from "../../../hooks/useRoomName";
|
||||
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
|
||||
import { RightPanelPhases } from "../../../stores/right-panel/RightPanelStorePhases";
|
||||
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
|
||||
import { useTopic } from "../../../hooks/room/useTopic";
|
||||
import { useAccountData } from "../../../hooks/useAccountData";
|
||||
import { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
|
||||
import { useRoomMemberCount, useRoomMembers } from "../../../hooks/useRoomMembers";
|
||||
import { _t, getCurrentLanguage } from "../../../languageHandler";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { Flex } from "../../utils/Flex";
|
||||
import { Box } from "../../utils/Box";
|
||||
import { useRoomCallStatus } from "../../../hooks/room/useRoomCallStatus";
|
||||
|
@ -46,6 +46,9 @@ import { placeCall } from "../../../utils/room/placeCall";
|
|||
import { useEncryptionStatus } from "../../../hooks/useEncryptionStatus";
|
||||
import { E2EStatus } from "../../../utils/ShieldUtils";
|
||||
import FacePile from "../elements/FacePile";
|
||||
import { useRoomState } from "../../../hooks/useRoomState";
|
||||
import RoomAvatar from "../avatars/RoomAvatar";
|
||||
import { formatCount } from "../../../utils/FormattingUtils";
|
||||
|
||||
/**
|
||||
* A helper to transform a notification color to the what the Compound Icon Button
|
||||
|
@ -76,9 +79,10 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
|
|||
|
||||
const roomName = useRoomName(room);
|
||||
const roomTopic = useTopic(room);
|
||||
const roomState = useRoomState(room);
|
||||
|
||||
const members = useRoomMembers(room);
|
||||
const memberCount = useRoomMemberCount(room);
|
||||
const members = useRoomMembers(room, 2500);
|
||||
const memberCount = useRoomMemberCount(room, { throttleWait: 2500 });
|
||||
|
||||
const { voiceCallDisabledReason, voiceCallType, videoCallDisabledReason, videoCallType } = useRoomCallStatus(room);
|
||||
|
||||
|
@ -116,7 +120,7 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
|
|||
showOrHidePanel(RightPanelPhases.RoomSummary);
|
||||
}}
|
||||
>
|
||||
<DecoratedRoomAvatar room={room} size="40px" displayBadge={false} />
|
||||
<RoomAvatar room={room} size="40px" />
|
||||
<Box flex="1" className="mx_RoomHeader_info">
|
||||
<BodyText
|
||||
as="div"
|
||||
|
@ -126,9 +130,21 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
|
|||
title={roomName}
|
||||
role="heading"
|
||||
aria-level={1}
|
||||
className="mx_RoomHeader_heading"
|
||||
>
|
||||
{roomName}
|
||||
|
||||
{!isDirectMessage && roomState.getJoinRule() === JoinRule.Public && (
|
||||
<Tooltip label={_t("Public room")}>
|
||||
<PublicIcon
|
||||
width="16px"
|
||||
height="16px"
|
||||
className="text-secondary"
|
||||
aria-label={_t("Public room")}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{isDirectMessage && e2eStatus === E2EStatus.Verified && (
|
||||
<Tooltip label={_t("common|verified")}>
|
||||
<VerifiedIcon
|
||||
|
@ -214,7 +230,7 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
|
|||
size="20px"
|
||||
overflow={false}
|
||||
>
|
||||
{memberCount.toLocaleString(getCurrentLanguage())}
|
||||
{formatCount(memberCount)}
|
||||
</FacePile>
|
||||
</BodyText>
|
||||
)}
|
||||
|
|
|
@ -23,17 +23,20 @@ import { useTypedEventEmitter } from "./useEventEmitter";
|
|||
// Hook to simplify watching Matrix Room joined members
|
||||
export const useRoomMembers = (room: Room, throttleWait = 250): RoomMember[] => {
|
||||
const [members, setMembers] = useState<RoomMember[]>(room.getJoinedMembers());
|
||||
useTypedEventEmitter(
|
||||
room.currentState,
|
||||
RoomStateEvent.Members,
|
||||
throttle(
|
||||
() => {
|
||||
setMembers(room.getJoinedMembers());
|
||||
},
|
||||
throttleWait,
|
||||
{ leading: true, trailing: true },
|
||||
),
|
||||
|
||||
const throttledUpdate = useMemo(
|
||||
() =>
|
||||
throttle(
|
||||
() => {
|
||||
setMembers(room.getJoinedMembers());
|
||||
},
|
||||
throttleWait,
|
||||
{ leading: true, trailing: true },
|
||||
),
|
||||
[room, throttleWait],
|
||||
);
|
||||
|
||||
useTypedEventEmitter(room.currentState, RoomStateEvent.Members, throttledUpdate);
|
||||
return members;
|
||||
};
|
||||
|
||||
|
@ -50,11 +53,11 @@ type RoomMemberCountOpts = {
|
|||
* @param opts The options.
|
||||
* @returns the room member count.
|
||||
*/
|
||||
export const useRoomMemberCount = (room: Room, opts: RoomMemberCountOpts = { throttleWait: 250 }): number => {
|
||||
export const useRoomMemberCount = (
|
||||
room: Room,
|
||||
{ throttleWait }: RoomMemberCountOpts = { throttleWait: 250 },
|
||||
): number => {
|
||||
const [count, setCount] = useState<number>(room.getJoinedMemberCount());
|
||||
|
||||
const { throttleWait } = opts;
|
||||
|
||||
const throttledUpdate = useMemo(
|
||||
() =>
|
||||
throttle(
|
||||
|
|
|
@ -897,7 +897,7 @@
|
|||
"hidebold": "Hide notification dot (only display counters badges)",
|
||||
"intentional_mentions": "Enable intentional mentions",
|
||||
"ask_to_join": "Enable ask to join",
|
||||
"new_room_decoration_ui": "Under active development, new room header & details interface"
|
||||
"new_room_decoration_ui": "New room header & details interface"
|
||||
},
|
||||
"Thank you for trying the beta, please go into as much detail as you can so we can improve it.": "Thank you for trying the beta, please go into as much detail as you can so we can improve it.",
|
||||
"Notification Settings": "Notification Settings",
|
||||
|
@ -1876,6 +1876,7 @@
|
|||
"Room %(name)s": "Room %(name)s",
|
||||
"Recently visited rooms": "Recently visited rooms",
|
||||
"No recently visited rooms": "No recently visited rooms",
|
||||
"Public room": "Public room",
|
||||
"Untrusted": "Untrusted",
|
||||
"%(count)s members": {
|
||||
"other": "%(count)s members",
|
||||
|
@ -1883,7 +1884,6 @@
|
|||
},
|
||||
"Video room": "Video room",
|
||||
"Public space": "Public space",
|
||||
"Public room": "Public room",
|
||||
"Private space": "Private space",
|
||||
"Private room": "Private room",
|
||||
"%(names)s and %(name)s": "%(names)s and %(name)s",
|
||||
|
@ -2112,6 +2112,7 @@
|
|||
"Edit widgets, bridges & bots": "Edit widgets, bridges & bots",
|
||||
"Add widgets, bridges & bots": "Add widgets, bridges & bots",
|
||||
"Not encrypted": "Not encrypted",
|
||||
"Search": "Search",
|
||||
"Files": "Files",
|
||||
"Poll history": "Poll history",
|
||||
"Pinned": "Pinned",
|
||||
|
|
|
@ -548,6 +548,7 @@ export const SETTINGS: { [setting: string]: ISetting } = {
|
|||
isFeature: true,
|
||||
labsGroup: LabGroup.Rooms,
|
||||
displayName: _td("labs|new_room_decoration_ui"),
|
||||
description: _td("labs|under_active_development"),
|
||||
supportedLevels: LEVELS_FEATURE,
|
||||
default: false,
|
||||
controller: new ReloadOnChangeController(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue