diff --git a/package.json b/package.json index 8e1a1fa668..ffd701a233 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "karma-summary-reporter": "^1.5.1", "karma-webpack": "^4.0.0-beta.0", "matrix-mock-request": "^1.2.3", - "matrix-react-test-utils": "^0.1.1", + "matrix-react-test-utils": "^0.2.2", "mocha": "^5.0.5", "react-addons-test-utils": "^15.4.0", "require-json": "0.0.1", diff --git a/src/Modal.js b/src/Modal.js index 96be445ab1..26c9da8bbb 100644 --- a/src/Modal.js +++ b/src/Modal.js @@ -274,7 +274,7 @@ class ModalManager { this._reRender(); return { close: closeDialog, - then: (resolve, reject) => onFinishedProm.then(resolve, reject), + finished: onFinishedProm, }; } @@ -285,7 +285,7 @@ class ModalManager { this._reRender(); return { close: closeDialog, - then: (resolve, reject) => onFinishedProm.then(resolve, reject), + finished: onFinishedProm, }; } diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index deef8488f4..b8903076c7 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -935,7 +935,7 @@ export default React.createClass({ const CreateRoomDialog = sdk.getComponent('dialogs.CreateRoomDialog'); const modal = Modal.createTrackedDialog('Create Room', '', CreateRoomDialog); - const [shouldCreate, name, noFederate] = await modal; + const [shouldCreate, name, noFederate] = await modal.finished; if (shouldCreate) { const createOpts = {}; if (name) createOpts.name = name; diff --git a/src/components/views/auth/ModularServerConfig.js b/src/components/views/auth/ModularServerConfig.js index b5af58adf1..ff8d88f738 100644 --- a/src/components/views/auth/ModularServerConfig.js +++ b/src/components/views/auth/ModularServerConfig.js @@ -15,13 +15,13 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; import sdk from '../../../index'; import { _t } from '../../../languageHandler'; import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils"; import SdkConfig from "../../../SdkConfig"; import AutoDiscoveryUtils from "../../../utils/AutoDiscoveryUtils"; import * as ServerType from '../../views/auth/ServerTypeSelector'; +import ServerConfig from "./ServerConfig"; const MODULAR_URL = 'https://modular.im/?utm_source=riot-web&utm_medium=web&utm_campaign=riot-web-authentication'; @@ -33,49 +33,8 @@ const MODULAR_URL = 'https://modular.im/?utm_source=riot-web&utm_medium=web&utm_ * This is a variant of ServerConfig with only the HS field and different body * text that is specific to the Modular case. */ -export default class ModularServerConfig extends React.PureComponent { - static propTypes = { - onServerConfigChange: PropTypes.func, - - // The current configuration that the user is expecting to change. - serverConfig: PropTypes.instanceOf(ValidatedServerConfig).isRequired, - - delayTimeMs: PropTypes.number, // time to wait before invoking onChanged - - // Called after the component calls onServerConfigChange - onAfterSubmit: PropTypes.func, - - // Optional text for the submit button. If falsey, no button will be shown. - submitText: PropTypes.string, - - // Optional class for the submit button. Only applies if the submit button - // is to be rendered. - submitClass: PropTypes.string, - }; - - static defaultProps = { - onServerConfigChange: function() {}, - customHsUrl: "", - delayTimeMs: 0, - }; - - constructor(props) { - super(props); - - this.state = { - busy: false, - errorText: "", - hsUrl: props.serverConfig.hsUrl, - isUrl: props.serverConfig.isUrl, - }; - } - - componentWillReceiveProps(newProps) { - if (newProps.serverConfig.hsUrl === this.state.hsUrl && - newProps.serverConfig.isUrl === this.state.isUrl) return; - - this.validateAndApplyServer(newProps.serverConfig.hsUrl, newProps.serverConfig.isUrl); - } +export default class ModularServerConfig extends ServerConfig { + static propTypes = ServerConfig.propTypes; async validateAndApplyServer(hsUrl, isUrl) { // Always try and use the defaults first @@ -120,35 +79,6 @@ export default class ModularServerConfig extends React.PureComponent { return this.validateAndApplyServer(this.state.hsUrl, ServerType.TYPES.PREMIUM.identityServerUrl); } - onHomeserverBlur = (ev) => { - this._hsTimeoutId = this._waitThenInvoke(this._hsTimeoutId, () => { - this.validateServer(); - }); - }; - - onHomeserverChange = (ev) => { - const hsUrl = ev.target.value; - this.setState({ hsUrl }); - }; - - onSubmit = async (ev) => { - ev.preventDefault(); - ev.stopPropagation(); - const result = await this.validateServer(); - if (!result) return; // Do not continue. - - if (this.props.onAfterSubmit) { - this.props.onAfterSubmit(); - } - }; - - _waitThenInvoke(existingTimeoutId, fn) { - if (existingTimeoutId) { - clearTimeout(existingTimeoutId); - } - return setTimeout(fn.bind(this), this.props.delayTimeMs); - } - render() { const Field = sdk.getComponent('elements.Field'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); diff --git a/src/components/views/auth/RegistrationForm.js b/src/components/views/auth/RegistrationForm.js index cd3dab12ac..f3b9640e16 100644 --- a/src/components/views/auth/RegistrationForm.js +++ b/src/components/views/auth/RegistrationForm.js @@ -2,6 +2,7 @@ Copyright 2015, 2016 OpenMarket Ltd Copyright 2017 Vector Creations Ltd Copyright 2018, 2019 New Vector Ltd +Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -69,10 +70,10 @@ module.exports = React.createClass({ fieldValid: {}, // The ISO2 country code selected in the phone number entry phoneCountry: this.props.defaultPhoneCountry, - username: "", - email: "", - phoneNumber: "", - password: "", + username: this.props.defaultUsername || "", + email: this.props.defaultEmail || "", + phoneNumber: this.props.defaultPhoneNumber || "", + password: this.props.defaultPassword || "", passwordConfirm: "", passwordComplexity: null, passwordSafe: false, @@ -90,7 +91,7 @@ module.exports = React.createClass({ } const self = this; - if (this.state.email == '') { + if (this.state.email === '') { const haveIs = Boolean(this.props.serverConfig.isUrl); let desc; @@ -455,7 +456,6 @@ module.exports = React.createClass({ ref={field => this[FIELD_EMAIL] = field} type="text" label={emailPlaceholder} - defaultValue={this.props.defaultEmail} value={this.state.email} onChange={this.onEmailChange} onValidate={this.onEmailValidate} @@ -469,7 +469,6 @@ module.exports = React.createClass({ ref={field => this[FIELD_PASSWORD] = field} type="password" label={_t("Password")} - defaultValue={this.props.defaultPassword} value={this.state.password} onChange={this.onPasswordChange} onValidate={this.onPasswordValidate} @@ -483,7 +482,6 @@ module.exports = React.createClass({ ref={field => this[FIELD_PASSWORD_CONFIRM] = field} type="password" label={_t("Confirm")} - defaultValue={this.props.defaultPassword} value={this.state.passwordConfirm} onChange={this.onPasswordConfirmChange} onValidate={this.onPasswordConfirmValidate} @@ -512,7 +510,6 @@ module.exports = React.createClass({ ref={field => this[FIELD_PHONE_NUMBER] = field} type="text" label={phoneLabel} - defaultValue={this.props.defaultPhoneNumber} value={this.state.phoneNumber} prefix={phoneCountry} onChange={this.onPhoneNumberChange} @@ -528,7 +525,6 @@ module.exports = React.createClass({ type="text" autoFocus={true} label={_t("Username")} - defaultValue={this.props.defaultUsername} value={this.state.username} onChange={this.onUsernameChange} onValidate={this.onUsernameValidate} diff --git a/src/components/views/avatars/BaseAvatar.js b/src/components/views/avatars/BaseAvatar.js index 80f5c43d0c..afc6faa18d 100644 --- a/src/components/views/avatars/BaseAvatar.js +++ b/src/components/views/avatars/BaseAvatar.js @@ -1,6 +1,7 @@ /* Copyright 2015, 2016 OpenMarket Ltd Copyright 2018 New Vector Ltd +Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,7 +20,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import { MatrixClient } from 'matrix-js-sdk'; import AvatarLogic from '../../../Avatar'; -import sdk from '../../../index'; import SettingsStore from "../../../settings/SettingsStore"; import AccessibleButton from '../elements/AccessibleButton'; @@ -121,6 +121,10 @@ module.exports = React.createClass({ ); urls.push(defaultImageUrl); // lowest priority } + + // deduplicate URLs + urls = Array.from(new Set(urls)); + return { imageUrls: urls, defaultImageUrl: defaultImageUrl, diff --git a/src/components/views/messages/RoomAvatarEvent.js b/src/components/views/messages/RoomAvatarEvent.js index d035fc9237..207a385b92 100644 --- a/src/components/views/messages/RoomAvatarEvent.js +++ b/src/components/views/messages/RoomAvatarEvent.js @@ -1,5 +1,6 @@ /* Copyright 2017 Vector Creations Ltd +Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,7 +18,6 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import MatrixClientPeg from '../../../MatrixClientPeg'; -import { ContentRepo } from 'matrix-js-sdk'; import { _t } from '../../../languageHandler'; import sdk from '../../../index'; import Modal from '../../../Modal'; @@ -31,12 +31,21 @@ module.exports = React.createClass({ mxEvent: PropTypes.object.isRequired, }, - onAvatarClick: function(name) { - const httpUrl = MatrixClientPeg.get().mxcUrlToHttp(this.props.mxEvent.getContent().url); + onAvatarClick: function() { + const cli = MatrixClientPeg.get(); + const ev = this.props.mxEvent; + const httpUrl = cli.mxcUrlToHttp(ev.getContent().url); + + const room = cli.getRoom(this.props.mxEvent.getRoomId()); + const text = _t('%(senderDisplayName)s changed the avatar for %(roomName)s', { + senderDisplayName: ev.sender && ev.sender.name ? ev.sender.name : ev.getSender(), + roomName: room ? room.name : '', + }); + const ImageView = sdk.getComponent("elements.ImageView"); const params = { src: httpUrl, - name: name, + name: text, }; Modal.createDialog(ImageView, params, "mx_Dialog_lightbox"); }, @@ -44,29 +53,22 @@ module.exports = React.createClass({ render: function() { const ev = this.props.mxEvent; const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender(); - const BaseAvatar = sdk.getComponent("avatars.BaseAvatar"); - - const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId()); - const name = _t('%(senderDisplayName)s changed the avatar for %(roomName)s', { - senderDisplayName: senderDisplayName, - roomName: room ? room.name : '', - }); + const RoomAvatar = sdk.getComponent("avatars.RoomAvatar"); if (!ev.getContent().url || ev.getContent().url.trim().length === 0) { return (