User status in room summary card (#34239)
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
|||||||
RoomEvent,
|
RoomEvent,
|
||||||
RoomStateEvent,
|
RoomStateEvent,
|
||||||
} from "matrix-js-sdk/src/matrix";
|
} from "matrix-js-sdk/src/matrix";
|
||||||
|
import { type UserStatus } from "@element-hq/web-shared-components";
|
||||||
|
|
||||||
import { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
|
import { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
|
||||||
import { useIsEncrypted } from "../../../hooks/useIsEncrypted";
|
import { useIsEncrypted } from "../../../hooks/useIsEncrypted";
|
||||||
@@ -41,9 +42,16 @@ import { usePinnedEvents } from "../../../hooks/usePinnedEvents";
|
|||||||
import { tagRoom } from "../../../utils/room/tagRoom";
|
import { tagRoom } from "../../../utils/room/tagRoom";
|
||||||
import { inviteToRoom } from "../../../utils/room/inviteToRoom";
|
import { inviteToRoom } from "../../../utils/room/inviteToRoom";
|
||||||
import { getTagsForRoom } from "../../../utils/room/getTagsForRoom";
|
import { getTagsForRoom } from "../../../utils/room/getTagsForRoom";
|
||||||
|
import { useDmMember } from "../../views/avatars/WithPresenceIndicator";
|
||||||
|
import { useUserStatus } from "../../../hooks/useUserStatus";
|
||||||
|
|
||||||
export interface RoomSummaryCardState {
|
export interface RoomSummaryCardState {
|
||||||
isDirectMessage: boolean;
|
isDirectMessage: boolean;
|
||||||
|
/**
|
||||||
|
* The MSC4426 status of the other user if this room is a DM.
|
||||||
|
* Should be undefined for non-DM rooms.
|
||||||
|
*/
|
||||||
|
userStatus: UserStatus | undefined;
|
||||||
/**
|
/**
|
||||||
* Whether the room is encrypted, used to display the correct badge and icon
|
* Whether the room is encrypted, used to display the correct badge and icon
|
||||||
*/
|
*/
|
||||||
@@ -182,6 +190,8 @@ export function useRoomSummaryCardViewModel(
|
|||||||
const isFavorite = roomTags.includes(DefaultTagID.Favourite);
|
const isFavorite = roomTags.includes(DefaultTagID.Favourite);
|
||||||
|
|
||||||
const isDirectMessage = useIsDirectMessage(room);
|
const isDirectMessage = useIsDirectMessage(room);
|
||||||
|
const dmMember = useDmMember(room);
|
||||||
|
const userStatus = useUserStatus(dmMember?.userId);
|
||||||
|
|
||||||
const onRoomMembersClick = (): void => {
|
const onRoomMembersClick = (): void => {
|
||||||
RightPanelStore.instance.pushCard({ phase: RightPanelPhases.MemberList }, true);
|
RightPanelStore.instance.pushCard({ phase: RightPanelPhases.MemberList }, true);
|
||||||
@@ -261,6 +271,7 @@ export function useRoomSummaryCardViewModel(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
isDirectMessage,
|
isDirectMessage,
|
||||||
|
userStatus,
|
||||||
isRoomEncrypted,
|
isRoomEncrypted,
|
||||||
roomJoinRule,
|
roomJoinRule,
|
||||||
e2eStatus,
|
e2eStatus,
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error"
|
|||||||
import ErrorSolidIcon from "@vector-im/compound-design-tokens/assets/web/icons/error-solid";
|
import ErrorSolidIcon from "@vector-im/compound-design-tokens/assets/web/icons/error-solid";
|
||||||
import ChevronDownIcon from "@vector-im/compound-design-tokens/assets/web/icons/chevron-down";
|
import ChevronDownIcon from "@vector-im/compound-design-tokens/assets/web/icons/chevron-down";
|
||||||
import { JoinRule, type Room } from "matrix-js-sdk/src/matrix";
|
import { JoinRule, type Room } from "matrix-js-sdk/src/matrix";
|
||||||
import { Box, Flex, HistoryVisibilityBadge, LinkedText } from "@element-hq/web-shared-components";
|
import { Box, Flex, HistoryVisibilityBadge, LinkedText, StatusTextView } from "@element-hq/web-shared-components";
|
||||||
|
|
||||||
import BaseCard from "./BaseCard.tsx";
|
import BaseCard from "./BaseCard.tsx";
|
||||||
import { _t } from "../../../languageHandler.tsx";
|
import { _t } from "../../../languageHandler.tsx";
|
||||||
@@ -153,6 +153,7 @@ const RoomSummaryCardView: React.FC<IProps> = ({
|
|||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
</Heading>
|
</Heading>
|
||||||
|
{vm.userStatus && <StatusTextView status={vm.userStatus} />}
|
||||||
<Text
|
<Text
|
||||||
as="div"
|
as="div"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ describe("<RoomSummaryCard />", () => {
|
|||||||
// Setup mock view models
|
// Setup mock view models
|
||||||
const vmDefaultValues: RoomSummaryCardState = {
|
const vmDefaultValues: RoomSummaryCardState = {
|
||||||
isDirectMessage: false,
|
isDirectMessage: false,
|
||||||
|
userStatus: undefined,
|
||||||
isRoomEncrypted: false,
|
isRoomEncrypted: false,
|
||||||
e2eStatus: undefined,
|
e2eStatus: undefined,
|
||||||
isVideoRoom: false,
|
isVideoRoom: false,
|
||||||
@@ -325,4 +326,31 @@ describe("<RoomSummaryCard />", () => {
|
|||||||
expect(screen.queryByText("Public room")).toBeInTheDocument();
|
expect(screen.queryByText("Public room")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("user status", () => {
|
||||||
|
it("shows the other user's status when set", () => {
|
||||||
|
mocked(useRoomSummaryCardViewModel).mockReturnValue({
|
||||||
|
...vmDefaultValues,
|
||||||
|
isDirectMessage: true,
|
||||||
|
userStatus: { emoji: "💬", text: "In a meeting" },
|
||||||
|
});
|
||||||
|
|
||||||
|
getComponent();
|
||||||
|
|
||||||
|
expect(screen.getByText("In a meeting")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("💬")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not show a status when there is none", () => {
|
||||||
|
mocked(useRoomSummaryCardViewModel).mockReturnValue({
|
||||||
|
...vmDefaultValues,
|
||||||
|
isDirectMessage: true,
|
||||||
|
userStatus: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
getComponent();
|
||||||
|
|
||||||
|
expect(screen.queryByText("In a meeting")).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--cpd-space-1x);
|
gap: var(--cpd-space-1x);
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font: var(--cpd-font-body-md-medium);
|
font: var(--cpd-font-body-md-medium);
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
.menuStatusText {
|
.menuStatusText {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user