- { _t("You must register to use this functionality",
- {},
- { 'a': (sub) => { sub } })
- }
+ { _t("You must register to use this functionality",
+ {},
+ { 'a': (sub) => { sub } })
+ }
) }
diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js
index ed6167cbe7..3ab009d7b8 100644
--- a/src/components/structures/GroupView.js
+++ b/src/components/structures/GroupView.js
@@ -43,7 +43,7 @@ import {mediaFromMxc} from "../../customisations/Media";
import {replaceableComponent} from "../../utils/replaceableComponent";
const LONG_DESC_PLACEHOLDER = _td(
-`
HTML for your community's page
+ `
HTML for your community's page
Use the long description to introduce new members to the community, or distribute
some important links
@@ -110,14 +110,16 @@ class CategoryRoomList extends React.Component {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog(
'Failed to add the following room to the group summary',
- '', ErrorDialog,
- {
- title: _t(
- "Failed to add the following rooms to the summary of %(groupId)s:",
- {groupId: this.props.groupId},
- ),
- description: errorList.join(", "),
- });
+ '',
+ ErrorDialog,
+ {
+ title: _t(
+ "Failed to add the following rooms to the summary of %(groupId)s:",
+ {groupId: this.props.groupId},
+ ),
+ description: errorList.join(", "),
+ },
+ );
});
},
}, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
@@ -146,8 +148,8 @@ class CategoryRoomList extends React.Component {
let catHeader =
;
if (this.props.category && this.props.category.profile) {
catHeader =
- { this.props.category.profile.name }
-
;
+ { this.props.category.profile.name }
+
;
}
return
{ catHeader }
@@ -190,13 +192,14 @@ class FeaturedRoom extends React.Component {
Modal.createTrackedDialog(
'Failed to remove room from group summary',
'', ErrorDialog,
- {
- title: _t(
- "Failed to remove the room from the summary of %(groupId)s",
- {groupId: this.props.groupId},
- ),
- description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}),
- });
+ {
+ title: _t(
+ "Failed to remove the room from the summary of %(groupId)s",
+ {groupId: this.props.groupId},
+ ),
+ description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}),
+ },
+ );
});
};
@@ -283,13 +286,14 @@ class RoleUserList extends React.Component {
Modal.createTrackedDialog(
'Failed to add the following users to the community summary',
'', ErrorDialog,
- {
- title: _t(
- "Failed to add the following users to the summary of %(groupId)s:",
- {groupId: this.props.groupId},
- ),
- description: errorList.join(", "),
- });
+ {
+ title: _t(
+ "Failed to add the following users to the summary of %(groupId)s:",
+ {groupId: this.props.groupId},
+ ),
+ description: errorList.join(", "),
+ },
+ );
});
},
}, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
@@ -299,11 +303,11 @@ class RoleUserList extends React.Component {
const TintableSvg = sdk.getComponent("elements.TintableSvg");
const addButton = this.props.editing ?
(
-
-
- { _t('Add a User') }
-
- ) : ;
+
+
+ { _t('Add a User') }
+
+ ) : ;
const userNodes = this.props.users.map((u) => {
return
- { _t("Leave %(groupName)s?", {groupName: this.props.groupId}) }
- { warnings }
+ { _t("Leave %(groupName)s?", {groupName: this.props.groupId}) }
+ { warnings }
),
button: _t("Leave"),
@@ -1055,10 +1061,11 @@ export default class GroupView extends React.Component {
return null;
}
- const membershipButtonClasses = classnames([
- 'mx_RoomHeader_textButton',
- 'mx_GroupView_textButton',
- ],
+ const membershipButtonClasses = classnames(
+ [
+ 'mx_RoomHeader_textButton',
+ 'mx_GroupView_textButton',
+ ],
membershipButtonExtraClasses,
);
diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx
index e4762e35ad..44b404bd3a 100644
--- a/src/components/structures/LeftPanel.tsx
+++ b/src/components/structures/LeftPanel.tsx
@@ -347,7 +347,7 @@ export default class LeftPanel extends React.Component {
if (element) {
classes = element.classList;
}
- } while (element && !cssClasses.some(c => classes.contains(c)));
+ } while (element && (!cssClasses.some(c => classes.contains(c)) || element.offsetParent === null));
if (element) {
element.focus();
diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js
index 132d9ab4c3..c93f07fa0f 100644
--- a/src/components/structures/MessagePanel.js
+++ b/src/components/structures/MessagePanel.js
@@ -427,8 +427,10 @@ export default class MessagePanel extends React.Component {
// we get a new DOM node (restarting the animation) when the ghost
// moves to a different event.
return (
-
+
{ hr }
);
@@ -1014,13 +1016,13 @@ class CreationGrouper {
ret.push(
- { eventTiles }
+ { eventTiles }
,
);
@@ -1222,11 +1224,11 @@ class MemberGrouper {
ret.push(
- { eventTiles }
+ { eventTiles }
,
);
diff --git a/src/components/structures/RoomSearch.tsx b/src/components/structures/RoomSearch.tsx
index a64feed42c..34682877e0 100644
--- a/src/components/structures/RoomSearch.tsx
+++ b/src/components/structures/RoomSearch.tsx
@@ -17,6 +17,8 @@ limitations under the License.
import * as React from "react";
import { createRef } from "react";
import classNames from "classnames";
+import { Room } from "matrix-js-sdk/src/models/room";
+
import defaultDispatcher from "../../dispatcher/dispatcher";
import { _t } from "../../languageHandler";
import { ActionPayload } from "../../dispatcher/payloads";
@@ -26,7 +28,7 @@ import RoomListStore from "../../stores/room-list/RoomListStore";
import { NameFilterCondition } from "../../stores/room-list/filters/NameFilterCondition";
import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager";
import {replaceableComponent} from "../../utils/replaceableComponent";
-import SpaceStore, {UPDATE_SELECTED_SPACE} from "../../stores/SpaceStore";
+import SpaceStore, {UPDATE_SELECTED_SPACE, UPDATE_TOP_LEVEL_SPACES} from "../../stores/SpaceStore";
interface IProps {
isMinimized: boolean;
@@ -40,6 +42,7 @@ interface IProps {
interface IState {
query: string;
focused: boolean;
+ inSpaces: boolean;
}
@replaceableComponent("structures.RoomSearch")
@@ -54,11 +57,13 @@ export default class RoomSearch extends React.PureComponent {
this.state = {
query: "",
focused: false,
+ inSpaces: false,
};
this.dispatcherRef = defaultDispatcher.register(this.onAction);
// clear filter when changing spaces, in future we may wish to maintain a filter per-space
SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.clearInput);
+ SpaceStore.instance.on(UPDATE_TOP_LEVEL_SPACES, this.onSpaces);
}
public componentDidUpdate(prevProps: Readonly, prevState: Readonly): void {
@@ -79,8 +84,15 @@ export default class RoomSearch extends React.PureComponent {
public componentWillUnmount() {
defaultDispatcher.unregister(this.dispatcherRef);
SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.clearInput);
+ SpaceStore.instance.off(UPDATE_TOP_LEVEL_SPACES, this.onSpaces);
}
+ private onSpaces = (spaces: Room[]) => {
+ this.setState({
+ inSpaces: spaces.length > 0,
+ });
+ };
+
private onAction = (payload: ActionPayload) => {
if (payload.action === 'view_room' && payload.clear_search) {
this.clearInput();
@@ -152,6 +164,11 @@ export default class RoomSearch extends React.PureComponent {
'mx_RoomSearch_inputExpanded': this.state.query || this.state.focused,
});
+ let placeholder = _t("Filter");
+ if (this.state.inSpaces) {
+ placeholder = _t("Filter all spaces");
+ }
+
let icon = (
);
@@ -165,7 +182,7 @@ export default class RoomSearch extends React.PureComponent {
onBlur={this.onBlur}
onChange={this.onChange}
onKeyDown={this.onKeyDown}
- placeholder={_t("Filter")}
+ placeholder={placeholder}
autoComplete="off"
/>
);
diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js
index 38e3cd97e8..b2f0c70bd7 100644
--- a/src/components/structures/RoomStatusBar.js
+++ b/src/components/structures/RoomStatusBar.js
@@ -200,20 +200,22 @@ export default class RoomStatusBar extends React.Component {
} else if (resourceLimitError) {
title = messageForResourceLimitError(
resourceLimitError.data.limit_type,
- resourceLimitError.data.admin_contact, {
- 'monthly_active_user': _td(
- "Your message wasn't sent because this homeserver has hit its Monthly Active User Limit. " +
- "Please contact your service administrator to continue using the service.",
- ),
- 'hs_disabled': _td(
- "Your message wasn't sent because this homeserver has been blocked by it's administrator. " +
- "Please contact your service administrator to continue using the service.",
- ),
- '': _td(
- "Your message wasn't sent because this homeserver has exceeded a resource limit. " +
- "Please contact your service administrator to continue using the service.",
- ),
- });
+ resourceLimitError.data.admin_contact,
+ {
+ 'monthly_active_user': _td(
+ "Your message wasn't sent because this homeserver has hit its Monthly Active User Limit. " +
+ "Please contact your service administrator to continue using the service.",
+ ),
+ 'hs_disabled': _td(
+ "Your message wasn't sent because this homeserver has been blocked by it's administrator. " +
+ "Please contact your service administrator to continue using the service.",
+ ),
+ '': _td(
+ "Your message wasn't sent because this homeserver has exceeded a resource limit. " +
+ "Please contact your service administrator to continue using the service.",
+ ),
+ },
+ );
} else {
title = _t('Some of your messages have not been sent');
}
@@ -265,7 +267,7 @@ export default class RoomStatusBar extends React.Component {
+ height="24" title="/!\ " alt="/!\ " />
{_t('Connectivity to the server has been lost.')}
diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx
index 7168b7d139..5108643673 100644
--- a/src/components/structures/RoomView.tsx
+++ b/src/components/structures/RoomView.tsx
@@ -190,6 +190,9 @@ export interface IState {
rejectError?: Error;
hasPinnedWidgets?: boolean;
dragCounter: number;
+ // whether or not a spaces context switch brought us here,
+ // if it did we don't want the room to be marked as read as soon as it is loaded.
+ wasContextSwitch?: boolean;
}
@replaceableComponent("structures.RoomView")
@@ -326,6 +329,7 @@ export default class RoomView extends React.Component {
shouldPeek: this.state.matrixClientIsReady && RoomViewStore.shouldPeek(),
showingPinned: SettingsStore.getValue("PinnedEvents.isOpen", roomId),
showReadReceipts: SettingsStore.getValue("showReadReceipts", roomId),
+ wasContextSwitch: RoomViewStore.getWasContextSwitch(),
};
if (!initial && this.state.shouldPeek && !newState.shouldPeek) {
@@ -2014,6 +2018,7 @@ export default class RoomView extends React.Component {
timelineSet={this.state.room.getUnfilteredTimelineSet()}
showReadReceipts={this.state.showReadReceipts}
manageReadReceipts={!this.state.isPeeking}
+ sendReadReceiptOnLoad={!this.state.wasContextSwitch}
manageReadMarkers={!this.state.isPeeking}
hidden={hideMessagePanel}
highlightedEventId={highlightedEventId}
diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js
index a014a6e4fe..5c5062633d 100644
--- a/src/components/structures/ScrollPanel.js
+++ b/src/components/structures/ScrollPanel.js
@@ -884,16 +884,20 @@ export default class ScrollPanel extends React.Component {
// give the an explicit role=list because Safari+VoiceOver seems to think an ordered-list with
// list-style-type: none; is no longer a list
- return (
- { this.props.fixedChildren }
-
diff --git a/src/components/views/dialogs/SessionRestoreErrorDialog.js b/src/components/views/dialogs/SessionRestoreErrorDialog.js
index 50d7fbea09..43e73a2f83 100644
--- a/src/components/views/dialogs/SessionRestoreErrorDialog.js
+++ b/src/components/views/dialogs/SessionRestoreErrorDialog.js
@@ -98,7 +98,7 @@ export default class SessionRestoreErrorDialog extends React.Component {
"may be incompatible with this version. Close this window and return " +
"to the more recent version.",
{ brand },
- ) }
+ ) }
{ _t(
"Clearing your browser's storage may fix the problem, but will sign you " +
diff --git a/src/components/views/dialogs/StorageEvictedDialog.js b/src/components/views/dialogs/StorageEvictedDialog.js
index 15c5347644..1e17ab1738 100644
--- a/src/components/views/dialogs/StorageEvictedDialog.js
+++ b/src/components/views/dialogs/StorageEvictedDialog.js
@@ -45,10 +45,12 @@ export default class StorageEvictedDialog extends React.Component {
let logRequest;
if (SdkConfig.get().bug_report_endpoint_url) {
logRequest = _t(
- "To help us prevent this in future, please send us logs.", {},
- {
- a: text => {text},
- });
+ "To help us prevent this in future, please send us logs.",
+ {},
+ {
+ a: text => {text},
+ },
+ );
}
return (
diff --git a/src/components/views/dialogs/UserSettingsDialog.js b/src/components/views/dialogs/UserSettingsDialog.js
index eb9eaeb5dd..e7f6953589 100644
--- a/src/components/views/dialogs/UserSettingsDialog.js
+++ b/src/components/views/dialogs/UserSettingsDialog.js
@@ -155,8 +155,12 @@ export default class UserSettingsDialog extends React.Component {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
return (
-
+
diff --git a/src/components/views/dialogs/VerificationRequestDialog.js b/src/components/views/dialogs/VerificationRequestDialog.js
index 205597a1c4..9281275e6a 100644
--- a/src/components/views/dialogs/VerificationRequestDialog.js
+++ b/src/components/views/dialogs/VerificationRequestDialog.js
@@ -52,11 +52,13 @@ export default class VerificationRequestDialog extends React.Component {
const title = request && request.isSelfVerification ?
_t("Verify other login") : _t("Verification Request");
- return
+ return
+
{_t("The widget will verify your user ID, but won't be able to perform actions for you:")}
diff --git a/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js b/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js
index 43fb25f152..e71983b074 100644
--- a/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js
+++ b/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js
@@ -40,10 +40,11 @@ export default class ConfirmDestroyCrossSigningDialog extends React.Component {
return (
+ className='mx_ConfirmDestroyCrossSigningDialog'
+ hasCancel={true}
+ onFinished={this.props.onFinished}
+ title={_t("Destroy cross-signing keys?")}
+ >
{_t(
diff --git a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js
index 1fafe03d95..4ac15ab5a3 100644
--- a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js
+++ b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js
@@ -373,21 +373,24 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
{_t(
"If you've forgotten your Security Phrase you can "+
"use your Security Key or " +
- "set up new recovery options"
- , {}, {
- button1: s =>
- {s}
- ,
- button2: s =>
- {s}
- ,
- })}
+ "set up new recovery options",
+ {},
+ {
+ button1: s =>
+ {s}
+ ,
+ button2: s =>
+ {s}
+ ,
+ })}
;
} else {
title = _t("Enter Security Key");
@@ -435,15 +438,17 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
{_t(
"If you've forgotten your Security Key you can "+
- ""
- , {}, {
- button: s =>
- {s}
- ,
- })}
+ "",
+ {},
+ {
+ button: s =>
+ {s}
+ ,
+ },
+ )}