mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-15 20:54:59 +08:00
Extract room directory results to its own component (#8252)
This commit is contained in:
parent
5fbb25c707
commit
233278546b
@ -24,17 +24,14 @@ import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import Modal from "../../Modal";
|
||||
import { linkifyAndSanitizeHtml } from '../../HtmlUtils';
|
||||
import { _t } from '../../languageHandler';
|
||||
import SdkConfig from '../../SdkConfig';
|
||||
import { instanceForInstanceId, protocolNameForInstanceId } from '../../utils/DirectoryUtils';
|
||||
import Analytics from '../../Analytics';
|
||||
import NetworkDropdown, { ALL_ROOMS, Protocols } from "../views/directory/NetworkDropdown";
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import { mediaFromMxc } from "../../customisations/Media";
|
||||
import { IDialogProps } from "../views/dialogs/IDialogProps";
|
||||
import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton";
|
||||
import BaseAvatar from "../views/avatars/BaseAvatar";
|
||||
import ErrorDialog from "../views/dialogs/ErrorDialog";
|
||||
import QuestionDialog from "../views/dialogs/QuestionDialog";
|
||||
import BaseDialog from "../views/dialogs/BaseDialog";
|
||||
@ -45,9 +42,7 @@ import { getDisplayAliasForAliasSet } from "../../Rooms";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import PosthogTrackers from "../../PosthogTrackers";
|
||||
import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
|
||||
|
||||
const MAX_NAME_LENGTH = 80;
|
||||
const MAX_TOPIC_LENGTH = 800;
|
||||
import { PublicRoomTile } from "../views/rooms/PublicRoomTile";
|
||||
|
||||
const LAST_SERVER_KEY = "mx_last_room_directory_server";
|
||||
const LAST_INSTANCE_KEY = "mx_last_room_directory_instance";
|
||||
@ -249,7 +244,7 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
||||
* HS admins to do this through the RoomSettings interface, but
|
||||
* this needs SPEC-417.
|
||||
*/
|
||||
private removeFromDirectory(room: IPublicRoomsChunkRoom) {
|
||||
private removeFromDirectory = (room: IPublicRoomsChunkRoom) => {
|
||||
const alias = getDisplayAliasForRoom(room);
|
||||
const name = room.name || alias || _t('Unnamed room');
|
||||
|
||||
@ -289,14 +284,6 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private onRoomClicked = (room: IPublicRoomsChunkRoom, ev: React.MouseEvent) => {
|
||||
// If room was shift-clicked, remove it from the room directory
|
||||
if (ev.shiftKey) {
|
||||
ev.preventDefault();
|
||||
this.removeFromDirectory(room);
|
||||
}
|
||||
};
|
||||
|
||||
private onOptionChange = (server: string, instanceId?: string) => {
|
||||
@ -404,21 +391,6 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
||||
}
|
||||
};
|
||||
|
||||
private onPreviewClick = (ev: ButtonEvent, room: IPublicRoomsChunkRoom) => {
|
||||
this.showRoom(room, null, false, true);
|
||||
ev.stopPropagation();
|
||||
};
|
||||
|
||||
private onViewClick = (ev: ButtonEvent, room: IPublicRoomsChunkRoom) => {
|
||||
this.showRoom(room);
|
||||
ev.stopPropagation();
|
||||
};
|
||||
|
||||
private onJoinClick = (ev: ButtonEvent, room: IPublicRoomsChunkRoom) => {
|
||||
this.showRoom(room, null, true);
|
||||
ev.stopPropagation();
|
||||
};
|
||||
|
||||
private onCreateRoomClick = (ev: ButtonEvent) => {
|
||||
this.onFinished();
|
||||
dis.dispatch({
|
||||
@ -433,7 +405,7 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
||||
this.showRoom(null, alias, autoJoin);
|
||||
}
|
||||
|
||||
private showRoom(room: IPublicRoomsChunkRoom, roomAlias?: string, autoJoin = false, shouldPeek = false) {
|
||||
private showRoom = (room: IPublicRoomsChunkRoom, roomAlias?: string, autoJoin = false, shouldPeek = false) => {
|
||||
this.onFinished();
|
||||
const payload: ViewRoomPayload = {
|
||||
action: Action.ViewRoom,
|
||||
@ -477,112 +449,7 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
||||
payload.room_id = room.room_id;
|
||||
}
|
||||
dis.dispatch(payload);
|
||||
}
|
||||
|
||||
private createRoomCells(room: IPublicRoomsChunkRoom) {
|
||||
const client = MatrixClientPeg.get();
|
||||
const clientRoom = client.getRoom(room.room_id);
|
||||
const hasJoinedRoom = clientRoom && clientRoom.getMyMembership() === "join";
|
||||
const isGuest = client.isGuest();
|
||||
let previewButton;
|
||||
let joinOrViewButton;
|
||||
|
||||
// Element Web currently does not allow guests to join rooms, so we
|
||||
// instead show them preview buttons for all rooms. If the room is not
|
||||
// world readable, a modal will appear asking you to register first. If
|
||||
// it is readable, the preview appears as normal.
|
||||
if (!hasJoinedRoom && (room.world_readable || isGuest)) {
|
||||
previewButton = (
|
||||
<AccessibleButton kind="secondary" onClick={(ev) => this.onPreviewClick(ev, room)}>
|
||||
{ _t("Preview") }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
if (hasJoinedRoom) {
|
||||
joinOrViewButton = (
|
||||
<AccessibleButton kind="secondary" onClick={(ev) => this.onViewClick(ev, room)}>
|
||||
{ _t("View") }
|
||||
</AccessibleButton>
|
||||
);
|
||||
} else if (!isGuest) {
|
||||
joinOrViewButton = (
|
||||
<AccessibleButton kind="primary" onClick={(ev) => this.onJoinClick(ev, room)}>
|
||||
{ _t("Join") }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
||||
let name = room.name || getDisplayAliasForRoom(room) || _t('Unnamed room');
|
||||
if (name.length > MAX_NAME_LENGTH) {
|
||||
name = `${name.substring(0, MAX_NAME_LENGTH)}...`;
|
||||
}
|
||||
|
||||
let topic = room.topic || '';
|
||||
// Additional truncation based on line numbers is done via CSS,
|
||||
// but to ensure that the DOM is not polluted with a huge string
|
||||
// we give it a hard limit before rendering.
|
||||
if (topic.length > MAX_TOPIC_LENGTH) {
|
||||
topic = `${topic.substring(0, MAX_TOPIC_LENGTH)}...`;
|
||||
}
|
||||
topic = linkifyAndSanitizeHtml(topic);
|
||||
let avatarUrl = null;
|
||||
if (room.avatar_url) avatarUrl = mediaFromMxc(room.avatar_url).getSquareThumbnailHttp(32);
|
||||
|
||||
// We use onMouseDown instead of onClick, so that we can avoid text getting selected
|
||||
return <div
|
||||
key={room.room_id}
|
||||
role="listitem"
|
||||
className="mx_RoomDirectory_listItem"
|
||||
>
|
||||
<div
|
||||
onMouseDown={(ev) => this.onRoomClicked(room, ev)}
|
||||
className="mx_RoomDirectory_roomAvatar"
|
||||
>
|
||||
<BaseAvatar
|
||||
width={32}
|
||||
height={32}
|
||||
resizeMethod='crop'
|
||||
name={name}
|
||||
idName={name}
|
||||
url={avatarUrl}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
onMouseDown={(ev) => this.onRoomClicked(room, ev)}
|
||||
className="mx_RoomDirectory_roomDescription"
|
||||
>
|
||||
<div className="mx_RoomDirectory_name">
|
||||
{ name }
|
||||
</div>
|
||||
<div
|
||||
className="mx_RoomDirectory_topic"
|
||||
dangerouslySetInnerHTML={{ __html: topic }}
|
||||
/>
|
||||
<div className="mx_RoomDirectory_alias">
|
||||
{ getDisplayAliasForRoom(room) }
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
onMouseDown={(ev) => this.onRoomClicked(room, ev)}
|
||||
className="mx_RoomDirectory_roomMemberCount"
|
||||
>
|
||||
{ room.num_joined_members }
|
||||
</div>
|
||||
<div
|
||||
onMouseDown={(ev) => this.onRoomClicked(room, ev)}
|
||||
className="mx_RoomDirectory_preview"
|
||||
>
|
||||
{ previewButton }
|
||||
</div>
|
||||
<div
|
||||
onMouseDown={(ev) => this.onRoomClicked(room, ev)}
|
||||
className="mx_RoomDirectory_join"
|
||||
>
|
||||
{ joinOrViewButton }
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
};
|
||||
private stringLooksLikeId(s: string, fieldType: IFieldType) {
|
||||
let pat = /^#[^\s]+:[^\s]/;
|
||||
if (fieldType && fieldType.regexp) {
|
||||
@ -620,7 +487,14 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
||||
content = <Spinner />;
|
||||
} else {
|
||||
const cells = (this.state.publicRooms || [])
|
||||
.reduce((cells, room) => cells.concat(this.createRoomCells(room)), []);
|
||||
.map(room =>
|
||||
<PublicRoomTile
|
||||
key={room.room_id}
|
||||
room={room}
|
||||
showRoom={this.showRoom}
|
||||
removeFromDirectory={this.removeFromDirectory}
|
||||
/>,
|
||||
);
|
||||
// we still show the scrollpanel, at least for now, because
|
||||
// otherwise we don't fetch more because we don't get a fill
|
||||
// request from the scrollpanel because there isn't one
|
||||
|
179
src/components/views/rooms/PublicRoomTile.tsx
Normal file
179
src/components/views/rooms/PublicRoomTile.tsx
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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, { useCallback, useContext, useEffect, useState } from "react";
|
||||
import { IPublicRoomsChunkRoom } from "matrix-js-sdk/src/client";
|
||||
|
||||
import BaseAvatar from "../avatars/BaseAvatar";
|
||||
import { mediaFromMxc } from "../../../customisations/Media";
|
||||
import { linkifyAndSanitizeHtml } from "../../../HtmlUtils";
|
||||
import { getDisplayAliasForRoom } from "../../structures/RoomDirectory";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import { _t } from "../../../languageHandler";
|
||||
|
||||
const MAX_NAME_LENGTH = 80;
|
||||
const MAX_TOPIC_LENGTH = 800;
|
||||
|
||||
interface IProps {
|
||||
room: IPublicRoomsChunkRoom;
|
||||
removeFromDirectory?: (room: IPublicRoomsChunkRoom) => void;
|
||||
showRoom: (room: IPublicRoomsChunkRoom, roomAlias?: string, autoJoin?: boolean, shouldPeek?: boolean) => void;
|
||||
}
|
||||
|
||||
export const PublicRoomTile = ({
|
||||
room,
|
||||
showRoom,
|
||||
removeFromDirectory,
|
||||
}: IProps) => {
|
||||
const client = useContext(MatrixClientContext);
|
||||
|
||||
const [avatarUrl, setAvatarUrl] = useState<string | null>(null);
|
||||
const [name, setName] = useState("");
|
||||
const [topic, setTopic] = useState("");
|
||||
|
||||
const [hasJoinedRoom, setHasJoinedRoom] = useState(false);
|
||||
|
||||
const isGuest = client.isGuest();
|
||||
|
||||
useEffect(() => {
|
||||
const clientRoom = client.getRoom(room.room_id);
|
||||
|
||||
setHasJoinedRoom(clientRoom?.getMyMembership() === "join");
|
||||
|
||||
let name = room.name || getDisplayAliasForRoom(room) || _t('Unnamed room');
|
||||
if (name.length > MAX_NAME_LENGTH) {
|
||||
name = `${name.substring(0, MAX_NAME_LENGTH)}...`;
|
||||
}
|
||||
setName(name);
|
||||
|
||||
let topic = room.topic || '';
|
||||
// Additional truncation based on line numbers is done via CSS,
|
||||
// but to ensure that the DOM is not polluted with a huge string
|
||||
// we give it a hard limit before rendering.
|
||||
if (topic.length > MAX_TOPIC_LENGTH) {
|
||||
topic = `${topic.substring(0, MAX_TOPIC_LENGTH)}...`;
|
||||
}
|
||||
topic = linkifyAndSanitizeHtml(topic);
|
||||
setTopic(topic);
|
||||
if (room.avatar_url) {
|
||||
setAvatarUrl(mediaFromMxc(room.avatar_url).getSquareThumbnailHttp(32));
|
||||
}
|
||||
}, [room, client]);
|
||||
|
||||
const onRoomClicked = useCallback((ev: React.MouseEvent) => {
|
||||
// If room was shift-clicked, remove it from the room directory
|
||||
if (ev.shiftKey) {
|
||||
ev.preventDefault();
|
||||
removeFromDirectory?.(room);
|
||||
}
|
||||
}, [room, removeFromDirectory]);
|
||||
|
||||
const onPreviewClick = useCallback((ev: React.MouseEvent) => {
|
||||
showRoom(room, null, false, true);
|
||||
ev.stopPropagation();
|
||||
}, [room, showRoom]);
|
||||
|
||||
const onViewClick = useCallback((ev: React.MouseEvent) => {
|
||||
showRoom(room);
|
||||
ev.stopPropagation();
|
||||
}, [room, showRoom]);
|
||||
|
||||
const onJoinClick = useCallback((ev: React.MouseEvent) => {
|
||||
showRoom(room, null, true);
|
||||
ev.stopPropagation();
|
||||
}, [room, showRoom]);
|
||||
|
||||
let previewButton;
|
||||
let joinOrViewButton;
|
||||
|
||||
// Element Web currently does not allow guests to join rooms, so we
|
||||
// instead show them preview buttons for all rooms. If the room is not
|
||||
// world readable, a modal will appear asking you to register first. If
|
||||
// it is readable, the preview appears as normal.
|
||||
if (!hasJoinedRoom && (room.world_readable || isGuest)) {
|
||||
previewButton = (
|
||||
<AccessibleButton kind="secondary" onClick={onPreviewClick}>
|
||||
{ _t("Preview") }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
if (hasJoinedRoom) {
|
||||
joinOrViewButton = (
|
||||
<AccessibleButton kind="secondary" onClick={onViewClick}>
|
||||
{ _t("View") }
|
||||
</AccessibleButton>
|
||||
);
|
||||
} else if (!isGuest) {
|
||||
joinOrViewButton = (
|
||||
<AccessibleButton kind="primary" onClick={onJoinClick}>
|
||||
{ _t("Join") }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
||||
return <div
|
||||
role="listitem"
|
||||
className="mx_RoomDirectory_listItem"
|
||||
>
|
||||
<div
|
||||
onMouseDown={onRoomClicked}
|
||||
className="mx_RoomDirectory_roomAvatar"
|
||||
>
|
||||
<BaseAvatar
|
||||
width={32}
|
||||
height={32}
|
||||
resizeMethod='crop'
|
||||
name={name}
|
||||
idName={name}
|
||||
url={avatarUrl}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
onMouseDown={onRoomClicked}
|
||||
className="mx_RoomDirectory_roomDescription"
|
||||
>
|
||||
<div className="mx_RoomDirectory_name">
|
||||
{ name }
|
||||
</div>
|
||||
<div
|
||||
className="mx_RoomDirectory_topic"
|
||||
dangerouslySetInnerHTML={{ __html: topic }}
|
||||
/>
|
||||
<div className="mx_RoomDirectory_alias">
|
||||
{ getDisplayAliasForRoom(room) }
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
onMouseDown={onRoomClicked}
|
||||
className="mx_RoomDirectory_roomMemberCount"
|
||||
>
|
||||
{ room.num_joined_members }
|
||||
</div>
|
||||
<div
|
||||
onMouseDown={onRoomClicked}
|
||||
className="mx_RoomDirectory_preview"
|
||||
>
|
||||
{ previewButton }
|
||||
</div>
|
||||
<div
|
||||
onMouseDown={onRoomClicked}
|
||||
className="mx_RoomDirectory_join"
|
||||
>
|
||||
{ joinOrViewButton }
|
||||
</div>
|
||||
</div>;
|
||||
};
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
Copyright 2017 New Vector Ltd.
|
||||
|
||||
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 { Room } from 'matrix-js-sdk/src/matrix';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { Action } from '../../../dispatcher/actions';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import RoomDetailRow from "./RoomDetailRow";
|
||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||
|
||||
interface IProps {
|
||||
rooms?: Room[];
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default class RoomDetailList extends React.Component<IProps> {
|
||||
private getRows(): JSX.Element[] {
|
||||
if (!this.props.rooms) return [];
|
||||
return this.props.rooms.map((room, index) => {
|
||||
return <RoomDetailRow key={index} room={room} onClick={this.onDetailsClick} />;
|
||||
});
|
||||
}
|
||||
|
||||
private onDetailsClick = (ev: React.MouseEvent, room: Room): void => {
|
||||
dis.dispatch<ViewRoomPayload>({
|
||||
action: Action.ViewRoom,
|
||||
room_id: room.roomId,
|
||||
room_alias: room.getCanonicalAlias() || (room.getAltAliases() || [])[0],
|
||||
metricsTrigger: undefined, // Deprecated groups
|
||||
});
|
||||
};
|
||||
|
||||
public render(): JSX.Element {
|
||||
const rows = this.getRows();
|
||||
let rooms;
|
||||
if (rows.length === 0) {
|
||||
rooms = <i>{ _t('No rooms to show') }</i>;
|
||||
} else {
|
||||
rooms = <table className="mx_RoomDirectory_table">
|
||||
<tbody>
|
||||
{ this.getRows() }
|
||||
</tbody>
|
||||
</table>;
|
||||
}
|
||||
return <div className={classNames("mx_RoomDetailList", this.props.className)}>
|
||||
{ rooms }
|
||||
</div>;
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
/*
|
||||
Copyright 2017-2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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, { createRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { linkifyElement } from '../../../HtmlUtils';
|
||||
import { mediaFromMxc } from "../../../customisations/Media";
|
||||
import { getDisplayAliasForAliasSet } from '../../../Rooms';
|
||||
import BaseAvatar from "../avatars/BaseAvatar";
|
||||
|
||||
export function getDisplayAliasForRoom(room) {
|
||||
return getDisplayAliasForAliasSet(room.canonicalAlias, room.aliases);
|
||||
}
|
||||
|
||||
export const roomShape = PropTypes.shape({
|
||||
name: PropTypes.string,
|
||||
topic: PropTypes.string,
|
||||
roomId: PropTypes.string,
|
||||
avatarUrl: PropTypes.string,
|
||||
numJoinedMembers: PropTypes.number,
|
||||
canonicalAlias: PropTypes.string,
|
||||
aliases: PropTypes.arrayOf(PropTypes.string),
|
||||
|
||||
worldReadable: PropTypes.bool,
|
||||
guestCanJoin: PropTypes.bool,
|
||||
});
|
||||
|
||||
export default class RoomDetailRow extends React.Component {
|
||||
static propTypes = {
|
||||
room: roomShape,
|
||||
// passes ev, room as args
|
||||
onClick: PropTypes.func,
|
||||
onMouseDown: PropTypes.func,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this._topic = createRef();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._linkifyTopic();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this._linkifyTopic();
|
||||
}
|
||||
|
||||
_linkifyTopic() {
|
||||
if (this._topic.current) {
|
||||
linkifyElement(this._topic.current);
|
||||
}
|
||||
}
|
||||
|
||||
onClick = (ev) => {
|
||||
ev.preventDefault();
|
||||
if (this.props.onClick) {
|
||||
this.props.onClick(ev, this.props.room);
|
||||
}
|
||||
};
|
||||
|
||||
onTopicClick = (ev) => {
|
||||
// When clicking a link in the topic, prevent the event being propagated
|
||||
// to `onClick`.
|
||||
ev.stopPropagation();
|
||||
};
|
||||
|
||||
render() {
|
||||
const room = this.props.room;
|
||||
const name = room.name || getDisplayAliasForRoom(room) || _t('Unnamed room');
|
||||
|
||||
const guestRead = room.worldReadable ? (
|
||||
<div className="mx_RoomDirectory_perm">{ _t('World readable') }</div>
|
||||
) : <div />;
|
||||
const guestJoin = room.guestCanJoin ? (
|
||||
<div className="mx_RoomDirectory_perm">{ _t('Guests can join') }</div>
|
||||
) : <div />;
|
||||
|
||||
const perms = (guestRead || guestJoin) ? (<div className="mx_RoomDirectory_perms">
|
||||
{ guestRead }
|
||||
{ guestJoin }
|
||||
</div>) : <div />;
|
||||
|
||||
let avatarUrl = null;
|
||||
if (room.avatarUrl) avatarUrl = mediaFromMxc(room.avatarUrl).getSquareThumbnailHttp(24);
|
||||
|
||||
return <tr key={room.roomId} onClick={this.onClick} onMouseDown={this.props.onMouseDown}>
|
||||
<td className="mx_RoomDirectory_roomAvatar">
|
||||
<BaseAvatar
|
||||
width={24}
|
||||
height={24}
|
||||
resizeMethod='crop'
|
||||
name={name}
|
||||
idName={name}
|
||||
url={avatarUrl} />
|
||||
</td>
|
||||
<td className="mx_RoomDirectory_roomDescription">
|
||||
<div className="mx_RoomDirectory_name">{ name }</div>
|
||||
{ perms }
|
||||
<div className="mx_RoomDirectory_topic" ref={this._topic} onClick={this.onTopicClick}>
|
||||
{ room.topic }
|
||||
</div>
|
||||
<div className="mx_RoomDirectory_alias">{ getDisplayAliasForRoom(room) }</div>
|
||||
</td>
|
||||
<td className="mx_RoomDirectory_roomMemberCount">
|
||||
{ room.numJoinedMembers }
|
||||
</td>
|
||||
</tr>;
|
||||
}
|
||||
}
|
@ -1732,6 +1732,10 @@
|
||||
"Idle": "Idle",
|
||||
"Offline": "Offline",
|
||||
"Unknown": "Unknown",
|
||||
"Unnamed room": "Unnamed room",
|
||||
"Preview": "Preview",
|
||||
"View": "View",
|
||||
"Join": "Join",
|
||||
"Seen by %(userName)s at %(dateTime)s": "Seen by %(userName)s at %(dateTime)s",
|
||||
"Seen by %(displayName)s (%(userName)s) at %(dateTime)s": "Seen by %(displayName)s (%(userName)s) at %(dateTime)s",
|
||||
"Recently viewed": "Recently viewed",
|
||||
@ -1739,10 +1743,6 @@
|
||||
"Room %(name)s": "Room %(name)s",
|
||||
"Recently visited rooms": "Recently visited rooms",
|
||||
"No recently visited rooms": "No recently visited rooms",
|
||||
"No rooms to show": "No rooms to show",
|
||||
"Unnamed room": "Unnamed room",
|
||||
"World readable": "World readable",
|
||||
"Guests can join": "Guests can join",
|
||||
"(~%(count)s results)|other": "(~%(count)s results)",
|
||||
"(~%(count)s results)|one": "(~%(count)s result)",
|
||||
"Join Room": "Join Room",
|
||||
@ -2211,7 +2211,6 @@
|
||||
"Application window": "Application window",
|
||||
"Share content": "Share content",
|
||||
"Backspace": "Backspace",
|
||||
"Join": "Join",
|
||||
"Please <newIssueLink>create a new issue</newIssueLink> on GitHub so that we can investigate this bug.": "Please <newIssueLink>create a new issue</newIssueLink> on GitHub so that we can investigate this bug.",
|
||||
"Something went wrong!": "Something went wrong!",
|
||||
"%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s",
|
||||
@ -3021,8 +3020,6 @@
|
||||
"Couldn't find a matching Matrix room": "Couldn't find a matching Matrix room",
|
||||
"Fetching third party location failed": "Fetching third party location failed",
|
||||
"Unable to look up room ID from server": "Unable to look up room ID from server",
|
||||
"Preview": "Preview",
|
||||
"View": "View",
|
||||
"Create new room": "Create new room",
|
||||
"No results for \"%(query)s\"": "No results for \"%(query)s\"",
|
||||
"Try different words or check for typos. Some results may not be visible as they're private and you need an invite to join them.": "Try different words or check for typos. Some results may not be visible as they're private and you need an invite to join them.",
|
||||
|
Loading…
Reference in New Issue
Block a user