diff --git a/src/AddThreepid.js b/src/AddThreepid.js index 8f4e3883d3..b13cb0c9f3 100644 --- a/src/AddThreepid.js +++ b/src/AddThreepid.js @@ -22,6 +22,10 @@ import Modal from './Modal'; import { _t } from './languageHandler'; import IdentityAuthClient from './IdentityAuthClient'; +function getIdServerDomain() { + return MatrixClientPeg.get().idBaseUrl.split("://")[1]; +} + /** * Allows a user to add a third party identifier to their homeserver and, * optionally, the identity servers. @@ -166,7 +170,7 @@ export default class AddThreepid { await MatrixClientPeg.get().bindThreePid({ sid: this.sessionId, client_secret: this.clientSecret, - id_server: identityServerDomain, + id_server: getIdServerDomain(), id_access_token: identityAccessToken, }); } else { @@ -198,7 +202,7 @@ export default class AddThreepid { await MatrixClientPeg.get().addThreePid({ sid: this.sessionId, client_secret: this.clientSecret, - id_server: identityServerDomain, + id_server: getIdServerDomain(), }, this.bind); } } catch (err) { @@ -260,7 +264,7 @@ export default class AddThreepid { await MatrixClientPeg.get().bindThreePid({ sid: this.sessionId, client_secret: this.clientSecret, - id_server: identityServerDomain, + id_server: getIdServerDomain(), id_access_token: await authClient.getAccessToken(), }); } else { @@ -292,7 +296,7 @@ export default class AddThreepid { await MatrixClientPeg.get().addThreePid({ sid: this.sessionId, client_secret: this.clientSecret, - id_server: identityServerDomain, + id_server: getIdServerDomain(), }, this.bind); } } diff --git a/src/components/views/dialogs/CreateRoomDialog.js b/src/components/views/dialogs/CreateRoomDialog.js index 8e267da5d1..026c60235a 100644 --- a/src/components/views/dialogs/CreateRoomDialog.js +++ b/src/components/views/dialogs/CreateRoomDialog.js @@ -73,6 +73,14 @@ export default createReactClass({ this._detailsRef.removeEventListener("toggle", this.onDetailsToggled); }, + _onKeyDown: function(event) { + if (event.key === "Enter") { + this.onOk(); + event.preventDefault(); + event.stopPropagation(); + } + }, + onOk: async function() { const activeElement = document.activeElement; if (activeElement) { @@ -176,7 +184,7 @@ export default createReactClass({ -
+
this._nameFieldRef = ref} label={ _t('Name') } onChange={this.onNameChange} onValidate={this.onNameValidate} value={this.state.name} className="mx_CreateRoomDialog_name" /> diff --git a/src/components/views/rooms/BasicMessageComposer.js b/src/components/views/rooms/BasicMessageComposer.js index 4ec43d8af2..92c2ae29e6 100644 --- a/src/components/views/rooms/BasicMessageComposer.js +++ b/src/components/views/rooms/BasicMessageComposer.js @@ -90,6 +90,7 @@ export default class BasicMessageEditor extends React.Component { this._modifiedFlag = false; this._isIMEComposing = false; this._hasTextSelected = false; + this._emoticonSettingHandle = null; } _replaceEmoticon = (caretPosition, inputType, diff) => { @@ -437,18 +438,25 @@ export default class BasicMessageEditor extends React.Component { this.setState({completionIndex}); } + _configureEmoticonAutoReplace() { + const shouldReplace = SettingsStore.getValue('MessageComposerInput.autoReplaceEmoji'); + this.props.model.setTransformCallback(shouldReplace ? this._replaceEmoticon : null); + } + componentWillUnmount() { this._editorRef.removeEventListener("input", this._onInput, true); this._editorRef.removeEventListener("compositionstart", this._onCompositionStart, true); this._editorRef.removeEventListener("compositionend", this._onCompositionEnd, true); + SettingsStore.unwatchSetting(this._emoticonSettingHandle); } componentDidMount() { const model = this.props.model; model.setUpdateCallback(this._updateEditorState); - if (SettingsStore.getValue('MessageComposerInput.autoReplaceEmoji')) { - model.setTransformCallback(this._replaceEmoticon); - } + this._emoticonSettingHandle = SettingsStore.watchSetting('MessageComposerInput.autoReplaceEmoji', null, () => { + this._configureEmoticonAutoReplace(); + }); + this._configureEmoticonAutoReplace(); const partCreator = model.partCreator; // TODO: does this allow us to get rid of EditorStateTransfer? // not really, but we could not serialize the parts, and just change the autoCompleter diff --git a/src/components/views/settings/account/EmailAddresses.js b/src/components/views/settings/account/EmailAddresses.js index e9bf79b005..07f2a60c38 100644 --- a/src/components/views/settings/account/EmailAddresses.js +++ b/src/components/views/settings/account/EmailAddresses.js @@ -193,8 +193,14 @@ export default class EmailAddresses extends React.Component { this.props.onEmailsChange(emails); }).catch((err) => { this.setState({continueDisabled: false}); - if (err.errcode !== 'M_THREEPID_AUTH_FAILED') { - const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + if (err.errcode === 'M_THREEPID_AUTH_FAILED') { + Modal.createTrackedDialog("Email hasn't been verified yet", "", ErrorDialog, { + title: _t("Your email address hasn't been verified yet"), + description: _t("Click the link in the email you received to verify " + + "and then click continue again."), + }); + } else { console.error("Unable to verify email address: ", err); Modal.createTrackedDialog('Unable to verify email address', '', ErrorDialog, { title: _t("Unable to verify email address."), diff --git a/src/components/views/settings/discovery/EmailAddresses.js b/src/components/views/settings/discovery/EmailAddresses.js index a4fcd605fc..cc3d2d0dad 100644 --- a/src/components/views/settings/discovery/EmailAddresses.js +++ b/src/components/views/settings/discovery/EmailAddresses.js @@ -171,8 +171,14 @@ export class EmailAddress extends React.Component { }); } catch (err) { this.setState({ continueDisabled: false }); - if (err.errcode !== 'M_THREEPID_AUTH_FAILED') { - const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + if (err.errcode === 'M_THREEPID_AUTH_FAILED') { + Modal.createTrackedDialog("E-mail hasn't been verified yet", "", ErrorDialog, { + title: _t("Your email address hasn't been verified yet"), + description: _t("Click the link in the email you received to verify " + + "and then click continue again."), + }); + } else { console.error("Unable to verify email address: " + err); Modal.createTrackedDialog('Unable to verify email address', '', ErrorDialog, { title: _t("Unable to verify email address."), diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index f6ed69a201..bd9229aaea 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -742,6 +742,8 @@ "Who can read history?": "Who can read history?", "Unable to revoke sharing for email address": "Unable to revoke sharing for email address", "Unable to share email address": "Unable to share email address", + "Your email address hasn't been verified yet": "Your email address hasn't been verified yet", + "Click the link in the email you received to verify and then click continue again.": "Click the link in the email you received to verify and then click continue again.", "Unable to verify email address.": "Unable to verify email address.", "Verify the link in your inbox": "Verify the link in your inbox", "Complete": "Complete", diff --git a/src/rageshake/rageshake.js b/src/rageshake/rageshake.js index c848be6c2b..d61956c925 100644 --- a/src/rageshake/rageshake.js +++ b/src/rageshake/rageshake.js @@ -1,6 +1,7 @@ /* Copyright 2017 OpenMarket Ltd Copyright 2018 New Vector Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -76,8 +77,22 @@ class ConsoleLogger { args = args.map((arg) => { if (arg instanceof Error) { return arg.message + (arg.stack ? `\n${arg.stack}` : ''); - } else if (typeof(arg) === 'object') { - return JSON.stringify(arg); + } else if (typeof (arg) === 'object') { + try { + return JSON.stringify(arg); + } catch (e) { + // In development, it can be useful to log complex cyclic + // objects to the console for inspection. This is fine for + // the console, but default `stringify` can't handle that. + // We workaround this by using a special replacer function + // to only log values of the root object and avoid cycles. + return JSON.stringify(arg, (key, value) => { + if (key && typeof value === "object") { + return ""; + } + return value; + }); + } } else { return arg; }