Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 9edd498

Browse files
authored
Prepare room components for local rooms (#9082)
1 parent c980885 commit 9edd498

File tree

7 files changed

+252
-109
lines changed

7 files changed

+252
-109
lines changed

res/css/views/rooms/_RoomHeader.pcss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ limitations under the License.
100100
display: flex;
101101
user-select: none;
102102

103-
&:hover {
103+
&:not(.mx_RoomHeader_name--textonly):hover {
104104
background-color: $quinary-content;
105105
}
106106

@@ -139,7 +139,7 @@ limitations under the License.
139139
opacity: 0.6;
140140
}
141141

142-
.mx_RoomHeader_name,
142+
.mx_RoomHeader_name:not(.mx_RoomHeader_name--textonly),
143143
.mx_RoomHeader_avatar {
144144
cursor: pointer;
145145
}

src/components/views/rooms/EventTile.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ import { haveRendererForEvent, isMessageEvent, renderTile } from "../../../event
8080
import ThreadSummary, { ThreadMessagePreview } from "./ThreadSummary";
8181
import { ReadReceiptGroup } from './ReadReceiptGroup';
8282
import { useTooltip } from "../../../utils/useTooltip";
83+
import { isLocalRoom } from '../../../utils/localRoom/isLocalRoom';
8384

8485
export type GetRelationsForEvent = (eventId: string, relationType: string, eventType: string) => Relations;
8586

@@ -766,6 +767,9 @@ export class UnwrappedEventTile extends React.Component<IProps, IState> {
766767
private renderE2EPadlock() {
767768
const ev = this.props.mxEvent;
768769

770+
// no icon for local rooms
771+
if (isLocalRoom(ev.getRoomId())) return;
772+
769773
// event could not be decrypted
770774
if (ev.getContent().msgtype === 'm.bad.encrypted') {
771775
return <E2ePadlockUndecryptable />;

src/components/views/rooms/NewRoomIntro.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { MatrixClientPeg } from "../../../MatrixClientPeg";
3838
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
3939
import { UIComponent } from "../../../settings/UIFeature";
4040
import { privateShouldBeEncrypted } from "../../../utils/rooms";
41+
import { LocalRoom } from "../../../models/LocalRoom";
4142

4243
function hasExpectedEncryptionSettings(matrixClient: MatrixClient, room: Room): boolean {
4344
const isEncrypted: boolean = matrixClient.isRoomEncrypted(room.roomId);
@@ -49,11 +50,19 @@ const NewRoomIntro = () => {
4950
const cli = useContext(MatrixClientContext);
5051
const { room, roomId } = useContext(RoomContext);
5152

52-
const dmPartner = DMRoomMap.shared().getUserIdForRoomId(roomId);
53+
const isLocalRoom = room instanceof LocalRoom;
54+
const dmPartner = isLocalRoom
55+
? room.targets[0]?.userId
56+
: DMRoomMap.shared().getUserIdForRoomId(roomId);
57+
5358
let body;
5459
if (dmPartner) {
60+
let introMessage = _t("This is the beginning of your direct message history with <displayName/>.");
5561
let caption;
56-
if ((room.getJoinedMemberCount() + room.getInvitedMemberCount()) === 2) {
62+
63+
if (isLocalRoom) {
64+
introMessage = _t("Send your first message to invite <displayName/> to chat");
65+
} else if ((room.getJoinedMemberCount() + room.getInvitedMemberCount()) === 2) {
5766
caption = _t("Only the two of you are in this conversation, unless either of you invites anyone to join.");
5867
}
5968

@@ -75,7 +84,7 @@ const NewRoomIntro = () => {
7584

7685
<h2>{ room.name }</h2>
7786

78-
<p>{ _t("This is the beginning of your direct message history with <displayName/>.", {}, {
87+
<p>{ _t(introMessage, {}, {
7988
displayName: () => <b>{ displayName }</b>,
8089
}) }</p>
8190
{ caption && <p>{ caption }</p> }
@@ -200,7 +209,7 @@ const NewRoomIntro = () => {
200209
);
201210

202211
let subButton;
203-
if (room.currentState.mayClientSendStateEvent(EventType.RoomEncryption, MatrixClientPeg.get())) {
212+
if (room.currentState.mayClientSendStateEvent(EventType.RoomEncryption, MatrixClientPeg.get()) && !isLocalRoom) {
204213
subButton = (
205214
<AccessibleButton kind='link_inline' onClick={openRoomSettings}>{ _t("Enable encryption in settings.") }</AccessibleButton>
206215
);

src/components/views/rooms/RoomHeader.tsx

Lines changed: 104 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ interface IProps {
6565
appsShown: boolean;
6666
searchInfo: ISearchInfo;
6767
excludedRightPanelPhaseButtons?: Array<RightPanelPhases>;
68+
showButtons?: boolean;
69+
enableRoomOptionsMenu?: boolean;
6870
}
6971

7072
interface IState {
@@ -76,6 +78,8 @@ export default class RoomHeader extends React.Component<IProps, IState> {
7678
editing: false,
7779
inRoom: false,
7880
excludedRightPanelPhaseButtons: [],
81+
showButtons: true,
82+
enableRoomOptionsMenu: true,
7983
};
8084

8185
static contextType = RoomContext;
@@ -130,81 +134,7 @@ export default class RoomHeader extends React.Component<IProps, IState> {
130134
this.setState({ contextMenuPosition: null });
131135
};
132136

133-
public render() {
134-
let searchStatus = null;
135-
136-
// don't display the search count until the search completes and
137-
// gives us a valid (possibly zero) searchCount.
138-
if (this.props.searchInfo &&
139-
this.props.searchInfo.searchCount !== undefined &&
140-
this.props.searchInfo.searchCount !== null) {
141-
searchStatus = <div className="mx_RoomHeader_searchStatus">&nbsp;
142-
{ _t("(~%(count)s results)", { count: this.props.searchInfo.searchCount }) }
143-
</div>;
144-
}
145-
146-
// XXX: this is a bit inefficient - we could just compare room.name for 'Empty room'...
147-
let settingsHint = false;
148-
const members = this.props.room ? this.props.room.getJoinedMembers() : undefined;
149-
if (members) {
150-
if (members.length === 1 && members[0].userId === MatrixClientPeg.get().credentials.userId) {
151-
const nameEvent = this.props.room.currentState.getStateEvents('m.room.name', '');
152-
if (!nameEvent || !nameEvent.getContent().name) {
153-
settingsHint = true;
154-
}
155-
}
156-
}
157-
158-
let oobName = _t("Join Room");
159-
if (this.props.oobData && this.props.oobData.name) {
160-
oobName = this.props.oobData.name;
161-
}
162-
163-
let contextMenu: JSX.Element;
164-
if (this.state.contextMenuPosition && this.props.room) {
165-
contextMenu = (
166-
<RoomContextMenu
167-
{...contextMenuBelow(this.state.contextMenuPosition)}
168-
room={this.props.room}
169-
onFinished={this.onContextMenuCloseClick}
170-
/>
171-
);
172-
}
173-
174-
const textClasses = classNames('mx_RoomHeader_nametext', { mx_RoomHeader_settingsHint: settingsHint });
175-
const name = (
176-
<ContextMenuTooltipButton
177-
className="mx_RoomHeader_name"
178-
onClick={this.onContextMenuOpenClick}
179-
isExpanded={!!this.state.contextMenuPosition}
180-
title={_t("Room options")}
181-
>
182-
<RoomName room={this.props.room}>
183-
{ (name) => {
184-
const roomName = name || oobName;
185-
return <div dir="auto" className={textClasses} title={roomName}>{ roomName }</div>;
186-
} }
187-
</RoomName>
188-
{ this.props.room && <div className="mx_RoomHeader_chevron" /> }
189-
{ contextMenu }
190-
</ContextMenuTooltipButton>
191-
);
192-
193-
const topicElement = <RoomTopic
194-
room={this.props.room}
195-
className="mx_RoomHeader_topic"
196-
/>;
197-
198-
let roomAvatar;
199-
if (this.props.room) {
200-
roomAvatar = <DecoratedRoomAvatar
201-
room={this.props.room}
202-
avatarSize={24}
203-
oobData={this.props.oobData}
204-
viewAvatarOnClick={true}
205-
/>;
206-
}
207-
137+
private renderButtons(): JSX.Element[] {
208138
const buttons: JSX.Element[] = [];
209139

210140
if (this.props.inRoom &&
@@ -269,10 +199,105 @@ export default class RoomHeader extends React.Component<IProps, IState> {
269199
buttons.push(inviteButton);
270200
}
271201

272-
const rightRow =
273-
<div className="mx_RoomHeader_buttons">
274-
{ buttons }
202+
return buttons;
203+
}
204+
205+
private renderName(oobName) {
206+
let contextMenu: JSX.Element;
207+
if (this.state.contextMenuPosition && this.props.room) {
208+
contextMenu = (
209+
<RoomContextMenu
210+
{...contextMenuBelow(this.state.contextMenuPosition)}
211+
room={this.props.room}
212+
onFinished={this.onContextMenuCloseClick}
213+
/>
214+
);
215+
}
216+
217+
// XXX: this is a bit inefficient - we could just compare room.name for 'Empty room'...
218+
let settingsHint = false;
219+
const members = this.props.room ? this.props.room.getJoinedMembers() : undefined;
220+
if (members) {
221+
if (members.length === 1 && members[0].userId === MatrixClientPeg.get().credentials.userId) {
222+
const nameEvent = this.props.room.currentState.getStateEvents('m.room.name', '');
223+
if (!nameEvent || !nameEvent.getContent().name) {
224+
settingsHint = true;
225+
}
226+
}
227+
}
228+
229+
const textClasses = classNames('mx_RoomHeader_nametext', { mx_RoomHeader_settingsHint: settingsHint });
230+
const roomName = <RoomName room={this.props.room}>
231+
{ (name) => {
232+
const roomName = name || oobName;
233+
return <div dir="auto" className={textClasses} title={roomName}>{ roomName }</div>;
234+
} }
235+
</RoomName>;
236+
237+
if (this.props.enableRoomOptionsMenu) {
238+
return (
239+
<ContextMenuTooltipButton
240+
className="mx_RoomHeader_name"
241+
onClick={this.onContextMenuOpenClick}
242+
isExpanded={!!this.state.contextMenuPosition}
243+
title={_t("Room options")}
244+
>
245+
{ roomName }
246+
{ this.props.room && <div className="mx_RoomHeader_chevron" /> }
247+
{ contextMenu }
248+
</ContextMenuTooltipButton>
249+
);
250+
}
251+
252+
return <div className="mx_RoomHeader_name mx_RoomHeader_name--textonly">
253+
{ roomName }
254+
</div>;
255+
}
256+
257+
public render() {
258+
let searchStatus = null;
259+
260+
// don't display the search count until the search completes and
261+
// gives us a valid (possibly zero) searchCount.
262+
if (this.props.searchInfo &&
263+
this.props.searchInfo.searchCount !== undefined &&
264+
this.props.searchInfo.searchCount !== null) {
265+
searchStatus = <div className="mx_RoomHeader_searchStatus">&nbsp;
266+
{ _t("(~%(count)s results)", { count: this.props.searchInfo.searchCount }) }
275267
</div>;
268+
}
269+
270+
let oobName = _t("Join Room");
271+
if (this.props.oobData && this.props.oobData.name) {
272+
oobName = this.props.oobData.name;
273+
}
274+
275+
const name = this.renderName(oobName);
276+
277+
const topicElement = <RoomTopic
278+
room={this.props.room}
279+
className="mx_RoomHeader_topic"
280+
/>;
281+
282+
let roomAvatar;
283+
if (this.props.room) {
284+
roomAvatar = <DecoratedRoomAvatar
285+
room={this.props.room}
286+
avatarSize={24}
287+
oobData={this.props.oobData}
288+
viewAvatarOnClick={true}
289+
/>;
290+
}
291+
292+
let buttons;
293+
if (this.props.showButtons) {
294+
buttons = <React.Fragment>
295+
<div className="mx_RoomHeader_buttons">
296+
{ this.renderButtons() }
297+
</div>
298+
<RoomHeaderButtons room={this.props.room} excludedRightPanelPhaseButtons={this.props.excludedRightPanelPhaseButtons} />
299+
</React.Fragment>;
300+
}
276301

277302
const e2eIcon = this.props.e2eStatus ? <E2EIcon status={this.props.e2eStatus} /> : undefined;
278303

@@ -294,8 +319,7 @@ export default class RoomHeader extends React.Component<IProps, IState> {
294319
{ searchStatus }
295320
{ topicElement }
296321
{ betaPill }
297-
{ rightRow }
298-
<RoomHeaderButtons room={this.props.room} excludedRightPanelPhaseButtons={this.props.excludedRightPanelPhaseButtons} />
322+
{ buttons }
299323
</div>
300324
<RoomLiveShareWarning roomId={this.props.room.roomId} />
301325
</div>

src/i18n/strings/en_EN.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,8 +1730,9 @@
17301730
"Code block": "Code block",
17311731
"Quote": "Quote",
17321732
"Insert link": "Insert link",
1733-
"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.",
17341733
"This is the beginning of your direct message history with <displayName/>.": "This is the beginning of your direct message history with <displayName/>.",
1734+
"Send your first message to invite <displayName/> to chat": "Send your first message to invite <displayName/> to chat",
1735+
"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.",
17351736
"Topic: %(topic)s (<a>edit</a>)": "Topic: %(topic)s (<a>edit</a>)",
17361737
"Topic: %(topic)s ": "Topic: %(topic)s ",
17371738
"<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 @@
17711772
"Room %(name)s": "Room %(name)s",
17721773
"Recently visited rooms": "Recently visited rooms",
17731774
"No recently visited rooms": "No recently visited rooms",
1774-
"(~%(count)s results)|other": "(~%(count)s results)",
1775-
"(~%(count)s results)|one": "(~%(count)s result)",
1776-
"Join Room": "Join Room",
1777-
"Room options": "Room options",
17781775
"Forget room": "Forget room",
17791776
"Hide Widgets": "Hide Widgets",
17801777
"Show Widgets": "Show Widgets",
17811778
"Search": "Search",
17821779
"Invite": "Invite",
1780+
"Room options": "Room options",
1781+
"(~%(count)s results)|other": "(~%(count)s results)",
1782+
"(~%(count)s results)|one": "(~%(count)s result)",
1783+
"Join Room": "Join Room",
17831784
"Video rooms are a beta feature": "Video rooms are a beta feature",
17841785
"Video room": "Video room",
17851786
"Public space": "Public space",

0 commit comments

Comments
 (0)