Move code into directory
This commit is contained in:
@@ -33,7 +33,7 @@ import { IRightPanelCard, IRightPanelCardState } from "../../stores/right-panel/
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import { XOR } from "../../@types/common";
|
||||
import ExtensionsCard from "../views/right_panel/ExtensionsCard";
|
||||
import MemberListView from "../views/rooms/MemberListView";
|
||||
import MemberListView from "../views/rooms/MemberList/MemberListView";
|
||||
|
||||
interface BaseProps {
|
||||
overwriteCard?: IRightPanelCard; // used to display a custom card and ignoring the RightPanelStore (used for UserView)
|
||||
|
||||
@@ -22,22 +22,22 @@ import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { throttle } from "lodash";
|
||||
|
||||
import { RoomMember } from "../../models/rooms/RoomMember";
|
||||
import { mediaFromMxc } from "../../customisations/Media";
|
||||
import UserIdentifierCustomisations from "../../customisations/UserIdentifier";
|
||||
import { shouldShowComponent } from "../../customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../settings/UIFeature";
|
||||
import { PresenceState } from "../../models/rooms/PresenceState";
|
||||
import { useMatrixClientContext } from "../../contexts/MatrixClientContext";
|
||||
import { SDKContext } from "../../contexts/SDKContext";
|
||||
import PosthogTrackers from "../../PosthogTrackers";
|
||||
import { ButtonEvent } from "../views/elements/AccessibleButton";
|
||||
import { inviteToRoom } from "../../utils/room/inviteToRoom";
|
||||
import { canInviteTo } from "../../utils/room/canInviteTo";
|
||||
import { isValid3pidInvite } from "../../RoomInvite";
|
||||
import { ThreePIDInvite } from "../../models/rooms/ThreePIDInvite";
|
||||
import { XOR } from "../../@types/common";
|
||||
import { useTypedEventEmitter } from "../../hooks/useEventEmitter";
|
||||
import { RoomMember } from "../../../models/rooms/RoomMember";
|
||||
import { mediaFromMxc } from "../../../customisations/Media";
|
||||
import UserIdentifierCustomisations from "../../../customisations/UserIdentifier";
|
||||
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../../settings/UIFeature";
|
||||
import { PresenceState } from "../../../models/rooms/PresenceState";
|
||||
import { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
|
||||
import { SDKContext } from "../../../contexts/SDKContext";
|
||||
import PosthogTrackers from "../../../PosthogTrackers";
|
||||
import { ButtonEvent } from "../../views/elements/AccessibleButton";
|
||||
import { inviteToRoom } from "../../../utils/room/inviteToRoom";
|
||||
import { canInviteTo } from "../../../utils/room/canInviteTo";
|
||||
import { isValid3pidInvite } from "../../../RoomInvite";
|
||||
import { ThreePIDInvite } from "../../../models/rooms/ThreePIDInvite";
|
||||
import { XOR } from "../../../@types/common";
|
||||
import { useTypedEventEmitter } from "../../../hooks/useEventEmitter";
|
||||
|
||||
type Member = XOR<{ member: RoomMember }, { threePidInvite: ThreePIDInvite }>;
|
||||
|
||||
@@ -9,26 +9,21 @@ import { useEffect, useMemo, useState } from "react";
|
||||
import { RoomStateEvent, MatrixEvent, EventType } from "matrix-js-sdk/src/matrix";
|
||||
import { UserVerificationStatus, CryptoEvent } from "matrix-js-sdk/src/crypto-api";
|
||||
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import { asyncSome } from "../../utils/arrays";
|
||||
import { getUserDeviceIds } from "../../utils/crypto/deviceInfo";
|
||||
import { RoomMember } from "../../models/rooms/RoomMember";
|
||||
import { E2EState } from "../views/rooms/E2EIcon";
|
||||
import { _t, _td, TranslationKey } from "../../languageHandler";
|
||||
import UserIdentifierCustomisations from "../../customisations/UserIdentifier";
|
||||
import { ThreePIDInvite } from "../../models/rooms/ThreePIDInvite";
|
||||
import dis from "../../../../dispatcher/dispatcher";
|
||||
import { MatrixClientPeg } from "../../../../MatrixClientPeg";
|
||||
import { Action } from "../../../../dispatcher/actions";
|
||||
import { asyncSome } from "../../../../utils/arrays";
|
||||
import { getUserDeviceIds } from "../../../../utils/crypto/deviceInfo";
|
||||
import { RoomMember } from "../../../../models/rooms/RoomMember";
|
||||
import { E2EState } from "../../../views/rooms/E2EIcon";
|
||||
import { _t, _td, TranslationKey } from "../../../../languageHandler";
|
||||
import UserIdentifierCustomisations from "../../../../customisations/UserIdentifier";
|
||||
|
||||
interface MemberTileViewModelProps {
|
||||
member: RoomMember;
|
||||
showPresence?: boolean;
|
||||
}
|
||||
|
||||
interface ThreePidTileViewModelProps {
|
||||
threePidInvite: ThreePIDInvite;
|
||||
}
|
||||
|
||||
export interface MemberTileViewState extends MemberTileViewModelProps {
|
||||
e2eStatus?: E2EState;
|
||||
name: string;
|
||||
@@ -47,27 +42,6 @@ const PowerLabel: Record<PowerStatus, TranslationKey> = {
|
||||
[PowerStatus.Moderator]: _td("power_level|moderator"),
|
||||
};
|
||||
|
||||
export interface ThreePidTileViewState {
|
||||
name: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export function useThreePidTileViewModel(props: ThreePidTileViewModelProps): ThreePidTileViewState {
|
||||
const invite = props.threePidInvite;
|
||||
const name = invite.event.getContent().display_name;
|
||||
const onClick = (): void => {
|
||||
dis.dispatch({
|
||||
action: Action.View3pidInvite,
|
||||
event: invite.event,
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
name,
|
||||
onClick,
|
||||
};
|
||||
}
|
||||
|
||||
export function useMemberTileViewModel(props: MemberTileViewModelProps): MemberTileViewState {
|
||||
const [e2eStatus, setE2eStatus] = useState<E2EState | undefined>();
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import dis from "../../../../dispatcher/dispatcher";
|
||||
import { Action } from "../../../../dispatcher/actions";
|
||||
import { ThreePIDInvite } from "../../../../models/rooms/ThreePIDInvite";
|
||||
|
||||
interface ThreePidTileViewModelProps {
|
||||
threePidInvite: ThreePIDInvite;
|
||||
}
|
||||
|
||||
export interface ThreePidTileViewState {
|
||||
name: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export function useThreePidTileViewModel(props: ThreePidTileViewModelProps): ThreePidTileViewState {
|
||||
const invite = props.threePidInvite;
|
||||
const name = invite.event.getContent().display_name;
|
||||
const onClick = (): void => {
|
||||
dis.dispatch({
|
||||
action: Action.View3pidInvite,
|
||||
event: invite.event,
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
name,
|
||||
onClick,
|
||||
};
|
||||
}
|
||||
@@ -10,9 +10,9 @@ import React from "react";
|
||||
import InviteIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-add-solid";
|
||||
import { UserAddIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { Flex } from "../../utils/Flex";
|
||||
import { MemberListViewState } from "../../viewmodels/MemberListViewModel";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { Flex } from "../../../utils/Flex";
|
||||
import { MemberListViewState } from "../../../viewmodels/memberlist/MemberListViewModel";
|
||||
import { _t } from "../../../../languageHandler";
|
||||
|
||||
interface TooltipProps {
|
||||
canInvite: boolean;
|
||||
@@ -96,7 +96,7 @@ function getHeaderLabelJSX(vm: MemberListViewState): React.ReactNode {
|
||||
return _t("member_list|count", { count: filteredMemberCount });
|
||||
}
|
||||
|
||||
const MemberListHeaderView: React.FC<Props> = (props: Props) => {
|
||||
export const MemberListHeaderView: React.FC<Props> = (props: Props) => {
|
||||
const vm = props.vm;
|
||||
|
||||
let contentJSX: React.ReactNode;
|
||||
@@ -135,5 +135,3 @@ const MemberListHeaderView: React.FC<Props> = (props: Props) => {
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default MemberListHeaderView;
|
||||
@@ -10,12 +10,13 @@ import React from "react";
|
||||
import { List, ListRowProps } from "react-virtualized/dist/commonjs/List";
|
||||
import { AutoSizer } from "react-virtualized";
|
||||
|
||||
import { Flex } from "../../utils/Flex";
|
||||
import { useMemberListViewModel } from "../../viewmodels/MemberListViewModel";
|
||||
import { RoomMemberTileView, ThreePidInviteTileView } from "./MemberTileView";
|
||||
import MemberListHeaderView from "./MemberListHeaderView";
|
||||
import BaseCard from "../right_panel/BaseCard";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { Flex } from "../../../utils/Flex";
|
||||
import { useMemberListViewModel } from "../../../viewmodels/memberlist/MemberListViewModel";
|
||||
import { RoomMemberTileView } from "./tiles/RoomMemberTileView";
|
||||
import { ThreePidInviteTileView } from "./tiles/ThreePidInviteTileView";
|
||||
import { MemberListHeaderView } from "./MemberListHeaderView";
|
||||
import BaseCard from "../../right_panel/BaseCard";
|
||||
import { _t } from "../../../../languageHandler";
|
||||
|
||||
interface IProps {
|
||||
roomId: string;
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import DisambiguatedProfile from "../../../messages/DisambiguatedProfile";
|
||||
import { RoomMember } from "../../../../../models/rooms/RoomMember";
|
||||
import { useMemberTileViewModel } from "../../../../viewmodels/memberlist/tiles/MemberTileViewModel";
|
||||
import { E2EIconView } from "./common/E2EIconView";
|
||||
import AvatarPresenceIconView from "./common/PresenceIconView";
|
||||
import BaseAvatar from "../../../avatars/BaseAvatar";
|
||||
import { _t } from "../../../../../languageHandler";
|
||||
import { MemberTileLayout } from "./common/MemberTileLayout";
|
||||
|
||||
interface IProps {
|
||||
member: RoomMember;
|
||||
showPresence?: boolean;
|
||||
}
|
||||
|
||||
export function RoomMemberTileView(props: IProps): JSX.Element {
|
||||
const vm = useMemberTileViewModel(props);
|
||||
const member = vm.member;
|
||||
const av = (
|
||||
<BaseAvatar
|
||||
size="32px"
|
||||
name={member.name}
|
||||
idName={member.userId}
|
||||
title={member.displayUserId}
|
||||
url={member.avatarThumbnailUrl}
|
||||
altText={_t("common|user_avatar")}
|
||||
/>
|
||||
);
|
||||
const name = vm.name;
|
||||
const nameJSX = <DisambiguatedProfile member={member} fallbackName={name || ""} />;
|
||||
|
||||
const presenceState = member.presenceState;
|
||||
let presenceJSX: JSX.Element | undefined;
|
||||
if (vm.showPresence && presenceState) {
|
||||
presenceJSX = <AvatarPresenceIconView presenceState={presenceState} />;
|
||||
}
|
||||
|
||||
let userLabelJSX;
|
||||
if (vm.userLabel) {
|
||||
userLabelJSX = <div className="mx_MemberTileView_user_label">{vm.userLabel}</div>;
|
||||
}
|
||||
|
||||
let e2eIcon;
|
||||
if (vm.e2eStatus) {
|
||||
e2eIcon = <E2EIconView status={vm.e2eStatus} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<MemberTileLayout
|
||||
title={vm.title}
|
||||
onClick={vm.onClick}
|
||||
avatarJsx={av}
|
||||
presenceJsx={presenceJSX}
|
||||
nameJsx={nameJSX}
|
||||
userLabelJsx={userLabelJSX}
|
||||
e2eIconJsx={e2eIcon}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import { useThreePidTileViewModel } from "../../../../viewmodels/memberlist/tiles/ThreePidTileViewModel";
|
||||
import { ThreePIDInvite } from "../../../../../models/rooms/ThreePIDInvite";
|
||||
import BaseAvatar from "../../../avatars/BaseAvatar";
|
||||
import { MemberTileLayout } from "./common/MemberTileLayout";
|
||||
|
||||
interface Props {
|
||||
threePidInvite: ThreePIDInvite;
|
||||
}
|
||||
|
||||
export function ThreePidInviteTileView(props: Props): JSX.Element {
|
||||
const vm = useThreePidTileViewModel(props);
|
||||
const av = <BaseAvatar name={vm.name} size="32px" aria-hidden="true" />;
|
||||
return <MemberTileLayout nameJsx={vm.name} avatarJsx={av} onClick={vm.onClick} />;
|
||||
}
|
||||
@@ -10,9 +10,9 @@ import { Tooltip } from "@vector-im/compound-web";
|
||||
import VerifiedIcon from "@vector-im/compound-design-tokens/assets/web/icons/verified";
|
||||
import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { E2EStatus } from "../../../utils/ShieldUtils";
|
||||
import { E2EState, crossSigningUserTitles } from "./E2EIcon";
|
||||
import { _t } from "../../../../../../languageHandler";
|
||||
import { E2EStatus } from "../../../../../../utils/ShieldUtils";
|
||||
import { E2EState, crossSigningUserTitles } from "../../../E2EIcon";
|
||||
|
||||
function getIconFromStatus(status: E2EState | E2EStatus): React.JSX.Element | undefined {
|
||||
switch (status) {
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import AccessibleButton from "../../../../elements/AccessibleButton";
|
||||
|
||||
interface Props {
|
||||
avatarJsx: JSX.Element;
|
||||
nameJsx: JSX.Element | string;
|
||||
onClick: () => void;
|
||||
title?: string;
|
||||
presenceJsx?: JSX.Element;
|
||||
userLabelJsx?: JSX.Element;
|
||||
e2eIconJsx?: JSX.Element;
|
||||
}
|
||||
|
||||
export function MemberTileLayout(props: Props): JSX.Element {
|
||||
return (
|
||||
// The wrapping div is required to make the magic mouse listener work, for some reason.
|
||||
<div>
|
||||
<AccessibleButton className="mx_MemberTileView" title={props.title} onClick={props.onClick}>
|
||||
<div className="mx_MemberTileView_left">
|
||||
<div className="mx_MemberTileView_avatar">
|
||||
{props.avatarJsx} {props.presenceJsx}
|
||||
</div>
|
||||
<div className="mx_MemberTileView_name">{props.nameJsx}</div>
|
||||
</div>
|
||||
<div className="mx_MemberTileView_right">
|
||||
{props.userLabelJsx}
|
||||
{props.e2eIconJsx}
|
||||
</div>
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import DisambiguatedProfile from "../messages/DisambiguatedProfile";
|
||||
import { RoomMember } from "../../../models/rooms/RoomMember";
|
||||
import { useThreePidTileViewModel, useMemberTileViewModel } from "../../viewmodels/MemberTileViewModel";
|
||||
import { E2EIconView } from "./E2EIconView";
|
||||
import AvatarPresenceIconView from "./PresenceIconView";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import { ThreePIDInvite } from "../../../models/rooms/ThreePIDInvite";
|
||||
import BaseAvatar from "../avatars/BaseAvatar";
|
||||
import { _t } from "../../../languageHandler";
|
||||
|
||||
interface IProps {
|
||||
member: RoomMember;
|
||||
showPresence?: boolean;
|
||||
}
|
||||
|
||||
interface ThreePidProps {
|
||||
threePidInvite: ThreePIDInvite;
|
||||
}
|
||||
|
||||
interface TileProps {
|
||||
avatarJsx: JSX.Element;
|
||||
nameJsx: JSX.Element | string;
|
||||
onClick: () => void;
|
||||
title?: string;
|
||||
presenceJsx?: JSX.Element;
|
||||
userLabelJsx?: JSX.Element;
|
||||
e2eIconJsx?: JSX.Element;
|
||||
}
|
||||
|
||||
function MemberTile(props: TileProps): JSX.Element {
|
||||
return (
|
||||
// The wrapping div is required to make the magic mouse listener work, for some reason.
|
||||
<div>
|
||||
<AccessibleButton className="mx_MemberTileView" title={props.title} onClick={props.onClick}>
|
||||
<div className="mx_MemberTileView_left">
|
||||
<div className="mx_MemberTileView_avatar">
|
||||
{props.avatarJsx} {props.presenceJsx}
|
||||
</div>
|
||||
<div className="mx_MemberTileView_name">{props.nameJsx}</div>
|
||||
</div>
|
||||
<div className="mx_MemberTileView_right">
|
||||
{props.userLabelJsx}
|
||||
{props.e2eIconJsx}
|
||||
</div>
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ThreePidInviteTileView(props: ThreePidProps): JSX.Element {
|
||||
const vm = useThreePidTileViewModel(props);
|
||||
const av = <BaseAvatar name={vm.name} size="32px" aria-hidden="true" />;
|
||||
return <MemberTile nameJsx={vm.name} avatarJsx={av} onClick={vm.onClick} />;
|
||||
}
|
||||
|
||||
export function RoomMemberTileView(props: IProps): JSX.Element {
|
||||
const vm = useMemberTileViewModel(props);
|
||||
const member = vm.member;
|
||||
const av = (
|
||||
<BaseAvatar
|
||||
size="32px"
|
||||
name={member.name}
|
||||
idName={member.userId}
|
||||
title={member.displayUserId}
|
||||
url={member.avatarThumbnailUrl}
|
||||
altText={_t("common|user_avatar")}
|
||||
/>
|
||||
);
|
||||
const name = vm.name;
|
||||
const nameJSX = <DisambiguatedProfile member={member} fallbackName={name || ""} />;
|
||||
|
||||
const presenceState = member.presenceState;
|
||||
let presenceJSX: JSX.Element | undefined;
|
||||
if (vm.showPresence && presenceState) {
|
||||
presenceJSX = <AvatarPresenceIconView presenceState={presenceState} />;
|
||||
}
|
||||
|
||||
let userLabelJSX;
|
||||
if (vm.userLabel) {
|
||||
userLabelJSX = <div className="mx_MemberTileView_user_label">{vm.userLabel}</div>;
|
||||
}
|
||||
|
||||
let e2eIcon;
|
||||
if (vm.e2eStatus) {
|
||||
e2eIcon = <E2EIconView status={vm.e2eStatus} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<MemberTile
|
||||
title={vm.title}
|
||||
onClick={vm.onClick}
|
||||
avatarJsx={av}
|
||||
presenceJsx={presenceJSX}
|
||||
nameJsx={nameJSX}
|
||||
userLabelJsx={userLabelJSX}
|
||||
e2eIconJsx={e2eIcon}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -18,11 +18,9 @@ import { RoomMember } from "../../../../../../src/models/rooms/RoomMember";
|
||||
import {
|
||||
getPending3PidInvites,
|
||||
sdkRoomMemberToRoomMember,
|
||||
} from "../../../../../../src/components/viewmodels/MemberListViewModel";
|
||||
import {
|
||||
RoomMemberTileView,
|
||||
ThreePidInviteTileView,
|
||||
} from "../../../../../../src/components/views/rooms/MemberTileView";
|
||||
} from "../../../../../../src/components/viewmodels/memberlist/MemberListViewModel";
|
||||
import { RoomMemberTileView } from "../../../../../../src/components/views/rooms/MemberList/tiles/RoomMemberTileView";
|
||||
import { ThreePidInviteTileView } from "../../../../../../src/components/views/rooms/MemberList/tiles/ThreePidInviteTileView";
|
||||
|
||||
describe("MemberTileView", () => {
|
||||
describe("RoomMemberTileView", () => {
|
||||
|
||||
@@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
|
||||
import AvatarPresenceIconView from "../../../../../../src/components/views/rooms/PresenceIconView";
|
||||
import AvatarPresenceIconView from "../../../../../../src/components/views/rooms/MemberList/tiles/common/PresenceIconView";
|
||||
|
||||
describe("<PresenceIconView/>", () => {
|
||||
it("renders correctly for presence=online", () => {
|
||||
|
||||
@@ -16,7 +16,7 @@ import { MatrixClientPeg } from "../../../../../../src/MatrixClientPeg";
|
||||
import * as TestUtils from "../../../../../test-utils";
|
||||
import { SDKContext } from "../../../../../../src/contexts/SDKContext";
|
||||
import { TestSdkContext } from "../../../../TestSdkContext";
|
||||
import MemberListView from "../../../../../../src/components/views/rooms/MemberListView";
|
||||
import MemberListView from "../../../../../../src/components/views/rooms/MemberList/MemberListView";
|
||||
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
|
||||
|
||||
export function createRoom(client: MatrixClient, opts = {}) {
|
||||
|
||||
Reference in New Issue
Block a user