Move code into directory

This commit is contained in:
R Midhun Suresh
2024-12-31 16:21:26 +05:30
parent 207551b0b7
commit c42394223d
15 changed files with 210 additions and 182 deletions

View File

@@ -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)

View File

@@ -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 }>;

View File

@@ -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>();

View File

@@ -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,
};
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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}
/>
);
}

View File

@@ -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} />;
}

View File

@@ -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) {

View File

@@ -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>
);
}

View File

@@ -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}
/>
);
}

View File

@@ -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", () => {

View File

@@ -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", () => {

View File

@@ -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 = {}) {