Prepare room components for local rooms (#9082)
This commit is contained in:
parent
c980885d6b
commit
9edd49818c
7 changed files with 252 additions and 109 deletions
|
@ -100,7 +100,7 @@ limitations under the License.
|
||||||
display: flex;
|
display: flex;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
&:hover {
|
&:not(.mx_RoomHeader_name--textonly):hover {
|
||||||
background-color: $quinary-content;
|
background-color: $quinary-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ limitations under the License.
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomHeader_name,
|
.mx_RoomHeader_name:not(.mx_RoomHeader_name--textonly),
|
||||||
.mx_RoomHeader_avatar {
|
.mx_RoomHeader_avatar {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,7 @@ import { haveRendererForEvent, isMessageEvent, renderTile } from "../../../event
|
||||||
import ThreadSummary, { ThreadMessagePreview } from "./ThreadSummary";
|
import ThreadSummary, { ThreadMessagePreview } from "./ThreadSummary";
|
||||||
import { ReadReceiptGroup } from './ReadReceiptGroup';
|
import { ReadReceiptGroup } from './ReadReceiptGroup';
|
||||||
import { useTooltip } from "../../../utils/useTooltip";
|
import { useTooltip } from "../../../utils/useTooltip";
|
||||||
|
import { isLocalRoom } from '../../../utils/localRoom/isLocalRoom';
|
||||||
|
|
||||||
export type GetRelationsForEvent = (eventId: string, relationType: string, eventType: string) => Relations;
|
export type GetRelationsForEvent = (eventId: string, relationType: string, eventType: string) => Relations;
|
||||||
|
|
||||||
|
@ -766,6 +767,9 @@ export class UnwrappedEventTile extends React.Component<IProps, IState> {
|
||||||
private renderE2EPadlock() {
|
private renderE2EPadlock() {
|
||||||
const ev = this.props.mxEvent;
|
const ev = this.props.mxEvent;
|
||||||
|
|
||||||
|
// no icon for local rooms
|
||||||
|
if (isLocalRoom(ev.getRoomId())) return;
|
||||||
|
|
||||||
// event could not be decrypted
|
// event could not be decrypted
|
||||||
if (ev.getContent().msgtype === 'm.bad.encrypted') {
|
if (ev.getContent().msgtype === 'm.bad.encrypted') {
|
||||||
return <E2ePadlockUndecryptable />;
|
return <E2ePadlockUndecryptable />;
|
||||||
|
|
|
@ -38,6 +38,7 @@ import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
||||||
import { UIComponent } from "../../../settings/UIFeature";
|
import { UIComponent } from "../../../settings/UIFeature";
|
||||||
import { privateShouldBeEncrypted } from "../../../utils/rooms";
|
import { privateShouldBeEncrypted } from "../../../utils/rooms";
|
||||||
|
import { LocalRoom } from "../../../models/LocalRoom";
|
||||||
|
|
||||||
function hasExpectedEncryptionSettings(matrixClient: MatrixClient, room: Room): boolean {
|
function hasExpectedEncryptionSettings(matrixClient: MatrixClient, room: Room): boolean {
|
||||||
const isEncrypted: boolean = matrixClient.isRoomEncrypted(room.roomId);
|
const isEncrypted: boolean = matrixClient.isRoomEncrypted(room.roomId);
|
||||||
|
@ -49,11 +50,19 @@ const NewRoomIntro = () => {
|
||||||
const cli = useContext(MatrixClientContext);
|
const cli = useContext(MatrixClientContext);
|
||||||
const { room, roomId } = useContext(RoomContext);
|
const { room, roomId } = useContext(RoomContext);
|
||||||
|
|
||||||
const dmPartner = DMRoomMap.shared().getUserIdForRoomId(roomId);
|
const isLocalRoom = room instanceof LocalRoom;
|
||||||
|
const dmPartner = isLocalRoom
|
||||||
|
? room.targets[0]?.userId
|
||||||
|
: DMRoomMap.shared().getUserIdForRoomId(roomId);
|
||||||
|
|
||||||
let body;
|
let body;
|
||||||
if (dmPartner) {
|
if (dmPartner) {
|
||||||
|
let introMessage = _t("This is the beginning of your direct message history with <displayName/>.");
|
||||||
let caption;
|
let caption;
|
||||||
if ((room.getJoinedMemberCount() + room.getInvitedMemberCount()) === 2) {
|
|
||||||
|
if (isLocalRoom) {
|
||||||
|
introMessage = _t("Send your first message to invite <displayName/> to chat");
|
||||||
|
} else if ((room.getJoinedMemberCount() + room.getInvitedMemberCount()) === 2) {
|
||||||
caption = _t("Only the two of you are in this conversation, unless either of you invites anyone to join.");
|
caption = _t("Only the two of you are in this conversation, unless either of you invites anyone to join.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +84,7 @@ const NewRoomIntro = () => {
|
||||||
|
|
||||||
<h2>{ room.name }</h2>
|
<h2>{ room.name }</h2>
|
||||||
|
|
||||||
<p>{ _t("This is the beginning of your direct message history with <displayName/>.", {}, {
|
<p>{ _t(introMessage, {}, {
|
||||||
displayName: () => <b>{ displayName }</b>,
|
displayName: () => <b>{ displayName }</b>,
|
||||||
}) }</p>
|
}) }</p>
|
||||||
{ caption && <p>{ caption }</p> }
|
{ caption && <p>{ caption }</p> }
|
||||||
|
@ -200,7 +209,7 @@ const NewRoomIntro = () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
let subButton;
|
let subButton;
|
||||||
if (room.currentState.mayClientSendStateEvent(EventType.RoomEncryption, MatrixClientPeg.get())) {
|
if (room.currentState.mayClientSendStateEvent(EventType.RoomEncryption, MatrixClientPeg.get()) && !isLocalRoom) {
|
||||||
subButton = (
|
subButton = (
|
||||||
<AccessibleButton kind='link_inline' onClick={openRoomSettings}>{ _t("Enable encryption in settings.") }</AccessibleButton>
|
<AccessibleButton kind='link_inline' onClick={openRoomSettings}>{ _t("Enable encryption in settings.") }</AccessibleButton>
|
||||||
);
|
);
|
||||||
|
|
|
@ -65,6 +65,8 @@ interface IProps {
|
||||||
appsShown: boolean;
|
appsShown: boolean;
|
||||||
searchInfo: ISearchInfo;
|
searchInfo: ISearchInfo;
|
||||||
excludedRightPanelPhaseButtons?: Array<RightPanelPhases>;
|
excludedRightPanelPhaseButtons?: Array<RightPanelPhases>;
|
||||||
|
showButtons?: boolean;
|
||||||
|
enableRoomOptionsMenu?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
|
@ -76,6 +78,8 @@ export default class RoomHeader extends React.Component<IProps, IState> {
|
||||||
editing: false,
|
editing: false,
|
||||||
inRoom: false,
|
inRoom: false,
|
||||||
excludedRightPanelPhaseButtons: [],
|
excludedRightPanelPhaseButtons: [],
|
||||||
|
showButtons: true,
|
||||||
|
enableRoomOptionsMenu: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
static contextType = RoomContext;
|
static contextType = RoomContext;
|
||||||
|
@ -130,81 +134,7 @@ export default class RoomHeader extends React.Component<IProps, IState> {
|
||||||
this.setState({ contextMenuPosition: null });
|
this.setState({ contextMenuPosition: null });
|
||||||
};
|
};
|
||||||
|
|
||||||
public render() {
|
private renderButtons(): JSX.Element[] {
|
||||||
let searchStatus = null;
|
|
||||||
|
|
||||||
// don't display the search count until the search completes and
|
|
||||||
// gives us a valid (possibly zero) searchCount.
|
|
||||||
if (this.props.searchInfo &&
|
|
||||||
this.props.searchInfo.searchCount !== undefined &&
|
|
||||||
this.props.searchInfo.searchCount !== null) {
|
|
||||||
searchStatus = <div className="mx_RoomHeader_searchStatus">
|
|
||||||
{ _t("(~%(count)s results)", { count: this.props.searchInfo.searchCount }) }
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: this is a bit inefficient - we could just compare room.name for 'Empty room'...
|
|
||||||
let settingsHint = false;
|
|
||||||
const members = this.props.room ? this.props.room.getJoinedMembers() : undefined;
|
|
||||||
if (members) {
|
|
||||||
if (members.length === 1 && members[0].userId === MatrixClientPeg.get().credentials.userId) {
|
|
||||||
const nameEvent = this.props.room.currentState.getStateEvents('m.room.name', '');
|
|
||||||
if (!nameEvent || !nameEvent.getContent().name) {
|
|
||||||
settingsHint = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let oobName = _t("Join Room");
|
|
||||||
if (this.props.oobData && this.props.oobData.name) {
|
|
||||||
oobName = this.props.oobData.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
let contextMenu: JSX.Element;
|
|
||||||
if (this.state.contextMenuPosition && this.props.room) {
|
|
||||||
contextMenu = (
|
|
||||||
<RoomContextMenu
|
|
||||||
{...contextMenuBelow(this.state.contextMenuPosition)}
|
|
||||||
room={this.props.room}
|
|
||||||
onFinished={this.onContextMenuCloseClick}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const textClasses = classNames('mx_RoomHeader_nametext', { mx_RoomHeader_settingsHint: settingsHint });
|
|
||||||
const name = (
|
|
||||||
<ContextMenuTooltipButton
|
|
||||||
className="mx_RoomHeader_name"
|
|
||||||
onClick={this.onContextMenuOpenClick}
|
|
||||||
isExpanded={!!this.state.contextMenuPosition}
|
|
||||||
title={_t("Room options")}
|
|
||||||
>
|
|
||||||
<RoomName room={this.props.room}>
|
|
||||||
{ (name) => {
|
|
||||||
const roomName = name || oobName;
|
|
||||||
return <div dir="auto" className={textClasses} title={roomName}>{ roomName }</div>;
|
|
||||||
} }
|
|
||||||
</RoomName>
|
|
||||||
{ this.props.room && <div className="mx_RoomHeader_chevron" /> }
|
|
||||||
{ contextMenu }
|
|
||||||
</ContextMenuTooltipButton>
|
|
||||||
);
|
|
||||||
|
|
||||||
const topicElement = <RoomTopic
|
|
||||||
room={this.props.room}
|
|
||||||
className="mx_RoomHeader_topic"
|
|
||||||
/>;
|
|
||||||
|
|
||||||
let roomAvatar;
|
|
||||||
if (this.props.room) {
|
|
||||||
roomAvatar = <DecoratedRoomAvatar
|
|
||||||
room={this.props.room}
|
|
||||||
avatarSize={24}
|
|
||||||
oobData={this.props.oobData}
|
|
||||||
viewAvatarOnClick={true}
|
|
||||||
/>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const buttons: JSX.Element[] = [];
|
const buttons: JSX.Element[] = [];
|
||||||
|
|
||||||
if (this.props.inRoom &&
|
if (this.props.inRoom &&
|
||||||
|
@ -269,10 +199,105 @@ export default class RoomHeader extends React.Component<IProps, IState> {
|
||||||
buttons.push(inviteButton);
|
buttons.push(inviteButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rightRow =
|
return buttons;
|
||||||
<div className="mx_RoomHeader_buttons">
|
}
|
||||||
{ buttons }
|
|
||||||
|
private renderName(oobName) {
|
||||||
|
let contextMenu: JSX.Element;
|
||||||
|
if (this.state.contextMenuPosition && this.props.room) {
|
||||||
|
contextMenu = (
|
||||||
|
<RoomContextMenu
|
||||||
|
{...contextMenuBelow(this.state.contextMenuPosition)}
|
||||||
|
room={this.props.room}
|
||||||
|
onFinished={this.onContextMenuCloseClick}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: this is a bit inefficient - we could just compare room.name for 'Empty room'...
|
||||||
|
let settingsHint = false;
|
||||||
|
const members = this.props.room ? this.props.room.getJoinedMembers() : undefined;
|
||||||
|
if (members) {
|
||||||
|
if (members.length === 1 && members[0].userId === MatrixClientPeg.get().credentials.userId) {
|
||||||
|
const nameEvent = this.props.room.currentState.getStateEvents('m.room.name', '');
|
||||||
|
if (!nameEvent || !nameEvent.getContent().name) {
|
||||||
|
settingsHint = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const textClasses = classNames('mx_RoomHeader_nametext', { mx_RoomHeader_settingsHint: settingsHint });
|
||||||
|
const roomName = <RoomName room={this.props.room}>
|
||||||
|
{ (name) => {
|
||||||
|
const roomName = name || oobName;
|
||||||
|
return <div dir="auto" className={textClasses} title={roomName}>{ roomName }</div>;
|
||||||
|
} }
|
||||||
|
</RoomName>;
|
||||||
|
|
||||||
|
if (this.props.enableRoomOptionsMenu) {
|
||||||
|
return (
|
||||||
|
<ContextMenuTooltipButton
|
||||||
|
className="mx_RoomHeader_name"
|
||||||
|
onClick={this.onContextMenuOpenClick}
|
||||||
|
isExpanded={!!this.state.contextMenuPosition}
|
||||||
|
title={_t("Room options")}
|
||||||
|
>
|
||||||
|
{ roomName }
|
||||||
|
{ this.props.room && <div className="mx_RoomHeader_chevron" /> }
|
||||||
|
{ contextMenu }
|
||||||
|
</ContextMenuTooltipButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="mx_RoomHeader_name mx_RoomHeader_name--textonly">
|
||||||
|
{ roomName }
|
||||||
</div>;
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
let searchStatus = null;
|
||||||
|
|
||||||
|
// don't display the search count until the search completes and
|
||||||
|
// gives us a valid (possibly zero) searchCount.
|
||||||
|
if (this.props.searchInfo &&
|
||||||
|
this.props.searchInfo.searchCount !== undefined &&
|
||||||
|
this.props.searchInfo.searchCount !== null) {
|
||||||
|
searchStatus = <div className="mx_RoomHeader_searchStatus">
|
||||||
|
{ _t("(~%(count)s results)", { count: this.props.searchInfo.searchCount }) }
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let oobName = _t("Join Room");
|
||||||
|
if (this.props.oobData && this.props.oobData.name) {
|
||||||
|
oobName = this.props.oobData.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = this.renderName(oobName);
|
||||||
|
|
||||||
|
const topicElement = <RoomTopic
|
||||||
|
room={this.props.room}
|
||||||
|
className="mx_RoomHeader_topic"
|
||||||
|
/>;
|
||||||
|
|
||||||
|
let roomAvatar;
|
||||||
|
if (this.props.room) {
|
||||||
|
roomAvatar = <DecoratedRoomAvatar
|
||||||
|
room={this.props.room}
|
||||||
|
avatarSize={24}
|
||||||
|
oobData={this.props.oobData}
|
||||||
|
viewAvatarOnClick={true}
|
||||||
|
/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let buttons;
|
||||||
|
if (this.props.showButtons) {
|
||||||
|
buttons = <React.Fragment>
|
||||||
|
<div className="mx_RoomHeader_buttons">
|
||||||
|
{ this.renderButtons() }
|
||||||
|
</div>
|
||||||
|
<RoomHeaderButtons room={this.props.room} excludedRightPanelPhaseButtons={this.props.excludedRightPanelPhaseButtons} />
|
||||||
|
</React.Fragment>;
|
||||||
|
}
|
||||||
|
|
||||||
const e2eIcon = this.props.e2eStatus ? <E2EIcon status={this.props.e2eStatus} /> : undefined;
|
const e2eIcon = this.props.e2eStatus ? <E2EIcon status={this.props.e2eStatus} /> : undefined;
|
||||||
|
|
||||||
|
@ -294,8 +319,7 @@ export default class RoomHeader extends React.Component<IProps, IState> {
|
||||||
{ searchStatus }
|
{ searchStatus }
|
||||||
{ topicElement }
|
{ topicElement }
|
||||||
{ betaPill }
|
{ betaPill }
|
||||||
{ rightRow }
|
{ buttons }
|
||||||
<RoomHeaderButtons room={this.props.room} excludedRightPanelPhaseButtons={this.props.excludedRightPanelPhaseButtons} />
|
|
||||||
</div>
|
</div>
|
||||||
<RoomLiveShareWarning roomId={this.props.room.roomId} />
|
<RoomLiveShareWarning roomId={this.props.room.roomId} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1730,8 +1730,9 @@
|
||||||
"Code block": "Code block",
|
"Code block": "Code block",
|
||||||
"Quote": "Quote",
|
"Quote": "Quote",
|
||||||
"Insert link": "Insert link",
|
"Insert link": "Insert link",
|
||||||
"Only the two of you are in this conversation, unless either of you invites anyone to join.": "Only the two of you are in this conversation, unless either of you invites anyone to join.",
|
|
||||||
"This is the beginning of your direct message history with <displayName/>.": "This is the beginning of your direct message history with <displayName/>.",
|
"This is the beginning of your direct message history with <displayName/>.": "This is the beginning of your direct message history with <displayName/>.",
|
||||||
|
"Send your first message to invite <displayName/> to chat": "Send your first message to invite <displayName/> to chat",
|
||||||
|
"Only the two of you are in this conversation, unless either of you invites anyone to join.": "Only the two of you are in this conversation, unless either of you invites anyone to join.",
|
||||||
"Topic: %(topic)s (<a>edit</a>)": "Topic: %(topic)s (<a>edit</a>)",
|
"Topic: %(topic)s (<a>edit</a>)": "Topic: %(topic)s (<a>edit</a>)",
|
||||||
"Topic: %(topic)s ": "Topic: %(topic)s ",
|
"Topic: %(topic)s ": "Topic: %(topic)s ",
|
||||||
"<a>Add a topic</a> to help people know what it is about.": "<a>Add a topic</a> to help people know what it is about.",
|
"<a>Add a topic</a> to help people know what it is about.": "<a>Add a topic</a> to help people know what it is about.",
|
||||||
|
@ -1771,15 +1772,15 @@
|
||||||
"Room %(name)s": "Room %(name)s",
|
"Room %(name)s": "Room %(name)s",
|
||||||
"Recently visited rooms": "Recently visited rooms",
|
"Recently visited rooms": "Recently visited rooms",
|
||||||
"No recently visited rooms": "No recently visited rooms",
|
"No recently visited rooms": "No recently visited rooms",
|
||||||
"(~%(count)s results)|other": "(~%(count)s results)",
|
|
||||||
"(~%(count)s results)|one": "(~%(count)s result)",
|
|
||||||
"Join Room": "Join Room",
|
|
||||||
"Room options": "Room options",
|
|
||||||
"Forget room": "Forget room",
|
"Forget room": "Forget room",
|
||||||
"Hide Widgets": "Hide Widgets",
|
"Hide Widgets": "Hide Widgets",
|
||||||
"Show Widgets": "Show Widgets",
|
"Show Widgets": "Show Widgets",
|
||||||
"Search": "Search",
|
"Search": "Search",
|
||||||
"Invite": "Invite",
|
"Invite": "Invite",
|
||||||
|
"Room options": "Room options",
|
||||||
|
"(~%(count)s results)|other": "(~%(count)s results)",
|
||||||
|
"(~%(count)s results)|one": "(~%(count)s result)",
|
||||||
|
"Join Room": "Join Room",
|
||||||
"Video rooms are a beta feature": "Video rooms are a beta feature",
|
"Video rooms are a beta feature": "Video rooms are a beta feature",
|
||||||
"Video room": "Video room",
|
"Video room": "Video room",
|
||||||
"Public space": "Public space",
|
"Public space": "Public space",
|
||||||
|
|
78
test/components/views/rooms/NewRoomIntro-test.tsx
Normal file
78
test/components/views/rooms/NewRoomIntro-test.tsx
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015 - 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
||||||
|
|
||||||
|
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 React from "react";
|
||||||
|
import { render, screen } from "@testing-library/react";
|
||||||
|
import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
|
import { LocalRoom } from "../../../../src/models/LocalRoom";
|
||||||
|
import { createTestClient } from "../../../test-utils";
|
||||||
|
import RoomContext from "../../../../src/contexts/RoomContext";
|
||||||
|
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
||||||
|
import NewRoomIntro from "../../../../src/components/views/rooms/NewRoomIntro";
|
||||||
|
import { IRoomState } from "../../../../src/components/structures/RoomView";
|
||||||
|
import DMRoomMap from "../../../../src/utils/DMRoomMap";
|
||||||
|
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||||
|
import { DirectoryMember } from "../../../../src/utils/direct-messages";
|
||||||
|
|
||||||
|
const renderNewRoomIntro = (client: MatrixClient, room: Room|LocalRoom) => {
|
||||||
|
render(
|
||||||
|
<MatrixClientContext.Provider value={client}>
|
||||||
|
<RoomContext.Provider value={{ room, roomId: room.roomId } as unknown as IRoomState}>
|
||||||
|
<NewRoomIntro />
|
||||||
|
</RoomContext.Provider>
|
||||||
|
</MatrixClientContext.Provider>,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("NewRoomIntro", () => {
|
||||||
|
let client: MatrixClient;
|
||||||
|
const roomId = "!room:example.com";
|
||||||
|
const userId = "@user:example.com";
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
client = createTestClient();
|
||||||
|
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(client);
|
||||||
|
DMRoomMap.makeShared();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("for a DM Room", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(userId);
|
||||||
|
renderNewRoomIntro(client, new Room(roomId, client, client.getUserId()));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render the expected intro", () => {
|
||||||
|
const expected = `This is the beginning of your direct message history with ${userId}.`;
|
||||||
|
screen.getByText((id, element) => element.tagName === "SPAN" && element.textContent === expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("for a DM LocalRoom", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(userId);
|
||||||
|
const localRoom = new LocalRoom(roomId, client, client.getUserId());
|
||||||
|
localRoom.targets.push(new DirectoryMember({ user_id: userId }));
|
||||||
|
renderNewRoomIntro(client, localRoom);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render the expected intro", () => {
|
||||||
|
const expected = `Send your first message to invite ${userId} to chat`;
|
||||||
|
screen.getByText((id, element) => element.tagName === "SPAN" && element.textContent === expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -127,7 +127,7 @@ describe('RoomHeader', () => {
|
||||||
|
|
||||||
it("hides call buttons when the room is tombstoned", () => {
|
it("hides call buttons when the room is tombstoned", () => {
|
||||||
const room = createRoom({ name: "Room", isDm: false, userIds: [] });
|
const room = createRoom({ name: "Room", isDm: false, userIds: [] });
|
||||||
const wrapper = render(room, {
|
const wrapper = render(room, {}, {
|
||||||
tombstone: mkEvent({
|
tombstone: mkEvent({
|
||||||
event: true,
|
event: true,
|
||||||
type: "m.room.tombstone",
|
type: "m.room.tombstone",
|
||||||
|
@ -142,6 +142,30 @@ describe('RoomHeader', () => {
|
||||||
expect(wrapper.find('[aria-label="Voice call"]').hostNodes()).toHaveLength(0);
|
expect(wrapper.find('[aria-label="Voice call"]').hostNodes()).toHaveLength(0);
|
||||||
expect(wrapper.find('[aria-label="Video call"]').hostNodes()).toHaveLength(0);
|
expect(wrapper.find('[aria-label="Video call"]').hostNodes()).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should render buttons if not passing showButtons (default true)", () => {
|
||||||
|
const room = createRoom({ name: "Room", isDm: false, userIds: [] });
|
||||||
|
const wrapper = render(room);
|
||||||
|
expect(wrapper.find(".mx_RoomHeader_buttons")).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not render buttons if passing showButtons = false", () => {
|
||||||
|
const room = createRoom({ name: "Room", isDm: false, userIds: [] });
|
||||||
|
const wrapper = render(room, { showButtons: false });
|
||||||
|
expect(wrapper.find(".mx_RoomHeader_buttons")).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render the room options context menu if not passing enableRoomOptionsMenu (default true)", () => {
|
||||||
|
const room = createRoom({ name: "Room", isDm: false, userIds: [] });
|
||||||
|
const wrapper = render(room);
|
||||||
|
expect(wrapper.find(".mx_RoomHeader_name.mx_AccessibleButton")).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not render the room options context menu if passing enableRoomOptionsMenu = false", () => {
|
||||||
|
const room = createRoom({ name: "Room", isDm: false, userIds: [] });
|
||||||
|
const wrapper = render(room, { enableRoomOptionsMenu: false });
|
||||||
|
expect(wrapper.find(".mx_RoomHeader_name.mx_AccessibleButton")).toHaveLength(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IRoomCreationInfo {
|
interface IRoomCreationInfo {
|
||||||
|
@ -185,25 +209,28 @@ function createRoom(info: IRoomCreationInfo) {
|
||||||
return room;
|
return room;
|
||||||
}
|
}
|
||||||
|
|
||||||
function render(room: Room, roomContext?: Partial<IRoomState>): ReactWrapper {
|
function render(room: Room, propsOverride = {}, roomContext?: Partial<IRoomState>): ReactWrapper {
|
||||||
return mount((
|
const props = {
|
||||||
<RoomContext.Provider value={{ ...roomContext, room } as IRoomState}>
|
room,
|
||||||
<RoomHeader
|
inRoom: true,
|
||||||
room={room}
|
onSearchClick: () => {},
|
||||||
inRoom={true}
|
onInviteClick: null,
|
||||||
onSearchClick={() => {}}
|
onForgetClick: () => {},
|
||||||
onInviteClick={null}
|
onCallPlaced: (_type) => { },
|
||||||
onForgetClick={() => {}}
|
onAppsClick: () => {},
|
||||||
onCallPlaced={(_type) => { }}
|
e2eStatus: E2EStatus.Normal,
|
||||||
onAppsClick={() => {}}
|
appsShown: true,
|
||||||
e2eStatus={E2EStatus.Normal}
|
searchInfo: {
|
||||||
appsShown={true}
|
|
||||||
searchInfo={{
|
|
||||||
searchTerm: "",
|
searchTerm: "",
|
||||||
searchScope: SearchScope.Room,
|
searchScope: SearchScope.Room,
|
||||||
searchCount: 0,
|
searchCount: 0,
|
||||||
}}
|
},
|
||||||
/>
|
...propsOverride,
|
||||||
|
};
|
||||||
|
|
||||||
|
return mount((
|
||||||
|
<RoomContext.Provider value={{ ...roomContext, room } as IRoomState}>
|
||||||
|
<RoomHeader {...props} />
|
||||||
</RoomContext.Provider>
|
</RoomContext.Provider>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue