Merge remote-tracking branch 'origin/develop' into jryans/id-change-red
commit
a3555cacea
156
CHANGELOG.md
156
CHANGELOG.md
|
@ -1,3 +1,159 @@
|
|||
Changes in [2.3.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.3.0) (2020-03-30)
|
||||
===================================================================================================
|
||||
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.3.0-rc.1...v2.3.0)
|
||||
|
||||
* Upgrade JS SDK to 5.2.0
|
||||
|
||||
Changes in [2.3.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.3.0-rc.1) (2020-03-26)
|
||||
=============================================================================================================
|
||||
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.3...v2.3.0-rc.1)
|
||||
|
||||
* Upgrade JS SDK to 5.2.0-rc.1
|
||||
* Add a flag to control whether cross-signing signatures are trusted
|
||||
[\#4277](https://github.com/matrix-org/matrix-react-sdk/pull/4277)
|
||||
* Update from Weblate
|
||||
[\#4282](https://github.com/matrix-org/matrix-react-sdk/pull/4282)
|
||||
* Update copy on SSSS symmetric upgrade toast
|
||||
[\#4281](https://github.com/matrix-org/matrix-react-sdk/pull/4281)
|
||||
* Wait for SSSS upgrade to complete
|
||||
[\#4270](https://github.com/matrix-org/matrix-react-sdk/pull/4270)
|
||||
* Update cross-signing verification copy and fix i18n
|
||||
[\#4278](https://github.com/matrix-org/matrix-react-sdk/pull/4278)
|
||||
* Fix soft-crash on bad permalinks
|
||||
[\#4280](https://github.com/matrix-org/matrix-react-sdk/pull/4280)
|
||||
* Fix: make self-verification wait for incoming request
|
||||
[\#4267](https://github.com/matrix-org/matrix-react-sdk/pull/4267)
|
||||
* Fall back to non-standard persisted api for Safari
|
||||
[\#4272](https://github.com/matrix-org/matrix-react-sdk/pull/4272)
|
||||
* Respond to backup key sharing requests
|
||||
[\#4275](https://github.com/matrix-org/matrix-react-sdk/pull/4275)
|
||||
* Log and display secret sharing cache state
|
||||
[\#4268](https://github.com/matrix-org/matrix-react-sdk/pull/4268)
|
||||
* Support sending config and ready events to capable widgets (Jitsi)
|
||||
[\#4266](https://github.com/matrix-org/matrix-react-sdk/pull/4266)
|
||||
* If cached keys are present in the key backup dialog, use them
|
||||
[\#4273](https://github.com/matrix-org/matrix-react-sdk/pull/4273)
|
||||
* Fix formatbar not hidden on highlighted message sent
|
||||
[\#4265](https://github.com/matrix-org/matrix-react-sdk/pull/4265)
|
||||
* Support Jitsi conferences sent/received on Riot Mobile and older Riot Webs
|
||||
[\#4252](https://github.com/matrix-org/matrix-react-sdk/pull/4252)
|
||||
* Use unified function to check cross-signing is ready
|
||||
[\#4263](https://github.com/matrix-org/matrix-react-sdk/pull/4263)
|
||||
* Migrate SSSS to symmetric
|
||||
[\#4224](https://github.com/matrix-org/matrix-react-sdk/pull/4224)
|
||||
* Migration to symmetric SSSS
|
||||
[\#4242](https://github.com/matrix-org/matrix-react-sdk/pull/4242)
|
||||
* Always display verification request toasts on top
|
||||
[\#4262](https://github.com/matrix-org/matrix-react-sdk/pull/4262)
|
||||
* Fix: assume SAS is supported when starting request with .start
|
||||
[\#4249](https://github.com/matrix-org/matrix-react-sdk/pull/4249)
|
||||
* Fix logout when Olm failed to load.
|
||||
[\#4261](https://github.com/matrix-org/matrix-react-sdk/pull/4261)
|
||||
* Improve naming of Jitsi conferences
|
||||
[\#4251](https://github.com/matrix-org/matrix-react-sdk/pull/4251)
|
||||
* Handle matrix.to user permalink in-room rather than solo
|
||||
[\#4245](https://github.com/matrix-org/matrix-react-sdk/pull/4245)
|
||||
* Fix: filter room list (again) by canonical and alternative aliases
|
||||
[\#4260](https://github.com/matrix-org/matrix-react-sdk/pull/4260)
|
||||
* EventIndex: Add some logging to the file panel populating.
|
||||
[\#4250](https://github.com/matrix-org/matrix-react-sdk/pull/4250)
|
||||
* Update from Weblate
|
||||
[\#4259](https://github.com/matrix-org/matrix-react-sdk/pull/4259)
|
||||
* Migrate RoomView to React Contexts in the hope for better temporal stability
|
||||
[\#4258](https://github.com/matrix-org/matrix-react-sdk/pull/4258)
|
||||
* Update WidgetUtils.js fix Jitsi path
|
||||
[\#4256](https://github.com/matrix-org/matrix-react-sdk/pull/4256)
|
||||
* Fix local jitsi build url fail and missing argument
|
||||
[\#4255](https://github.com/matrix-org/matrix-react-sdk/pull/4255)
|
||||
* Add shortcut CmdOrCtrl+. to toggle right panel
|
||||
[\#4244](https://github.com/matrix-org/matrix-react-sdk/pull/4244)
|
||||
* Improve Keyboard Shortcuts. Add alt-arrows & alt-shift-arrows
|
||||
[\#4241](https://github.com/matrix-org/matrix-react-sdk/pull/4241)
|
||||
* Bring back legacy verification by comparing public device keys
|
||||
[\#4240](https://github.com/matrix-org/matrix-react-sdk/pull/4240)
|
||||
* Searching: Return an empty result if the search term is an empty string.
|
||||
[\#4248](https://github.com/matrix-org/matrix-react-sdk/pull/4248)
|
||||
* Break continuation on showHiddenEvents-rendered events
|
||||
[\#4247](https://github.com/matrix-org/matrix-react-sdk/pull/4247)
|
||||
* Watch for show-RR settings changes, use room-specific and fix margins
|
||||
[\#4246](https://github.com/matrix-org/matrix-react-sdk/pull/4246)
|
||||
* Register Mac electron specific Cmd+, shortcut to User Settings
|
||||
[\#4243](https://github.com/matrix-org/matrix-react-sdk/pull/4243)
|
||||
* Use a local wrapper for Jitsi calls
|
||||
[\#4234](https://github.com/matrix-org/matrix-react-sdk/pull/4234)
|
||||
* Invite Dialog fixes
|
||||
[\#4233](https://github.com/matrix-org/matrix-react-sdk/pull/4233)
|
||||
* RoomPreviewBar word-break the sender name too
|
||||
[\#4239](https://github.com/matrix-org/matrix-react-sdk/pull/4239)
|
||||
* Report to the user when a key signature upload fails
|
||||
[\#4229](https://github.com/matrix-org/matrix-react-sdk/pull/4229)
|
||||
* pre-send megolm keys when possible when a user starts typing
|
||||
[\#4235](https://github.com/matrix-org/matrix-react-sdk/pull/4235)
|
||||
* we don't do mx_fadable anymore so get rid of broken RightPanel disabling
|
||||
[\#4238](https://github.com/matrix-org/matrix-react-sdk/pull/4238)
|
||||
* Fix left left panel overflowing vertically
|
||||
[\#4237](https://github.com/matrix-org/matrix-react-sdk/pull/4237)
|
||||
* Fix custom tags causing left panel to over-expand
|
||||
[\#4236](https://github.com/matrix-org/matrix-react-sdk/pull/4236)
|
||||
* Add Keyboard shortcuts dialog
|
||||
[\#4231](https://github.com/matrix-org/matrix-react-sdk/pull/4231)
|
||||
* Don't use buildkite agent to upload logs
|
||||
[\#4232](https://github.com/matrix-org/matrix-react-sdk/pull/4232)
|
||||
* Remove Gemini Scrollbars
|
||||
[\#4217](https://github.com/matrix-org/matrix-react-sdk/pull/4217)
|
||||
* Room Directory Explore Servers redesign
|
||||
[\#4209](https://github.com/matrix-org/matrix-react-sdk/pull/4209)
|
||||
* Fix redo keyboard shortcut on macOS
|
||||
[\#4110](https://github.com/matrix-org/matrix-react-sdk/pull/4110)
|
||||
* Fix: ensure local state for aliases doesn't get garbled up
|
||||
[\#4230](https://github.com/matrix-org/matrix-react-sdk/pull/4230)
|
||||
* Rename 'jump to bottom' to avoid ublock block
|
||||
[\#4208](https://github.com/matrix-org/matrix-react-sdk/pull/4208)
|
||||
* Restore key backup in background after complete security
|
||||
[\#4225](https://github.com/matrix-org/matrix-react-sdk/pull/4225)
|
||||
* Fix key backup trust text for cross-signing
|
||||
[\#4223](https://github.com/matrix-org/matrix-react-sdk/pull/4223)
|
||||
* Add default on config setting to control call button in composer
|
||||
[\#4227](https://github.com/matrix-org/matrix-react-sdk/pull/4227)
|
||||
* Fix: make alternative addresses UX less confusing
|
||||
[\#4221](https://github.com/matrix-org/matrix-react-sdk/pull/4221)
|
||||
* Wait for verification request on login
|
||||
[\#4222](https://github.com/matrix-org/matrix-react-sdk/pull/4222)
|
||||
* EventIndex: Add support to delete events from the index.
|
||||
[\#4204](https://github.com/matrix-org/matrix-react-sdk/pull/4204)
|
||||
* EventIndex: Remove a checkpoint if the HTTP request returns a 403.
|
||||
[\#4214](https://github.com/matrix-org/matrix-react-sdk/pull/4214)
|
||||
* Move to composer when typing letters with Shift held
|
||||
[\#4216](https://github.com/matrix-org/matrix-react-sdk/pull/4216)
|
||||
* Wrap large room names when previewing them
|
||||
[\#4213](https://github.com/matrix-org/matrix-react-sdk/pull/4213)
|
||||
* Rename Review Devices to Review Sessions
|
||||
[\#4219](https://github.com/matrix-org/matrix-react-sdk/pull/4219)
|
||||
* Fix typo in tabIndex to make React happy
|
||||
[\#4215](https://github.com/matrix-org/matrix-react-sdk/pull/4215)
|
||||
* Proof of concept for custom theme adding
|
||||
[\#4148](https://github.com/matrix-org/matrix-react-sdk/pull/4148)
|
||||
* Remove stuff that yarn install doesn't think we need
|
||||
[\#4205](https://github.com/matrix-org/matrix-react-sdk/pull/4205)
|
||||
* Declare jsx in tsconfig for IDEs
|
||||
[\#4207](https://github.com/matrix-org/matrix-react-sdk/pull/4207)
|
||||
* Fix: best-effort to join room without canonical alias over federation from
|
||||
room directory
|
||||
[\#4210](https://github.com/matrix-org/matrix-react-sdk/pull/4210)
|
||||
* Test for cross-signing homeserver support during login, toasts
|
||||
[\#4206](https://github.com/matrix-org/matrix-react-sdk/pull/4206)
|
||||
* Send verification request to a single device in a way compatible with non-
|
||||
cross-signing
|
||||
[\#4202](https://github.com/matrix-org/matrix-react-sdk/pull/4202)
|
||||
* Fixes for removing local alias
|
||||
[\#4199](https://github.com/matrix-org/matrix-react-sdk/pull/4199)
|
||||
* yarn upgrade
|
||||
[\#4201](https://github.com/matrix-org/matrix-react-sdk/pull/4201)
|
||||
* Support TypeScript for React components
|
||||
[\#4203](https://github.com/matrix-org/matrix-react-sdk/pull/4203)
|
||||
* When room name is changed, show both the old and new name
|
||||
[\#4183](https://github.com/matrix-org/matrix-react-sdk/pull/4183)
|
||||
|
||||
Changes in [2.2.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.3) (2020-03-17)
|
||||
===================================================================================================
|
||||
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.3-rc.1...v2.2.3)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "matrix-react-sdk",
|
||||
"version": "2.2.3",
|
||||
"version": "2.3.0",
|
||||
"description": "SDK for matrix.org using React",
|
||||
"author": "matrix.org",
|
||||
"repository": {
|
||||
|
|
|
@ -14,28 +14,31 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_AutoHideScrollbar {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
overflow-y: overlay; // where supported
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 3px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
scrollbar-color: transparent transparent;
|
||||
// make any scrollbar grey and thin
|
||||
html {
|
||||
scrollbar-color: $scrollbar-thumb-color $scrollbar-track-color;
|
||||
}
|
||||
// scrollbar-width is not inherited (but -color is, why?!),
|
||||
// so declare it on every element
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background-color: $scrollbar-track-color;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 3px;
|
||||
background-color: $scrollbar-thumb-color;
|
||||
}
|
||||
|
||||
// make auto-hide scrollbars not transparent again on hover
|
||||
.mx_AutoHideScrollbar:hover {
|
||||
scrollbar-color: $scrollbar-thumb-color $scrollbar-track-color;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
background-color: $scrollbar-track-color;
|
||||
}
|
||||
|
@ -43,5 +46,22 @@ limitations under the License.
|
|||
&::-webkit-scrollbar-thumb {
|
||||
background-color: $scrollbar-thumb-color;
|
||||
}
|
||||
scrollbar-color: $scrollbar-thumb-color $scrollbar-track-color;
|
||||
}
|
||||
|
||||
// make scrollbars transparent for autohide scrollbars
|
||||
.mx_AutoHideScrollbar {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
overflow-y: overlay; // where supported
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
scrollbar-color: transparent transparent;
|
||||
}
|
||||
|
|
|
@ -216,19 +216,19 @@ export async function promptForBackupPassphrase() {
|
|||
*
|
||||
* @param {Function} [func] An operation to perform once secret storage has been
|
||||
* bootstrapped. Optional.
|
||||
* @param {bool} [force] Reset secret storage even if it's already set up
|
||||
* @param {bool} [forceReset] Reset secret storage even if it's already set up
|
||||
*/
|
||||
export async function accessSecretStorage(func = async () => { }, force = false) {
|
||||
export async function accessSecretStorage(func = async () => { }, forceReset = false) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
secretStorageBeingAccessed = true;
|
||||
try {
|
||||
if (!await cli.hasSecretStorageKey() || force) {
|
||||
if (!await cli.hasSecretStorageKey() || forceReset) {
|
||||
// This dialog calls bootstrap itself after guiding the user through
|
||||
// passphrase creation.
|
||||
const { finished } = Modal.createTrackedDialogAsync('Create Secret Storage dialog', '',
|
||||
import("./async-components/views/dialogs/secretstorage/CreateSecretStorageDialog"),
|
||||
{
|
||||
force,
|
||||
force: forceReset,
|
||||
},
|
||||
null, /* priority = */ false, /* static = */ true,
|
||||
);
|
||||
|
|
|
@ -119,89 +119,85 @@ export default class DeviceListener {
|
|||
|
||||
const crossSigningReady = await cli.isCrossSigningReady();
|
||||
|
||||
if (!crossSigningReady) {
|
||||
if (this._dismissedThisDeviceToast) {
|
||||
ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY);
|
||||
return;
|
||||
}
|
||||
|
||||
// cross signing isn't enabled - nag to enable it
|
||||
// There are 3 different toasts for:
|
||||
if (cli.getStoredCrossSigningForUser(cli.getUserId())) {
|
||||
// Cross-signing on account but this device doesn't trust the master key (verify this session)
|
||||
ToastStore.sharedInstance().addOrReplaceToast({
|
||||
key: THIS_DEVICE_TOAST_KEY,
|
||||
title: _t("Verify this session"),
|
||||
icon: "verification_warning",
|
||||
props: {kind: 'verify_this_session'},
|
||||
component: sdk.getComponent("toasts.SetupEncryptionToast"),
|
||||
});
|
||||
} else {
|
||||
const backupInfo = await this._getKeyBackupInfo();
|
||||
if (backupInfo) {
|
||||
// No cross-signing on account but key backup available (upgrade encryption)
|
||||
if (this._dismissedThisDeviceToast) {
|
||||
ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY);
|
||||
} else {
|
||||
if (!crossSigningReady) {
|
||||
// cross signing isn't enabled - nag to enable it
|
||||
// There are 3 different toasts for:
|
||||
if (cli.getStoredCrossSigningForUser(cli.getUserId())) {
|
||||
// Cross-signing on account but this device doesn't trust the master key (verify this session)
|
||||
ToastStore.sharedInstance().addOrReplaceToast({
|
||||
key: THIS_DEVICE_TOAST_KEY,
|
||||
title: _t("Encryption upgrade available"),
|
||||
title: _t("Verify this session"),
|
||||
icon: "verification_warning",
|
||||
props: {kind: 'upgrade_encryption'},
|
||||
props: {kind: 'verify_this_session'},
|
||||
component: sdk.getComponent("toasts.SetupEncryptionToast"),
|
||||
});
|
||||
} else {
|
||||
// No cross-signing or key backup on account (set up encryption)
|
||||
const backupInfo = await this._getKeyBackupInfo();
|
||||
if (backupInfo) {
|
||||
// No cross-signing on account but key backup available (upgrade encryption)
|
||||
ToastStore.sharedInstance().addOrReplaceToast({
|
||||
key: THIS_DEVICE_TOAST_KEY,
|
||||
title: _t("Encryption upgrade available"),
|
||||
icon: "verification_warning",
|
||||
props: {kind: 'upgrade_encryption'},
|
||||
component: sdk.getComponent("toasts.SetupEncryptionToast"),
|
||||
});
|
||||
} else {
|
||||
// No cross-signing or key backup on account (set up encryption)
|
||||
ToastStore.sharedInstance().addOrReplaceToast({
|
||||
key: THIS_DEVICE_TOAST_KEY,
|
||||
title: _t("Set up encryption"),
|
||||
icon: "verification_warning",
|
||||
props: {kind: 'set_up_encryption'},
|
||||
component: sdk.getComponent("toasts.SetupEncryptionToast"),
|
||||
});
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (await cli.secretStorageKeyNeedsUpgrade()) {
|
||||
ToastStore.sharedInstance().addOrReplaceToast({
|
||||
key: THIS_DEVICE_TOAST_KEY,
|
||||
title: _t("Encryption upgrade available"),
|
||||
icon: "verification_warning",
|
||||
props: {kind: 'upgrade_ssss'},
|
||||
component: sdk.getComponent("toasts.SetupEncryptionToast"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// as long as cross-signing isn't ready,
|
||||
// you can't see or dismiss any device toasts
|
||||
if (crossSigningReady) {
|
||||
const newActiveToasts = new Set();
|
||||
|
||||
const devices = await cli.getStoredDevicesForUser(cli.getUserId());
|
||||
for (const device of devices) {
|
||||
if (device.deviceId == cli.deviceId) continue;
|
||||
|
||||
const deviceTrust = await cli.checkDeviceTrust(cli.getUserId(), device.deviceId);
|
||||
if (deviceTrust.isCrossSigningVerified() || this._dismissed.has(device.deviceId)) {
|
||||
ToastStore.sharedInstance().dismissToast(toastKey(device.deviceId));
|
||||
} else {
|
||||
this._activeNagToasts.add(device.deviceId);
|
||||
ToastStore.sharedInstance().addOrReplaceToast({
|
||||
key: THIS_DEVICE_TOAST_KEY,
|
||||
title: _t("Set up encryption"),
|
||||
key: toastKey(device.deviceId),
|
||||
title: _t("Unverified login. Was this you?"),
|
||||
icon: "verification_warning",
|
||||
props: {kind: 'set_up_encryption'},
|
||||
component: sdk.getComponent("toasts.SetupEncryptionToast"),
|
||||
props: { device },
|
||||
component: sdk.getComponent("toasts.UnverifiedSessionToast"),
|
||||
});
|
||||
newActiveToasts.add(device.deviceId);
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (await cli.secretStorageKeyNeedsUpgrade()) {
|
||||
if (this._dismissedThisDeviceToast) {
|
||||
ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY);
|
||||
return;
|
||||
|
||||
// clear any other outstanding toasts (eg. logged out devices)
|
||||
for (const deviceId of this._activeNagToasts) {
|
||||
if (!newActiveToasts.has(deviceId)) ToastStore.sharedInstance().dismissToast(toastKey(deviceId));
|
||||
}
|
||||
|
||||
ToastStore.sharedInstance().addOrReplaceToast({
|
||||
key: THIS_DEVICE_TOAST_KEY,
|
||||
title: _t("Encryption upgrade available"),
|
||||
icon: "verification_warning",
|
||||
props: {kind: 'upgrade_ssss'},
|
||||
component: sdk.getComponent("toasts.SetupEncryptionToast"),
|
||||
});
|
||||
} else {
|
||||
ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY);
|
||||
this._activeNagToasts = newActiveToasts;
|
||||
}
|
||||
|
||||
const newActiveToasts = new Set();
|
||||
|
||||
const devices = await cli.getStoredDevicesForUser(cli.getUserId());
|
||||
for (const device of devices) {
|
||||
if (device.deviceId == cli.deviceId) continue;
|
||||
|
||||
const deviceTrust = await cli.checkDeviceTrust(cli.getUserId(), device.deviceId);
|
||||
if (deviceTrust.isCrossSigningVerified() || this._dismissed.has(device.deviceId)) {
|
||||
ToastStore.sharedInstance().dismissToast(toastKey(device.deviceId));
|
||||
} else {
|
||||
this._activeNagToasts.add(device.deviceId);
|
||||
ToastStore.sharedInstance().addOrReplaceToast({
|
||||
key: toastKey(device.deviceId),
|
||||
title: _t("Unverified login. Was this you?"),
|
||||
icon: "verification_warning",
|
||||
props: { device },
|
||||
component: sdk.getComponent("toasts.UnverifiedSessionToast"),
|
||||
});
|
||||
newActiveToasts.add(device.deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
// clear any other outstanding toasts (eg. logged out devices)
|
||||
for (const deviceId of this._activeNagToasts) {
|
||||
if (!newActiveToasts.has(deviceId)) ToastStore.sharedInstance().dismissToast(toastKey(deviceId));
|
||||
}
|
||||
this._activeNagToasts = newActiveToasts;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,6 +118,11 @@ const shortcuts: Record<Categories, IShortcut[]> = {
|
|||
key: Key.ARROW_DOWN,
|
||||
}],
|
||||
description: _td("Navigate composer history"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
key: Key.ESCAPE,
|
||||
}],
|
||||
description: _td("Cancel replying to a message"),
|
||||
},
|
||||
],
|
||||
|
||||
|
|
|
@ -168,7 +168,6 @@ export default class ManageEventIndexDialog extends React.Component {
|
|||
totalRooms: formatCountLong(this.state.roomCount),
|
||||
})} <br />
|
||||
<Field
|
||||
id={"crawlerSleepTimeMs"}
|
||||
label={_t('Message downloading sleep time(ms)')}
|
||||
type='number'
|
||||
value={this.state.crawlerSleepTime}
|
||||
|
|
|
@ -412,7 +412,6 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
|||
<div>{_t("Enter your account password to confirm the upgrade:")}</div>
|
||||
<div><Field
|
||||
type="password"
|
||||
id="mx_CreateSecretStorage_accountPassword"
|
||||
label={_t("Password")}
|
||||
value={this.state.accountPassword}
|
||||
onChange={this._onAccountPasswordChange}
|
||||
|
@ -497,7 +496,6 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
|||
<div className="mx_CreateSecretStorageDialog_passPhraseContainer">
|
||||
<Field
|
||||
type="password"
|
||||
id="mx_CreateSecretStorageDialog_passPhraseField"
|
||||
className="mx_CreateSecretStorageDialog_passPhraseField"
|
||||
onChange={this._onPassPhraseChange}
|
||||
value={this.state.passPhrase}
|
||||
|
@ -574,7 +572,6 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
|||
<div className="mx_CreateSecretStorageDialog_passPhraseContainer">
|
||||
<Field
|
||||
type="password"
|
||||
id="mx_CreateSecretStorageDialog_passPhraseField"
|
||||
onChange={this._onPassPhraseConfirmChange}
|
||||
value={this.state.passPhraseConfirm}
|
||||
className="mx_CreateSecretStorageDialog_passPhraseField"
|
||||
|
|
|
@ -657,6 +657,7 @@ export default createReactClass({
|
|||
collapseLhs: true,
|
||||
});
|
||||
break;
|
||||
case 'focus_room_filter': // for CtrlOrCmd+K to work by expanding the left panel first
|
||||
case 'show_left_panel':
|
||||
this.setState({
|
||||
collapseLhs: false,
|
||||
|
|
|
@ -55,7 +55,7 @@ import RightPanelStore from "../../stores/RightPanelStore";
|
|||
import {haveTileForEvent} from "../views/rooms/EventTile";
|
||||
import RoomContext from "../../contexts/RoomContext";
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import { shieldStatusForMembership } from '../../utils/ShieldUtils';
|
||||
import { shieldStatusForRoom } from '../../utils/ShieldUtils';
|
||||
|
||||
const DEBUG = false;
|
||||
let debuglog = function() {};
|
||||
|
@ -820,7 +820,7 @@ export default createReactClass({
|
|||
|
||||
/* At this point, the user has encryption on and cross-signing on */
|
||||
this.setState({
|
||||
e2eStatus: await shieldStatusForMembership(this.context, room),
|
||||
e2eStatus: await shieldStatusForRoom(this.context, room),
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import * as React from "react";
|
|||
import {_t} from '../../languageHandler';
|
||||
import * as PropTypes from "prop-types";
|
||||
import * as sdk from "../../index";
|
||||
import AutoHideScrollbar from './AutoHideScrollbar';
|
||||
import { ReactNode } from "react";
|
||||
|
||||
/**
|
||||
|
@ -113,9 +114,9 @@ export default class TabbedView extends React.Component<IProps, IState> {
|
|||
private _renderTabPanel(tab: Tab): React.ReactNode {
|
||||
return (
|
||||
<div className="mx_TabbedView_tabPanel" key={"mx_tabpanel_" + tab.label}>
|
||||
<div className='mx_TabbedView_tabPanelContent'>
|
||||
<AutoHideScrollbar className='mx_TabbedView_tabPanelContent'>
|
||||
{tab.body}
|
||||
</div>
|
||||
</AutoHideScrollbar>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -296,7 +296,6 @@ export default createReactClass({
|
|||
<form onSubmit={this.onSubmitForm}>
|
||||
<div className="mx_AuthBody_fieldRow">
|
||||
<Field
|
||||
id="mx_ForgotPassword_email"
|
||||
name="reset_email" // define a name so browser's password autofill gets less confused
|
||||
type="text"
|
||||
label={_t('Email')}
|
||||
|
@ -307,7 +306,6 @@ export default createReactClass({
|
|||
</div>
|
||||
<div className="mx_AuthBody_fieldRow">
|
||||
<Field
|
||||
id="mx_ForgotPassword_password"
|
||||
name="reset_password"
|
||||
type="password"
|
||||
label={_t('Password')}
|
||||
|
@ -315,7 +313,6 @@ export default createReactClass({
|
|||
onChange={this.onInputChanged.bind(this, "password")}
|
||||
/>
|
||||
<Field
|
||||
id="mx_ForgotPassword_passwordConfirm"
|
||||
name="reset_password_confirm"
|
||||
type="password"
|
||||
label={_t('Confirm')}
|
||||
|
|
|
@ -213,7 +213,6 @@ export default class SoftLogout extends React.Component {
|
|||
<p>{introText}</p>
|
||||
{error}
|
||||
<Field
|
||||
id="softlogout_password"
|
||||
type="password"
|
||||
label={_t("Password")}
|
||||
onChange={this.onPasswordChange}
|
||||
|
|
|
@ -145,7 +145,6 @@ export const PasswordAuthEntry = createReactClass({
|
|||
<p>{ _t("Confirm your identity by entering your account password below.") }</p>
|
||||
<form onSubmit={this._onSubmit} className="mx_InteractiveAuthEntryComponents_passwordSection">
|
||||
<Field
|
||||
id="mx_InteractiveAuthEntryComponents_password"
|
||||
className={passwordBoxClass}
|
||||
type="password"
|
||||
name="passwordField"
|
||||
|
|
|
@ -106,7 +106,8 @@ export default class ModularServerConfig extends ServerConfig {
|
|||
)}
|
||||
<form onSubmit={this.onSubmit} autoComplete="off" action={null}>
|
||||
<div className="mx_ServerConfig_fields">
|
||||
<Field id="mx_ServerConfig_hsUrl"
|
||||
<Field
|
||||
id="mx_ServerConfig_hsUrl"
|
||||
label={_t("Server Name")}
|
||||
placeholder={this.props.serverConfig.hsUrl}
|
||||
value={this.state.hsUrl}
|
||||
|
|
|
@ -193,7 +193,6 @@ export default class PasswordLogin extends React.Component {
|
|||
classes.error = this.props.loginIncorrect && !this.state.username;
|
||||
return <Field
|
||||
className={classNames(classes)}
|
||||
id="mx_PasswordLogin_email"
|
||||
name="username" // make it a little easier for browser's remember-password
|
||||
key="email_input"
|
||||
type="text"
|
||||
|
@ -209,7 +208,6 @@ export default class PasswordLogin extends React.Component {
|
|||
classes.error = this.props.loginIncorrect && !this.state.username;
|
||||
return <Field
|
||||
className={classNames(classes)}
|
||||
id="mx_PasswordLogin_username"
|
||||
name="username" // make it a little easier for browser's remember-password
|
||||
key="username_input"
|
||||
type="text"
|
||||
|
@ -233,7 +231,6 @@ export default class PasswordLogin extends React.Component {
|
|||
|
||||
return <Field
|
||||
className={classNames(classes)}
|
||||
id="mx_PasswordLogin_phoneNumber"
|
||||
name="phoneNumber"
|
||||
key="phone_input"
|
||||
type="text"
|
||||
|
@ -290,7 +287,6 @@ export default class PasswordLogin extends React.Component {
|
|||
<div className="mx_Login_type_container">
|
||||
<label className="mx_Login_type_label">{ _t('Sign in with') }</label>
|
||||
<Field
|
||||
id="mx_PasswordLogin_type"
|
||||
element="select"
|
||||
value={this.state.loginType}
|
||||
onChange={this.onLoginTypeChange}
|
||||
|
@ -328,7 +324,6 @@ export default class PasswordLogin extends React.Component {
|
|||
{loginField}
|
||||
<Field
|
||||
className={pwFieldClass}
|
||||
id="mx_PasswordLogin_password"
|
||||
type="password"
|
||||
name="password"
|
||||
label={_t('Password')}
|
||||
|
|
|
@ -470,7 +470,6 @@ export default createReactClass({
|
|||
_t("Email") :
|
||||
_t("Email (optional)");
|
||||
return <Field
|
||||
id="mx_RegistrationForm_email"
|
||||
ref={field => this[FIELD_EMAIL] = field}
|
||||
type="text"
|
||||
label={emailPlaceholder}
|
||||
|
@ -524,7 +523,6 @@ export default createReactClass({
|
|||
onOptionChange={this.onPhoneCountryChange}
|
||||
/>;
|
||||
return <Field
|
||||
id="mx_RegistrationForm_phoneNumber"
|
||||
ref={field => this[FIELD_PHONE_NUMBER] = field}
|
||||
type="text"
|
||||
label={phoneLabel}
|
||||
|
|
|
@ -223,7 +223,8 @@ export default class ServerConfig extends React.PureComponent {
|
|||
{sub}
|
||||
</a>,
|
||||
})}
|
||||
<Field id="mx_ServerConfig_hsUrl"
|
||||
<Field
|
||||
id="mx_ServerConfig_hsUrl"
|
||||
label={_t("Homeserver URL")}
|
||||
placeholder={this.props.serverConfig.hsUrl}
|
||||
value={this.state.hsUrl}
|
||||
|
@ -246,7 +247,7 @@ export default class ServerConfig extends React.PureComponent {
|
|||
{sub}
|
||||
</a>,
|
||||
})}
|
||||
<Field id="mx_ServerConfig_isUrl"
|
||||
<Field
|
||||
label={_t("Identity Server URL")}
|
||||
placeholder={this.props.serverConfig.isUrl}
|
||||
value={this.state.isUrl || ''}
|
||||
|
|
|
@ -166,7 +166,6 @@ export default class BugReportDialog extends React.Component {
|
|||
) }
|
||||
</b></p>
|
||||
<Field
|
||||
id="mx_BugReportDialog_issueUrl"
|
||||
type="text"
|
||||
className="mx_BugReportDialog_field_input"
|
||||
label={_t("GitHub issue")}
|
||||
|
@ -175,7 +174,6 @@ export default class BugReportDialog extends React.Component {
|
|||
placeholder="https://github.com/vector-im/riot-web/issues/..."
|
||||
/>
|
||||
<Field
|
||||
id="mx_BugReportDialog_notes"
|
||||
className="mx_BugReportDialog_field_input"
|
||||
element="textarea"
|
||||
label={_t("Notes")}
|
||||
|
|
|
@ -174,7 +174,7 @@ export default createReactClass({
|
|||
const domain = MatrixClientPeg.get().getDomain();
|
||||
aliasField = (
|
||||
<div className="mx_CreateRoomDialog_aliasContainer">
|
||||
<RoomAliasField id="alias" ref={ref => this._aliasFieldRef = ref} onChange={this.onAliasChange} domain={domain} value={this.state.alias} />
|
||||
<RoomAliasField ref={ref => this._aliasFieldRef = ref} onChange={this.onAliasChange} domain={domain} value={this.state.alias} />
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
|
@ -188,8 +188,8 @@ export default createReactClass({
|
|||
>
|
||||
<form onSubmit={this.onOk} onKeyDown={this._onKeyDown}>
|
||||
<div className="mx_Dialog_content">
|
||||
<Field id="name" ref={ref => this._nameFieldRef = ref} label={ _t('Name') } onChange={this.onNameChange} onValidate={this.onNameValidate} value={this.state.name} className="mx_CreateRoomDialog_name" />
|
||||
<Field id="topic" label={ _t('Topic (optional)') } onChange={this.onTopicChange} value={this.state.topic} />
|
||||
<Field ref={ref => this._nameFieldRef = ref} label={ _t('Name') } onChange={this.onNameChange} onValidate={this.onNameValidate} value={this.state.name} className="mx_CreateRoomDialog_name" />
|
||||
<Field label={ _t('Topic (optional)') } onChange={this.onTopicChange} value={this.state.topic} />
|
||||
<LabelledToggleSwitch label={ _t("Make this room public")} onChange={this.onPublicChange} value={this.state.isPublic} />
|
||||
{ privateLabel }
|
||||
{ publicLabel }
|
||||
|
|
|
@ -174,7 +174,6 @@ export default class DeactivateAccountDialog extends React.Component {
|
|||
|
||||
<p>{ _t("To continue, please enter your password:") }</p>
|
||||
<Field
|
||||
id="mx_DeactivateAccountDialog_password"
|
||||
type="password"
|
||||
label={_t('Password')}
|
||||
onChange={this._onPasswordFieldChange}
|
||||
|
|
|
@ -302,7 +302,7 @@ class FilteredList extends React.PureComponent {
|
|||
render() {
|
||||
const TruncatedList = sdk.getComponent("elements.TruncatedList");
|
||||
return <div>
|
||||
<Field id="DevtoolsDialog_FilteredList_filter" label={_t('Filter results')} autoFocus={true} size={64}
|
||||
<Field label={_t('Filter results')} autoFocus={true} size={64}
|
||||
type="text" autoComplete="off" value={this.props.query} onChange={this.onQuery}
|
||||
className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query"
|
||||
// force re-render so that autoFocus is applied when this component is re-used
|
||||
|
|
|
@ -123,7 +123,6 @@ export default class ReportEventDialog extends PureComponent {
|
|||
</p>
|
||||
{adminMessage}
|
||||
<Field
|
||||
id="mx_ReportEventDialog_reason"
|
||||
className="mx_ReportEventDialog_reason"
|
||||
element="textarea"
|
||||
label={_t("Reason")}
|
||||
|
|
|
@ -116,7 +116,6 @@ export default createReactClass({
|
|||
</div>
|
||||
<div>
|
||||
<Field
|
||||
id="mx_TextInputDialog_field"
|
||||
className="mx_TextInputDialog_input"
|
||||
ref={this._field}
|
||||
type="text"
|
||||
|
|
|
@ -121,7 +121,7 @@ export default class EditableItemList extends React.Component {
|
|||
return (
|
||||
<form onSubmit={this._onItemAdded} autoComplete="off"
|
||||
noValidate={true} className="mx_EditableItemList_newItem">
|
||||
<Field id={`mx_EditableItemList_new_${this.props.id}`} label={this.props.placeholder} type="text"
|
||||
<Field label={this.props.placeholder} type="text"
|
||||
autoComplete="off" value={this.props.newItem || ""} onChange={this._onNewItemChanged}
|
||||
list={this.props.suggestionsListId} />
|
||||
<AccessibleButton onClick={this._onItemAdded} kind="primary" type="submit">
|
||||
|
|
|
@ -23,9 +23,15 @@ import { debounce } from 'lodash';
|
|||
// Invoke validation from user input (when typing, etc.) at most once every N ms.
|
||||
const VALIDATION_THROTTLE_MS = 200;
|
||||
|
||||
const BASE_ID = "mx_Field";
|
||||
let count = 1;
|
||||
function getId() {
|
||||
return `${BASE_ID}_${count++}`;
|
||||
}
|
||||
|
||||
export default class Field extends React.PureComponent {
|
||||
static propTypes = {
|
||||
// The field's ID, which binds the input and label together.
|
||||
// The field's ID, which binds the input and label together. Immutable.
|
||||
id: PropTypes.string.isRequired,
|
||||
// The element to create. Defaults to "input".
|
||||
// To define options for a select, use <Field><option ... /></Field>
|
||||
|
@ -63,13 +69,15 @@ export default class Field extends React.PureComponent {
|
|||
// All other props pass through to the <input>.
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
valid: undefined,
|
||||
feedback: undefined,
|
||||
focused: false,
|
||||
};
|
||||
|
||||
this.id = this.props.id || getId();
|
||||
}
|
||||
|
||||
onFocus = (ev) => {
|
||||
|
@ -167,6 +175,7 @@ export default class Field extends React.PureComponent {
|
|||
inputProps.type = inputProps.type || "text";
|
||||
inputProps.ref = input => this.input = input;
|
||||
inputProps.placeholder = inputProps.placeholder || inputProps.label;
|
||||
inputProps.id = this.id; // this overwrites the id from props
|
||||
|
||||
inputProps.onFocus = this.onFocus;
|
||||
inputProps.onChange = this.onChange;
|
||||
|
@ -211,7 +220,7 @@ export default class Field extends React.PureComponent {
|
|||
return <div className={fieldClasses}>
|
||||
{prefixContainer}
|
||||
{fieldInput}
|
||||
<label htmlFor={this.props.id}>{this.props.label}</label>
|
||||
<label htmlFor={this.id}>{this.props.label}</label>
|
||||
{postfixContainer}
|
||||
{fieldTooltip}
|
||||
</div>;
|
||||
|
|
|
@ -132,7 +132,7 @@ export default createReactClass({
|
|||
const label = typeof this.props.label === "undefined" ? _t("Power level") : this.props.label;
|
||||
if (this.state.custom) {
|
||||
picker = (
|
||||
<Field id={`powerSelector_custom_${this.props.powerLevelKey}`} type="number"
|
||||
<Field type="number"
|
||||
label={label} max={this.props.maxValue}
|
||||
onBlur={this.onCustomBlur} onKeyDown={this.onCustomKeyDown} onChange={this.onCustomChange}
|
||||
value={String(this.state.customValue)} disabled={this.props.disabled} />
|
||||
|
@ -151,7 +151,7 @@ export default createReactClass({
|
|||
});
|
||||
|
||||
picker = (
|
||||
<Field id={`powerSelector_notCustom_${this.props.powerLevelKey}`} element="select"
|
||||
<Field element="select"
|
||||
label={label} onChange={this.onSelectChange}
|
||||
value={String(this.state.selectValue)} disabled={this.props.disabled}>
|
||||
{options}
|
||||
|
|
|
@ -23,7 +23,6 @@ import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
|||
// Controlled form component wrapping Field for inputting a room alias scoped to a given domain
|
||||
export default class RoomAliasField extends React.PureComponent {
|
||||
static propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
domain: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func,
|
||||
value: PropTypes.string.isRequired,
|
||||
|
@ -50,7 +49,6 @@ export default class RoomAliasField extends React.PureComponent {
|
|||
className="mx_RoomAliasField"
|
||||
prefix={poundSign}
|
||||
postfix={domain}
|
||||
id={this.props.id}
|
||||
ref={ref => this._fieldRef = ref}
|
||||
onValidate={this._onValidate}
|
||||
placeholder={_t("e.g. my-room")}
|
||||
|
|
|
@ -22,6 +22,7 @@ import { _t } from '../../../languageHandler';
|
|||
|
||||
import * as recent from '../../../emojipicker/recent';
|
||||
import {DATA_BY_CATEGORY, getEmojiFromUnicode} from "../../../emoji";
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
|
||||
export const CATEGORY_HEADER_HEIGHT = 22;
|
||||
export const EMOJI_HEIGHT = 37;
|
||||
|
@ -214,7 +215,7 @@ class EmojiPicker extends React.Component {
|
|||
<div className="mx_EmojiPicker">
|
||||
<Header categories={this.categories} defaultCategory="recent" onAnchorClick={this.scrollToCategory} />
|
||||
<Search query={this.state.filter} onChange={this.onChangeFilter} />
|
||||
<div className="mx_EmojiPicker_body" ref={this.bodyRef} onScroll={this.onScroll}>
|
||||
<AutoHideScrollbar className="mx_EmojiPicker_body" wrappedRef={e => this.bodyRef.current = e} onScroll={this.onScroll}>
|
||||
{this.categories.map(category => {
|
||||
const emojis = this.memoizedDataByCategory[category.id];
|
||||
const categoryElement = (<Category key={category.id} id={category.id} name={category.name}
|
||||
|
@ -226,7 +227,7 @@ class EmojiPicker extends React.Component {
|
|||
heightBefore += height;
|
||||
return categoryElement;
|
||||
})}
|
||||
</div>
|
||||
</AutoHideScrollbar>
|
||||
{this.state.previewEmoji || !this.props.showQuickReactions
|
||||
? <Preview emoji={this.state.previewEmoji} />
|
||||
: <QuickReactions onClick={this.onClickEmoji} selectedEmojis={this.props.selectedEmojis} /> }
|
||||
|
|
|
@ -62,7 +62,6 @@ class EditableAliasesList extends EditableItemList {
|
|||
className="mx_EditableItemList_newItem"
|
||||
>
|
||||
<RoomAliasField
|
||||
id={`mx_EditableItemList_new_${this.props.id}`}
|
||||
ref={this._aliasField}
|
||||
onChange={onChange}
|
||||
value={this.props.newItem || ""}
|
||||
|
|
|
@ -155,7 +155,7 @@ export default class RoomProfileSettings extends React.Component {
|
|||
onChange={this._onAvatarChanged} accept="image/*" />
|
||||
<div className="mx_ProfileSettings_profile">
|
||||
<div className="mx_ProfileSettings_controls">
|
||||
<Field id="profileDisplayName" label={_t("Room Name")}
|
||||
<Field label={_t("Room Name")}
|
||||
type="text" value={this.state.displayName} autoComplete="off"
|
||||
onChange={this._onDisplayNameChanged} disabled={!this.state.canSetName} />
|
||||
<Field id="profileTopic" label={_t("Room Topic")} disabled={!this.state.canSetTopic}
|
||||
|
|
|
@ -27,6 +27,7 @@ import { _t } from '../../../languageHandler';
|
|||
import classNames from 'classnames';
|
||||
import RateLimitedFunc from '../../../ratelimitedfunc';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
|
||||
|
||||
export default createReactClass({
|
||||
|
@ -264,14 +265,14 @@ export default createReactClass({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className={classes} style={style} >
|
||||
<AutoHideScrollbar className={classes} style={style} >
|
||||
{ stateViews }
|
||||
{ appsDrawer }
|
||||
{ fileDropTarget }
|
||||
{ callView }
|
||||
{ conferenceCallNotification }
|
||||
{ this.props.children }
|
||||
</div>
|
||||
</AutoHideScrollbar>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -37,7 +37,7 @@ import E2EIcon from './E2EIcon';
|
|||
import InviteOnlyIcon from './InviteOnlyIcon';
|
||||
// eslint-disable-next-line camelcase
|
||||
import rate_limited_func from '../../../ratelimitedfunc';
|
||||
import { shieldStatusForMembership } from '../../../utils/ShieldUtils';
|
||||
import { shieldStatusForRoom } from '../../../utils/ShieldUtils';
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'RoomTile',
|
||||
|
@ -157,7 +157,7 @@ export default createReactClass({
|
|||
|
||||
/* At this point, the user has encryption on and cross-signing on */
|
||||
this.setState({
|
||||
e2eStatus: await shieldStatusForMembership(cli, this.props.room),
|
||||
e2eStatus: await shieldStatusForRoom(cli, this.props.room),
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -131,8 +131,13 @@ export default class SendMessageComposer extends React.Component {
|
|||
this.onVerticalArrow(event, false);
|
||||
} else if (this._prepareToEncrypt) {
|
||||
this._prepareToEncrypt();
|
||||
} else if (event.key === Key.ESCAPE) {
|
||||
dis.dispatch({
|
||||
action: 'reply_to_event',
|
||||
event: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onVerticalArrow(e, up) {
|
||||
// arrows from an initial-caret composer navigates recent messages to edit
|
||||
|
|
|
@ -235,7 +235,7 @@ export default createReactClass({
|
|||
if (!this.state.cachedPassword) {
|
||||
currentPassword = (
|
||||
<div className={rowClassName}>
|
||||
<Field id="mx_ChangePassword_oldPassword"
|
||||
<Field
|
||||
type="password"
|
||||
label={_t('Current password')}
|
||||
value={this.state.oldPassword}
|
||||
|
@ -254,7 +254,6 @@ export default createReactClass({
|
|||
{ currentPassword }
|
||||
<div className={rowClassName}>
|
||||
<Field
|
||||
id="mx_ChangePassword_newPassword"
|
||||
type="password"
|
||||
label={passwordLabel}
|
||||
value={this.state.newPassword}
|
||||
|
@ -265,7 +264,6 @@ export default createReactClass({
|
|||
</div>
|
||||
<div className={rowClassName}>
|
||||
<Field
|
||||
id="mx_ChangePassword_newPasswordConfirm"
|
||||
type="password"
|
||||
label={_t("Confirm password")}
|
||||
value={this.state.newPasswordConfirm}
|
||||
|
|
|
@ -108,12 +108,12 @@ export default class CrossSigningPanel extends React.PureComponent {
|
|||
* 2. Access existing secret storage by requesting passphrase and accessing
|
||||
* cross-signing keys as needed.
|
||||
* 3. All keys are loaded and there's nothing to do.
|
||||
* @param {bool} [force] Bootstrap again even if keys already present
|
||||
* @param {bool} [forceReset] Bootstrap again even if keys already present
|
||||
*/
|
||||
_bootstrapSecureSecretStorage = async (force=false) => {
|
||||
_bootstrapSecureSecretStorage = async (forceReset=false) => {
|
||||
this.setState({ error: null });
|
||||
try {
|
||||
await accessSecretStorage(() => undefined, force);
|
||||
await accessSecretStorage(() => undefined, forceReset);
|
||||
} catch (e) {
|
||||
this.setState({ error: e });
|
||||
console.error("Error bootstrapping secret storage", e);
|
||||
|
|
|
@ -153,7 +153,7 @@ export default class ProfileSettings extends React.Component {
|
|||
{this.state.userId}
|
||||
{hostingSignup}
|
||||
</p>
|
||||
<Field id="profileDisplayName" label={_t("Display Name")}
|
||||
<Field label={_t("Display Name")}
|
||||
type="text" value={this.state.displayName} autoComplete="off"
|
||||
onChange={this._onDisplayNameChanged} />
|
||||
</div>
|
||||
|
|
|
@ -403,8 +403,8 @@ export default class SetIdServer extends React.Component {
|
|||
<span className="mx_SettingsTab_subsectionText">
|
||||
{bodyText}
|
||||
</span>
|
||||
<Field label={_t("Enter a new identity server")}
|
||||
id="mx_SetIdServer_idServer"
|
||||
<Field
|
||||
label={_t("Enter a new identity server")}
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
placeholder={this.state.defaultIdServer}
|
||||
|
|
|
@ -237,7 +237,7 @@ export default class EmailAddresses extends React.Component {
|
|||
{existingEmailElements}
|
||||
<form onSubmit={this._onAddClick} autoComplete="off"
|
||||
noValidate={true} className="mx_EmailAddresses_new">
|
||||
<Field id="mx_EmailAddressses_newEmailAddress"
|
||||
<Field
|
||||
type="text"
|
||||
label={_t("Email Address")}
|
||||
autoComplete="off"
|
||||
|
|
|
@ -232,7 +232,7 @@ export default class PhoneNumbers extends React.Component {
|
|||
{this.state.verifyError}
|
||||
</div>
|
||||
<form onSubmit={this._onContinueClick} autoComplete="off" noValidate={true}>
|
||||
<Field id="mx_PhoneNumbers_newPhoneNumberCode"
|
||||
<Field
|
||||
type="text"
|
||||
label={_t("Verification code")}
|
||||
autoComplete="off"
|
||||
|
@ -262,7 +262,7 @@ export default class PhoneNumbers extends React.Component {
|
|||
{existingPhoneElements}
|
||||
<form onSubmit={this._onAddClick} autoComplete="off" noValidate={true} className="mx_PhoneNumbers_new">
|
||||
<div className="mx_PhoneNumbers_input">
|
||||
<Field id="mx_PhoneNumbers_newPhoneNumber"
|
||||
<Field
|
||||
type="text"
|
||||
label={_t("Phone Number")}
|
||||
autoComplete="off"
|
||||
|
|
|
@ -208,7 +208,7 @@ export class PhoneNumber extends React.Component {
|
|||
{this.state.verifyError}
|
||||
</span>
|
||||
<form onSubmit={this.onContinueClick} autoComplete="off" noValidate={true}>
|
||||
<Field id="mx_PhoneNumbers_newPhoneNumberCode"
|
||||
<Field
|
||||
type="text"
|
||||
label={_t("Verification code")}
|
||||
autoComplete="off"
|
||||
|
|
|
@ -422,7 +422,6 @@ export default class GeneralUserSettingsTab extends React.Component {
|
|||
<Field
|
||||
label={_t("Custom theme URL")}
|
||||
type='text'
|
||||
id='mx_GeneralUserSettingsTab_customThemeInput'
|
||||
autoComplete="off"
|
||||
onChange={this._onCustomThemeChange}
|
||||
value={this.state.customThemeUrl}
|
||||
|
@ -448,7 +447,7 @@ export default class GeneralUserSettingsTab extends React.Component {
|
|||
<div className="mx_SettingsTab_section mx_GeneralUserSettingsTab_themeSection">
|
||||
<span className="mx_SettingsTab_subheading">{_t("Theme")}</span>
|
||||
{systemThemeSection}
|
||||
<Field id="theme" label={_t("Theme")} element="select"
|
||||
<Field label={_t("Theme")} element="select"
|
||||
value={this.state.theme} onChange={this._onThemeChange}
|
||||
disabled={this.state.useSystemTheme}
|
||||
>
|
||||
|
|
|
@ -272,7 +272,6 @@ export default class MjolnirUserSettingsTab extends React.Component {
|
|||
<div>
|
||||
<form onSubmit={this._onAddPersonalRule} autoComplete="off">
|
||||
<Field
|
||||
id="mx_MjolnirUserSettingsTab_personalAdd"
|
||||
type="text"
|
||||
label={_t("Server or user ID to ignore")}
|
||||
placeholder={_t("eg: @bot:* or example.org")}
|
||||
|
@ -305,7 +304,6 @@ export default class MjolnirUserSettingsTab extends React.Component {
|
|||
<div>
|
||||
<form onSubmit={this._onSubscribeList} autoComplete="off">
|
||||
<Field
|
||||
id="mx_MjolnirUserSettingsTab_subscriptionAdd"
|
||||
type="text"
|
||||
label={_t("Room ID or alias of ban list")}
|
||||
value={this.state.newList}
|
||||
|
|
|
@ -195,19 +195,16 @@ export default class PreferencesUserSettingsTab extends React.Component {
|
|||
{autoHideMenuOption}
|
||||
{autoLaunchOption}
|
||||
<Field
|
||||
id={"autocompleteDelay"}
|
||||
label={_t('Autocomplete delay (ms)')}
|
||||
type='number'
|
||||
value={this.state.autocompleteDelay}
|
||||
onChange={this._onAutocompleteDelayChange} />
|
||||
<Field
|
||||
id={"readMarkerInViewThresholdMs"}
|
||||
label={_t('Read Marker lifetime (ms)')}
|
||||
type='number'
|
||||
value={this.state.readMarkerInViewThresholdMs}
|
||||
onChange={this._onReadMarkerInViewThresholdMs} />
|
||||
<Field
|
||||
id={"readMarkerOutOfViewThresholdMs"}
|
||||
label={_t('Read Marker off-screen lifetime (ms)')}
|
||||
type='number'
|
||||
value={this.state.readMarkerOutOfViewThresholdMs}
|
||||
|
|
|
@ -163,7 +163,7 @@ export default class VoiceUserSettingsTab extends React.Component {
|
|||
if (audioOutputs.length > 0) {
|
||||
const defaultDevice = getDefaultDevice(audioOutputs);
|
||||
speakerDropdown = (
|
||||
<Field element="select" label={_t("Audio Output")} id="audioOutput"
|
||||
<Field element="select" label={_t("Audio Output")}
|
||||
value={this.state.activeAudioOutput || defaultDevice}
|
||||
onChange={this._setAudioOutput}>
|
||||
{this._renderDeviceOptions(audioOutputs, 'audioOutput')}
|
||||
|
@ -175,7 +175,7 @@ export default class VoiceUserSettingsTab extends React.Component {
|
|||
if (audioInputs.length > 0) {
|
||||
const defaultDevice = getDefaultDevice(audioInputs);
|
||||
microphoneDropdown = (
|
||||
<Field element="select" label={_t("Microphone")} id="audioInput"
|
||||
<Field element="select" label={_t("Microphone")}
|
||||
value={this.state.activeAudioInput || defaultDevice}
|
||||
onChange={this._setAudioInput}>
|
||||
{this._renderDeviceOptions(audioInputs, 'audioInput')}
|
||||
|
@ -187,7 +187,7 @@ export default class VoiceUserSettingsTab extends React.Component {
|
|||
if (videoInputs.length > 0) {
|
||||
const defaultDevice = getDefaultDevice(videoInputs);
|
||||
webcamDropdown = (
|
||||
<Field element="select" label={_t("Camera")} id="videoInput"
|
||||
<Field element="select" label={_t("Camera")}
|
||||
value={this.state.activeVideoInput || defaultDevice}
|
||||
onChange={this._setVideoInput}>
|
||||
{this._renderDeviceOptions(videoInputs, 'videoInput')}
|
||||
|
|
|
@ -2216,6 +2216,7 @@
|
|||
"Navigate recent messages to edit": "Navigate recent messages to edit",
|
||||
"Jump to start/end of the composer": "Jump to start/end of the composer",
|
||||
"Navigate composer history": "Navigate composer history",
|
||||
"Cancel replying to a message": "Cancel replying to a message",
|
||||
"Toggle microphone mute": "Toggle microphone mute",
|
||||
"Toggle video on/off": "Toggle video on/off",
|
||||
"Jump to room search": "Jump to room search",
|
||||
|
|
|
@ -18,7 +18,7 @@ interface Room {
|
|||
roomId: string;
|
||||
}
|
||||
|
||||
export async function shieldStatusForMembership(client: Client, room: Room): Promise<string> {
|
||||
export async function shieldStatusForRoom(client: Client, room: Room): Promise<string> {
|
||||
const members = (await room.getEncryptionTargetMembers()).map(({userId}) => userId);
|
||||
const inDMMap = !!DMRoomMap.shared().getUserIdForRoomId(room.roomId);
|
||||
|
||||
|
@ -41,8 +41,8 @@ export async function shieldStatusForMembership(client: Client, room: Room): Pro
|
|||
/* Don't alarm if no other users are verified */
|
||||
const includeUser = (verified.length > 0) && // Don't alarm for self in rooms where nobody else is verified
|
||||
!inDMMap && // Don't alarm for self in DMs with other users
|
||||
(members.length !== 2) || // Don't alarm for self in 1:1 chats with other users
|
||||
(members.length === 1); // Do alarm for self if we're alone in a room
|
||||
(members.length !== 2) || // Don't alarm for self in 1:1 chats with other users
|
||||
(members.length === 1); // Do alarm for self if we're alone in a room
|
||||
const targets = includeUser ? [...verified, client.getUserId()] : verified;
|
||||
for (const userId of targets) {
|
||||
const devices = await client.getStoredDevicesForUser(userId);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { shieldStatusForMembership } from '../../src/utils/ShieldUtils';
|
||||
import { shieldStatusForRoom } from '../../src/utils/ShieldUtils';
|
||||
import DMRoomMap from '../../src/utils/DMRoomMap';
|
||||
|
||||
function mkClient(selfTrust) {
|
||||
|
@ -55,7 +55,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
|
|||
roomId: dm ? "DM" : "other",
|
||||
getEncryptionTargetMembers: () => ["@self:localhost", "@FF1:h", "@FF2:h"].map((userId) => ({userId})),
|
||||
};
|
||||
const status = await shieldStatusForMembership(client, room);
|
||||
const status = await shieldStatusForRoom(client, room);
|
||||
expect(status).toEqual("normal");
|
||||
});
|
||||
|
||||
|
@ -68,7 +68,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
|
|||
roomId: dm ? "DM" : "other",
|
||||
getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@TT2:h"].map((userId) => ({userId})),
|
||||
};
|
||||
const status = await shieldStatusForMembership(client, room);
|
||||
const status = await shieldStatusForRoom(client, room);
|
||||
expect(status).toEqual(result);
|
||||
});
|
||||
|
||||
|
@ -81,7 +81,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
|
|||
roomId: dm ? "DM" : "other",
|
||||
getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@FF2:h"].map((userId) => ({userId})),
|
||||
};
|
||||
const status = await shieldStatusForMembership(client, room);
|
||||
const status = await shieldStatusForRoom(client, room);
|
||||
expect(status).toEqual(result);
|
||||
});
|
||||
|
||||
|
@ -94,7 +94,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
|
|||
roomId: dm ? "DM" : "other",
|
||||
getEncryptionTargetMembers: () => ["@self:localhost"].map((userId) => ({userId})),
|
||||
};
|
||||
const status = await shieldStatusForMembership(client, room);
|
||||
const status = await shieldStatusForRoom(client, room);
|
||||
expect(status).toEqual(result);
|
||||
});
|
||||
|
||||
|
@ -107,7 +107,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
|
|||
roomId: dm ? "DM" : "other",
|
||||
getEncryptionTargetMembers: () => ["@self:localhost", "@TT:h"].map((userId) => ({userId})),
|
||||
};
|
||||
const status = await shieldStatusForMembership(client, room);
|
||||
const status = await shieldStatusForRoom(client, room);
|
||||
expect(status).toEqual(result);
|
||||
});
|
||||
|
||||
|
@ -120,7 +120,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
|
|||
roomId: dm ? "DM" : "other",
|
||||
getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h"].map((userId) => ({userId})),
|
||||
};
|
||||
const status = await shieldStatusForMembership(client, room);
|
||||
const status = await shieldStatusForRoom(client, room);
|
||||
expect(status).toEqual(result);
|
||||
});
|
||||
});
|
||||
|
@ -140,7 +140,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() {
|
|||
roomId: dm ? "DM" : "other",
|
||||
getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h"].map((userId) => ({userId})),
|
||||
};
|
||||
const status = await shieldStatusForMembership(client, room);
|
||||
const status = await shieldStatusForRoom(client, room);
|
||||
expect(status).toEqual(result);
|
||||
});
|
||||
|
||||
|
@ -152,7 +152,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() {
|
|||
roomId: dm ? "DM" : "other",
|
||||
getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h", "@TT: h"].map((userId) => ({userId})),
|
||||
};
|
||||
const status = await shieldStatusForMembership(client, room);
|
||||
const status = await shieldStatusForRoom(client, room);
|
||||
expect(status).toEqual(result);
|
||||
});
|
||||
|
||||
|
@ -164,7 +164,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() {
|
|||
roomId: dm ? "DM" : "other",
|
||||
getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h", "@FT: h"].map((userId) => ({userId})),
|
||||
};
|
||||
const status = await shieldStatusForMembership(client, room);
|
||||
const status = await shieldStatusForRoom(client, room);
|
||||
expect(status).toEqual(result);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5690,8 +5690,8 @@ mathml-tag-names@^2.0.1:
|
|||
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
|
||||
|
||||
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop":
|
||||
version "5.1.1"
|
||||
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/b2e154377a4268441a3b27b183dd7f7018187035"
|
||||
version "5.2.0"
|
||||
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/223d37ffce674a23ca73702f04b9ba31cfd84196"
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.8.3"
|
||||
another-json "^0.2.0"
|
||||
|
|
Loading…
Reference in New Issue