From eea8b3a668dcc72aed101abe56186b7477765604 Mon Sep 17 00:00:00 2001
From: Travis Ralston
Date: Fri, 8 Oct 2021 23:04:26 +0100
Subject: [PATCH] PARTIAL: Add customisation point for visibility of invites
and room creation
Fixes https://github.com/vector-im/element-web/issues/19331
(cherry picked from commit d99660d420be70298a5f53dd84c1ab07c4fc5850)
---
src/SlashCommands.tsx | 168 ++++++++++++------
src/components/views/right_panel/UserInfo.tsx | 5 +-
src/components/views/rooms/MemberList.tsx | 29 +--
src/components/views/rooms/RoomSublist.tsx | 54 +++---
src/i18n/strings/en_EN.json | 4 +
5 files changed, 163 insertions(+), 97 deletions(-)
diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx
index 3ffe7b37ab1..701f584b9fa 100644
--- a/src/SlashCommands.tsx
+++ b/src/SlashCommands.tsx
@@ -20,8 +20,10 @@ limitations under the License.
import * as React from 'react';
import { User } from "matrix-js-sdk/src/models/user";
import { EventType } from "matrix-js-sdk/src/@types/event";
-
import * as ContentHelpers from 'matrix-js-sdk/src/content-helpers';
+import { parseFragment as parseHtml, Element as ChildElement } from "parse5";
+import { logger } from "matrix-js-sdk/src/logger";
+
import { MatrixClientPeg } from './MatrixClientPeg';
import dis from './dispatcher/dispatcher';
import { _t, _td } from './languageHandler';
@@ -37,7 +39,6 @@ import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from './utils/I
import { isPermalinkHost, parsePermalink } from "./utils/permalinks/Permalinks";
import { WidgetType } from "./widgets/WidgetType";
import { Jitsi } from "./widgets/Jitsi";
-import { parseFragment as parseHtml, Element as ChildElement } from "parse5";
import BugReportDialog from "./components/views/dialogs/BugReportDialog";
import { ensureDMExists } from "./createRoom";
import { ViewUserPayload } from "./dispatcher/payloads/ViewUserPayload";
@@ -55,8 +56,6 @@ import DevtoolsDialog from './components/views/dialogs/DevtoolsDialog';
import RoomUpgradeWarningDialog from "./components/views/dialogs/RoomUpgradeWarningDialog";
import InfoDialog from "./components/views/dialogs/InfoDialog";
import SlashCommandHelpDialog from "./components/views/dialogs/SlashCommandHelpDialog";
-
-import { logger } from "matrix-js-sdk/src/logger";
import { shouldShowComponent } from "./customisations/helpers/UIComponents";
import { TimelineRenderingType } from './contexts/RoomContext';
import RoomViewStore from "./stores/RoomViewStore";
@@ -183,7 +182,7 @@ export const Commands = [
command: 'spoiler',
args: '',
description: _td('Sends the given message as a spoiler'),
- runFn: function (roomId, message) {
+ runFn: function(roomId, message) {
return successSync(ContentHelpers.makeHtmlMessage(
message,
`${message}`,
@@ -195,7 +194,7 @@ export const Commands = [
command: 'shrug',
args: '',
description: _td('Prepends ¯\\_(ツ)_/¯ to a plain-text message'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
let message = '¯\\_(ツ)_/¯';
if (args) {
message = message + ' ' + args;
@@ -208,7 +207,7 @@ export const Commands = [
command: 'tableflip',
args: '',
description: _td('Prepends (╯°□°)╯︵ ┻━┻ to a plain-text message'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
let message = '(╯°□°)╯︵ ┻━┻';
if (args) {
message = message + ' ' + args;
@@ -221,7 +220,7 @@ export const Commands = [
command: 'unflip',
args: '',
description: _td('Prepends ┬──┬ ノ( ゜-゜ノ) to a plain-text message'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
let message = '┬──┬ ノ( ゜-゜ノ)';
if (args) {
message = message + ' ' + args;
@@ -234,7 +233,7 @@ export const Commands = [
command: 'lenny',
args: '',
description: _td('Prepends ( ͡° ͜ʖ ͡°) to a plain-text message'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
let message = '( ͡° ͜ʖ ͡°)';
if (args) {
message = message + ' ' + args;
@@ -247,7 +246,7 @@ export const Commands = [
command: 'plain',
args: '',
description: _td('Sends a message as plain text, without interpreting it as markdown'),
- runFn: function (roomId, messages) {
+ runFn: function(roomId, messages) {
return successSync(ContentHelpers.makeTextMessage(messages));
},
category: CommandCategories.messages,
@@ -256,7 +255,7 @@ export const Commands = [
command: 'html',
args: '',
description: _td('Sends a message as html, without interpreting it as markdown'),
- runFn: function (roomId, messages) {
+ runFn: function(roomId, messages) {
return successSync(ContentHelpers.makeHtmlMessage(messages, messages));
},
category: CommandCategories.messages,
@@ -265,7 +264,7 @@ export const Commands = [
command: 'upgraderoom',
args: '',
description: _td('Upgrades a room to a new version'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
const cli = MatrixClientPeg.get();
const room = cli.getRoom(roomId);
@@ -291,7 +290,7 @@ export const Commands = [
command: 'nick',
args: '',
description: _td('Changes your display nickname'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
return success(MatrixClientPeg.get().setDisplayName(args));
}
@@ -305,7 +304,7 @@ export const Commands = [
aliases: ['roomnick'],
args: '',
description: _td('Changes your display nickname in the current room only'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
const cli = MatrixClientPeg.get();
const ev = cli.getRoom(roomId).currentState.getStateEvents('m.room.member', cli.getUserId());
@@ -324,7 +323,7 @@ export const Commands = [
command: 'roomavatar',
args: '[]',
description: _td('Changes the avatar of the current room'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
let promise = Promise.resolve(args);
if (!args) {
promise = singleMxcUpload();
@@ -342,7 +341,7 @@ export const Commands = [
command: 'myroomavatar',
args: '[]',
description: _td('Changes your avatar in this current room only'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
const cli = MatrixClientPeg.get();
const room = cli.getRoom(roomId);
const userId = cli.getUserId();
@@ -369,7 +368,7 @@ export const Commands = [
command: 'myavatar',
args: '[]',
description: _td('Changes your avatar in all rooms'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
let promise = Promise.resolve(args);
if (!args) {
promise = singleMxcUpload();
@@ -387,7 +386,7 @@ export const Commands = [
command: 'topic',
args: '[]',
description: _td('Gets or sets the room topic'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
const cli = MatrixClientPeg.get();
if (args) {
return success(cli.setRoomTopic(roomId, args));
@@ -413,7 +412,7 @@ export const Commands = [
command: 'roomname',
args: '',
description: _td('Sets the room name'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
return success(MatrixClientPeg.get().setRoomName(roomId, args));
}
@@ -422,12 +421,75 @@ export const Commands = [
category: CommandCategories.admin,
renderingTypes: [TimelineRenderingType.Room],
}),
+ new Command({
+ command: 'invite',
+ args: ' []',
+ description: _td('Invites user with given id to current room'),
+ isEnabled: () => shouldShowComponent(UIComponent.InviteUsers),
+ runFn: function(roomId, args) {
+ if (args) {
+ const [address, reason] = args.split(/\s+(.+)/);
+ if (address) {
+ // We use a MultiInviter to re-use the invite logic, even though
+ // we're only inviting one user.
+ // If we need an identity server but don't have one, things
+ // get a bit more complex here, but we try to show something
+ // meaningful.
+ let prom = Promise.resolve();
+ if (
+ getAddressType(address) === 'email' &&
+ !MatrixClientPeg.get().getIdentityServerUrl()
+ ) {
+ const defaultIdentityServerUrl = getDefaultIdentityServerUrl();
+ if (defaultIdentityServerUrl) {
+ const { finished } = Modal.createTrackedDialog<[boolean]>(
+ 'Slash Commands',
+ 'Identity server',
+ QuestionDialog, {
+ title: _t("Use an identity server"),
+ description: { _t(
+ "Use an identity server to invite by email. " +
+ "Click continue to use the default identity server " +
+ "(%(defaultIdentityServerName)s) or manage in Settings.",
+ {
+ defaultIdentityServerName: abbreviateUrl(defaultIdentityServerUrl),
+ },
+ ) }
,
+ button: _t("Continue"),
+ },
+ );
+
+ prom = finished.then(([useDefault]) => {
+ if (useDefault) {
+ useDefaultIdentityServer();
+ return;
+ }
+ throw new Error(_t("Use an identity server to invite by email. Manage in Settings."));
+ });
+ } else {
+ return reject(_t("Use an identity server to invite by email. Manage in Settings."));
+ }
+ }
+ const inviter = new MultiInviter(roomId);
+ return success(prom.then(() => {
+ return inviter.invite([address], reason);
+ }).then(() => {
+ if (inviter.getCompletionState(address) !== "invited") {
+ throw new Error(inviter.getErrorText(address));
+ }
+ }));
+ }
+ }
+ return reject(this.getUsage());
+ },
+ category: CommandCategories.actions,
+ }),
new Command({
command: 'join',
aliases: ['j', 'goto'],
args: '',
description: _td('Joins room with given address'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
// Note: we support 2 versions of this command. The first is
// the public-facing one for most users and the other is a
@@ -542,7 +604,7 @@ export const Commands = [
command: 'part',
args: '[]',
description: _td('Leave room'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
const cli = MatrixClientPeg.get();
let targetRoomId;
@@ -586,7 +648,7 @@ export const Commands = [
command: 'kick',
args: ' [reason]',
description: _td('Kicks user with given id'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
const matches = args.match(/^(\S+?)( +(.*))?$/);
if (matches) {
@@ -602,7 +664,7 @@ export const Commands = [
command: 'ban',
args: ' [reason]',
description: _td('Bans user with given id'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
const matches = args.match(/^(\S+?)( +(.*))?$/);
if (matches) {
@@ -618,7 +680,7 @@ export const Commands = [
command: 'unban',
args: '',
description: _td('Unbans user with given ID'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
const matches = args.match(/^(\S+)$/);
if (matches) {
@@ -635,7 +697,7 @@ export const Commands = [
command: 'ignore',
args: '',
description: _td('Ignores a user, hiding their messages from you'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
const cli = MatrixClientPeg.get();
@@ -649,7 +711,7 @@ export const Commands = [
Modal.createTrackedDialog('Slash Commands', 'User ignored', InfoDialog, {
title: _t('Ignored user'),
description:
-
{_t('You are now ignoring %(userId)s', { userId })}
+
{ _t('You are now ignoring %(userId)s', { userId }) }
,
});
}),
@@ -664,7 +726,7 @@ export const Commands = [
command: 'unignore',
args: '',
description: _td('Stops ignoring a user, showing their messages going forward'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
const cli = MatrixClientPeg.get();
@@ -679,7 +741,7 @@ export const Commands = [
Modal.createTrackedDialog('Slash Commands', 'User unignored', InfoDialog, {
title: _t('Unignored user'),
description:
-
{_t('You are no longer ignoring %(userId)s', { userId })}
+
{ _t('You are no longer ignoring %(userId)s', { userId }) }
,
});
}),
@@ -699,7 +761,7 @@ export const Commands = [
const room = cli.getRoom(RoomViewStore.getRoomId());
return room?.currentState.maySendStateEvent(EventType.RoomPowerLevels, cli.getUserId());
},
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
const matches = args.match(/^(\S+?)( +(-?\d+))?$/);
let powerLevel = 50; // default power level for op
@@ -735,7 +797,7 @@ export const Commands = [
const room = cli.getRoom(RoomViewStore.getRoomId());
return room?.currentState.maySendStateEvent(EventType.RoomPowerLevels, cli.getUserId());
},
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
const matches = args.match(/^(\S+)$/);
if (matches) {
@@ -756,7 +818,7 @@ export const Commands = [
new Command({
command: 'devtools',
description: _td('Opens the Developer Tools dialog'),
- runFn: function (roomId) {
+ runFn: function(roomId) {
Modal.createDialog(DevtoolsDialog, { roomId });
return success();
},
@@ -767,7 +829,7 @@ export const Commands = [
args: '',
description: _td('Adds a custom widget by URL to the room'),
isEnabled: () => SettingsStore.getValue(UIFeature.Widgets),
- runFn: function (roomId, widgetUrl) {
+ runFn: function(roomId, widgetUrl) {
if (!widgetUrl) {
return reject(_t("Please supply a widget URL or embed code"));
}
@@ -820,7 +882,7 @@ export const Commands = [
command: 'verify',
args: ' ',
description: _td('Verifies a user, session, and pubkey tuple'),
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
const matches = args.match(/^(\S+) +(\S+) +(\S+)$/);
if (matches) {
@@ -851,12 +913,12 @@ export const Commands = [
_t('WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session' +
' %(deviceId)s is "%(fprint)s" which does not match the provided key ' +
'"%(fingerprint)s". This could mean your communications are being intercepted!',
- {
- fprint,
- userId,
- deviceId,
- fingerprint,
- }));
+ {
+ fprint,
+ userId,
+ deviceId,
+ fingerprint,
+ }));
}
await cli.setDeviceVerified(userId, deviceId, true);
@@ -869,7 +931,7 @@ export const Commands = [
{
_t('The signing key you provided matches the signing key you received ' +
'from %(userId)s\'s session %(deviceId)s. Session marked as verified.',
- { userId, deviceId })
+ { userId, deviceId })
}
,
@@ -885,7 +947,7 @@ export const Commands = [
new Command({
command: 'discardsession',
description: _td('Forces the current outbound group session in an encrypted room to be discarded'),
- runFn: function (roomId) {
+ runFn: function(roomId) {
try {
MatrixClientPeg.get().forceDiscardSession(roomId);
} catch (e) {
@@ -900,7 +962,7 @@ export const Commands = [
command: "rainbow",
description: _td("Sends the given message coloured as a rainbow"),
args: '',
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (!args) return reject(this.getUserId());
return successSync(ContentHelpers.makeHtmlMessage(args, textToHtmlRainbow(args)));
},
@@ -910,7 +972,7 @@ export const Commands = [
command: "rainbowme",
description: _td("Sends the given emote coloured as a rainbow"),
args: '',
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (!args) return reject(this.getUserId());
return successSync(ContentHelpers.makeHtmlEmote(args, textToHtmlRainbow(args)));
},
@@ -919,7 +981,7 @@ export const Commands = [
new Command({
command: "help",
description: _td("Displays list of commands with usages and descriptions"),
- runFn: function () {
+ runFn: function() {
Modal.createTrackedDialog('Slash Commands', 'Help', SlashCommandHelpDialog);
return success();
},
@@ -929,7 +991,7 @@ export const Commands = [
command: "whois",
description: _td("Displays information about a user"),
args: "",
- runFn: function (roomId, userId) {
+ runFn: function(roomId, userId) {
if (!userId || !userId.startsWith("@") || !userId.includes(":")) {
return reject(this.getUsage());
}
@@ -950,7 +1012,7 @@ export const Commands = [
description: _td("Send a bug report with logs"),
isEnabled: () => !!SdkConfig.get().bug_report_endpoint_url,
args: "",
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
return success(
Modal.createTrackedDialog('Slash Commands', 'Bug Report Dialog', BugReportDialog, {
initialText: args,
@@ -963,7 +1025,7 @@ export const Commands = [
command: "query",
description: _td("Opens chat with the given user"),
args: "",
- runFn: function (roomId, userId) {
+ runFn: function(roomId, userId) {
// easter-egg for now: look up phone numbers through the thirdparty API
// (very dumb phone number detection...)
const isPhoneNumber = userId && /^\+?[0123456789]+$/.test(userId);
@@ -994,7 +1056,7 @@ export const Commands = [
command: "msg",
description: _td("Sends a message to the given user"),
args: " []",
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
if (args) {
// matches the first whitespace delimited group and then the rest of the string
const matches = args.match(/^(\S+?)(?: +(.*))?$/s);
@@ -1024,7 +1086,7 @@ export const Commands = [
command: "holdcall",
description: _td("Places the call in the current room on hold"),
category: CommandCategories.other,
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
const call = CallHandler.sharedInstance().getCallForRoom(roomId);
if (!call) {
return reject("No active call in this room");
@@ -1038,7 +1100,7 @@ export const Commands = [
command: "unholdcall",
description: _td("Takes the call in the current room off hold"),
category: CommandCategories.other,
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
const call = CallHandler.sharedInstance().getCallForRoom(roomId);
if (!call) {
return reject("No active call in this room");
@@ -1052,7 +1114,7 @@ export const Commands = [
command: "converttodm",
description: _td("Converts the room to a DM"),
category: CommandCategories.other,
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
const room = MatrixClientPeg.get().getRoom(roomId);
return success(guessAndSetDMRoom(room, true));
},
@@ -1062,7 +1124,7 @@ export const Commands = [
command: "converttoroom",
description: _td("Converts the DM to a room"),
category: CommandCategories.other,
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
const room = MatrixClientPeg.get().getRoom(roomId);
return success(guessAndSetDMRoom(room, false));
},
@@ -1084,7 +1146,7 @@ export const Commands = [
command: effect.command,
description: effect.description(),
args: '',
- runFn: function (roomId, args) {
+ runFn: function(roomId, args) {
return success((async () => {
if (!args) {
args = effect.fallbackMessage();
diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx
index ec5889d8e9f..1162c951ee4 100644
--- a/src/components/views/right_panel/UserInfo.tsx
+++ b/src/components/views/right_panel/UserInfo.tsx
@@ -26,6 +26,8 @@ import { Room } from 'matrix-js-sdk/src/models/room';
import { EventTimeline } from 'matrix-js-sdk/src/models/event-timeline';
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
import { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
+import { EventType } from "matrix-js-sdk/src/@types/event";
+import { logger } from "matrix-js-sdk/src/logger";
import dis from '../../../dispatcher/dispatcher';
import Modal from '../../../Modal';
@@ -62,7 +64,6 @@ import ErrorDialog from "../dialogs/ErrorDialog";
import QuestionDialog from "../dialogs/QuestionDialog";
import ConfirmUserActionDialog from "../dialogs/ConfirmUserActionDialog";
import InfoDialog from "../dialogs/InfoDialog";
-import { EventType } from "matrix-js-sdk/src/@types/event";
import { SetRightPanelPhasePayload } from "../../../dispatcher/payloads/SetRightPanelPhasePayload";
import RoomAvatar from "../avatars/RoomAvatar";
import RoomName from "../elements/RoomName";
@@ -72,8 +73,6 @@ import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInse
import SpaceStore from "../../../stores/spaces/SpaceStore";
import ConfirmSpaceUserActionDialog from "../dialogs/ConfirmSpaceUserActionDialog";
import { bulkSpaceBehaviour } from "../../../utils/space";
-
-import { logger } from "matrix-js-sdk/src/logger";
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
import { UIComponent } from "../../../settings/UIFeature";
import { TimelineRenderingType } from "../../../contexts/RoomContext";
diff --git a/src/components/views/rooms/MemberList.tsx b/src/components/views/rooms/MemberList.tsx
index 213b57337cd..7ee5fe286f2 100644
--- a/src/components/views/rooms/MemberList.tsx
+++ b/src/components/views/rooms/MemberList.tsx
@@ -19,6 +19,14 @@ limitations under the License.
*/
import React from 'react';
+import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
+import { Room } from 'matrix-js-sdk/src/models/room';
+import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
+import { RoomState } from 'matrix-js-sdk/src/models/room-state';
+import { User } from "matrix-js-sdk/src/models/user";
+import { throttle } from 'lodash';
+import { JoinRule } from "matrix-js-sdk/src/@types/partials";
+
import { _t } from '../../../languageHandler';
import SdkConfig from '../../../SdkConfig';
import dis from '../../../dispatcher/dispatcher';
@@ -31,11 +39,6 @@ import RoomAvatar from "../avatars/RoomAvatar";
import RoomName from "../elements/RoomName";
import { replaceableComponent } from "../../../utils/replaceableComponent";
import SettingsStore from "../../../settings/SettingsStore";
-import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
-import { Room } from 'matrix-js-sdk/src/models/room';
-import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
-import { RoomState } from 'matrix-js-sdk/src/models/room-state';
-import { User } from "matrix-js-sdk/src/models/user";
import TruncatedList from '../elements/TruncatedList';
import Spinner from "../elements/Spinner";
import SearchBox from "../../structures/SearchBox";
@@ -43,11 +46,9 @@ import AccessibleButton from '../elements/AccessibleButton';
import EntityTile from "./EntityTile";
import MemberTile from "./MemberTile";
import BaseAvatar from '../avatars/BaseAvatar';
-import { throttle } from 'lodash';
import SpaceStore from "../../../stores/spaces/SpaceStore";
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
import { UIComponent } from "../../../settings/UIFeature";
-import { JoinRule } from "matrix-js-sdk/src/@types/partials";
const INITIAL_LOAD_NUM_MEMBERS = 30;
const INITIAL_LOAD_NUM_INVITED = 5;
@@ -460,7 +461,7 @@ export default class MemberList extends React.Component {
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
if (room) {
- return room.currentState.getStateEvents("m.room.third_party_invite").filter(function (e) {
+ return room.currentState.getStateEvents("m.room.third_party_invite").filter(function(e) {
if (!isValid3pidInvite(e)) return false;
// discard all invites which have a m.room.member event since we've
@@ -538,7 +539,7 @@ export default class MemberList extends React.Component {
onClick={this.onInviteButtonClick}
disabled={!this.state.canInvite}
>
- {inviteButtonText}
+ { inviteButtonText }
);
}
@@ -546,7 +547,7 @@ export default class MemberList extends React.Component {
let invitedHeader;
let invitedSection;
if (this.getChildCountInvited() > 0) {
- invitedHeader = {_t("Invited")}
;
+ invitedHeader = { _t("Invited") }
;
invitedSection = (
{
return
- {scopeHeader}
- {inviteButton}
+ { scopeHeader }
+ { inviteButton }
}
footer={footer}
onClose={this.props.onClose}
@@ -595,8 +596,8 @@ export default class MemberList extends React.Component {
createOverflowElement={this.createOverflowTileJoined}
getChildren={this.getChildrenJoined}
getChildCount={this.getChildCountJoined} />
- {invitedHeader}
- {invitedSection}
+ { invitedHeader }
+ { invitedSection }
;
}
diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx
index 11c64eaa0dc..49d31a9311e 100644
--- a/src/components/views/rooms/RoomSublist.tsx
+++ b/src/components/views/rooms/RoomSublist.tsx
@@ -579,20 +579,20 @@ export default class RoomSublist extends React.Component {
-
{_t("Appearance")}
+
{ _t("Appearance") }
- {_t("Show rooms with unread messages first")}
+ { _t("Show rooms with unread messages first") }
- {_t("Show previews of messages")}
+ { _t("Show previews of messages") }
@@ -608,14 +608,14 @@ export default class RoomSublist extends React.Component {
>
-
{_t("Sort by")}
+
{ _t("Sort by") }
this.onTagSortChanged(SortAlgorithm.Recent)}
checked={!isAlphabetical}
name={`mx_${this.props.tagId}_sortBy`}
>
- {_t("Activity")}
+ { _t("Activity") }
{
checked={isAlphabetical}
name={`mx_${this.props.tagId}_sortBy`}
>
- {_t("A-Z")}
+ { _t("A-Z") }
- {otherSections}
+ { otherSections }
);
@@ -639,7 +639,7 @@ export default class RoomSublist extends React.Component {
onFinished={this.onCloseAddRoomMenu}
compact
>
- {this.props.addRoomContextMenu(this.onCloseAddRoomMenu)}
+ { this.props.addRoomContextMenu(this.onCloseAddRoomMenu) }
);
}
@@ -658,8 +658,8 @@ export default class RoomSublist extends React.Component {
return (
- {roomSublistEllipsisMenu}
- {contextMenu}
+ { roomSublistEllipsisMenu }
+ { contextMenu }
);
}
@@ -667,7 +667,7 @@ export default class RoomSublist extends React.Component {
private renderHeader(): React.ReactElement {
return (
- {({ onFocus, isActive, ref }) => {
+ { ({ onFocus, isActive, ref }) => {
const tabIndex = isActive ? 0 : -1;
let ariaLabel = _t("Jump to first unread room.");
@@ -762,14 +762,14 @@ export default class RoomSublist extends React.Component {
title={this.props.isMinimized ? this.props.label : undefined}
>
- {this.props.label}
+ { this.props.label }
- {this.renderMenu()}
- {this.props.isMinimized ? null : badgeContainer}
- {this.props.isMinimized ? null : addRoomButton}
+ { this.renderMenu() }
+ { this.props.isMinimized ? null : badgeContainer }
+ { this.props.isMinimized ? null : addRoomButton }
- {this.props.isMinimized ? badgeContainer : null}
- {this.props.isMinimized ? addRoomButton : null}
+ { this.props.isMinimized ? badgeContainer : null }
+ { this.props.isMinimized ? addRoomButton : null }
);
}
@@ -821,7 +821,7 @@ export default class RoomSublist extends React.Component {
const label = _t("Show %(count)s more", { count: numMissing });
let showMoreText = (
- {label}
+ { label }
);
if (this.props.isMinimized) showMoreText = null;
@@ -833,9 +833,9 @@ export default class RoomSublist extends React.Component {
aria-label={label}
>
- { /* set by CSS masking */}
+ { /* set by CSS masking */ }
- {showMoreText}
+ { showMoreText }
);
} else if (this.numTiles > this.layout.defaultVisibleTiles) {
@@ -843,7 +843,7 @@ export default class RoomSublist extends React.Component {
const label = _t("Show less");
let showLessText = (
- {label}
+ { label }
);
if (this.props.isMinimized) showLessText = null;
@@ -855,9 +855,9 @@ export default class RoomSublist extends React.Component {
aria-label={label}
>
- { /* set by CSS masking */}
+ { /* set by CSS masking */ }
- {showLessText}
+ { showLessText }
);
}
@@ -908,9 +908,9 @@ export default class RoomSublist extends React.Component {
enable={handles}
>
- {visibleTiles}
+ { visibleTiles }
- {showNButton}
+ { showNButton }
);
@@ -926,8 +926,8 @@ export default class RoomSublist extends React.Component {
aria-label={this.props.label}
onKeyDown={this.onKeyDown}
>
- {this.renderHeader()}
- {content}
+ { this.renderHeader() }
+ { content }
);
}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index f571b5bcc6e..166fef8b2ca 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -443,6 +443,10 @@
"Failed to set topic": "Failed to set topic",
"This room has no topic.": "This room has no topic.",
"Sets the room name": "Sets the room name",
+ "Invites user with given id to current room": "Invites user with given id to current room",
+ "Use an identity server": "Use an identity server",
+ "Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.",
+ "Use an identity server to invite by email. Manage in Settings.": "Use an identity server to invite by email. Manage in Settings.",
"Joins room with given address": "Joins room with given address",
"Leave room": "Leave room",
"Unrecognised room address:": "Unrecognised room address:",