diff --git a/res/css/_components.scss b/res/css/_components.scss index 97da563347..e017d4b95a 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -30,6 +30,7 @@ @import "./views/auth/_AuthHeader.scss"; @import "./views/auth/_AuthHeaderLogo.scss"; @import "./views/auth/_AuthPage.scss"; +@import "./views/auth/_CountryDropdown.scss"; @import "./views/auth/_InteractiveAuthEntryComponents.scss"; @import "./views/auth/_LanguageSelector.scss"; @import "./views/auth/_ServerConfig.scss"; diff --git a/res/css/structures/auth/_Login.scss b/res/css/structures/auth/_Login.scss index 5ba4a38c95..b48021c27a 100644 --- a/res/css/structures/auth/_Login.scss +++ b/res/css/structures/auth/_Login.scss @@ -15,13 +15,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_Login_support { - text-align: center; - font-size: 13px; - margin-top: 0px; - opacity: 0.7; -} - .mx_Login_field { width: 100%; box-sizing: border-box; @@ -33,14 +26,6 @@ limitations under the License. margin-bottom: 14px; } -.mx_Login_fieldLabel { - margin-top: -10px; - margin-left: 8px; - margin-bottom: 14px; - font-size: 13px; - opacity: 0.8; -} - .mx_Login_submit { @mixin mx_DialogButton; width: 100%; @@ -58,16 +43,6 @@ limitations under the License. opacity: 0.3; } -.mx_Login_label { - font-size: 13px; - opacity: 0.8; -} - -.mx_Login_checkbox, -.mx_Login_radio { - margin-right: 10px; -} - .mx_AuthBody a.mx_Login_sso_link:link, .mx_AuthBody a.mx_Login_sso_link:hover, .mx_AuthBody a.mx_Login_sso_link:visited { @@ -119,10 +94,6 @@ limitations under the License. flex: 1 1 auto; } -.mx_Login_field_group { - display: flex; -} - .mx_Login_field_prefix { height: 38px; padding: 0px 5px; @@ -147,7 +118,6 @@ limitations under the License. .mx_Login_phoneCountry { margin-bottom: 14px; - width: 150px; /* To override mx_Login_field_prefix */ text-align: left; diff --git a/res/css/views/auth/_AuthBody.scss b/res/css/views/auth/_AuthBody.scss index 845aea3fd9..08a8b4ff4a 100644 --- a/res/css/views/auth/_AuthBody.scss +++ b/res/css/views/auth/_AuthBody.scss @@ -47,6 +47,24 @@ limitations under the License. box-sizing: border-box; } +.mx_Auth_fieldRow { + display: flex; + margin-bottom: 10px; +} + +.mx_Auth_fieldRow > * { + margin: 0 5px; + flex: 1; +} + +.mx_Auth_fieldRow > *:first-child { + margin-left: 0; +} + +.mx_Auth_fieldRow > *:last-child { + margin-right: 0; +} + .mx_AuthBody a:link, .mx_AuthBody a:hover, .mx_AuthBody a:visited { diff --git a/res/css/views/auth/_CountryDropdown.scss b/res/css/views/auth/_CountryDropdown.scss new file mode 100644 index 0000000000..6fd3c0182c --- /dev/null +++ b/res/css/views/auth/_CountryDropdown.scss @@ -0,0 +1,34 @@ +/* +Copyright 2019 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_CountryDropdown .mx_Dropdown_input .mx_Dropdown_option { + padding: 0 3px; +} + +.mx_CountryDropdown .mx_Dropdown_arrow { + padding-right: 3px; +} + +.mx_CountryDropdown_shortOption { + display: inline-flex; + align-items: center; + height: 100%; +} + +.mx_CountryDropdown_option { + display: flex; + align-items: center; +} diff --git a/res/css/views/auth/_LanguageSelector.scss b/res/css/views/auth/_LanguageSelector.scss index e73dd4ac64..be40c9e6cd 100644 --- a/res/css/views/auth/_LanguageSelector.scss +++ b/res/css/views/auth/_LanguageSelector.scss @@ -25,22 +25,6 @@ limitations under the License. color: $authpage-lang-color; } -/* TODO: Consider using this new arrow for all dropdowns */ -.mx_Auth_language .mx_Dropdown_arrow { - width: 10px; - height: 6px; - border: none; - right: 6px; -} - .mx_Auth_language .mx_Dropdown_arrow::before { - content: ""; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - mask: url('$(res)/img/feather-icons/dropdown-arrow.svg'); - mask-repeat: no-repeat; background: $authpage-lang-color; } diff --git a/res/css/views/elements/_Dropdown.scss b/res/css/views/elements/_Dropdown.scss index 69dd1703ee..9d4fb5c4a9 100644 --- a/res/css/views/elements/_Dropdown.scss +++ b/res/css/views/elements/_Dropdown.scss @@ -23,11 +23,12 @@ limitations under the License. } .mx_Dropdown_input { + display: flex; + align-items: center; position: relative; border-radius: 3px; border: 1px solid $strong-input-border-color; - font-weight: 300; - font-size: 13px; + font-size: 12px; user-select: none; } @@ -41,19 +42,23 @@ limitations under the License. } .mx_Dropdown_arrow { - border-color: $primary-fg-color transparent transparent; - border-style: solid; - border-width: 5px 5px 0; display: block; - height: 0; - position: absolute; - right: 10px; - top: 14px; - width: 0 + position: relative; + width: 10px; + height: 6px; + padding-right: 8px; } -.mx_Dropdown.left_aligned .mx_Dropdown_arrow { - left: 10px; +.mx_Dropdown_arrow::before { + content: ""; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + mask: url('$(res)/img/feather-icons/dropdown-arrow.svg'); + mask-repeat: no-repeat; + background: $primary-fg-color; } .mx_Dropdown_input > .mx_Dropdown_option { @@ -62,10 +67,6 @@ limitations under the License. white-space: nowrap; } -.mx_Dropdown.left_aligned .mx_Dropdown_input > .mx_Dropdown_option { - padding-left: 25px; -} - .mx_Dropdown_option { height: 35px; line-height: 35px; @@ -81,7 +82,7 @@ limitations under the License. .mx_Dropdown_option img { margin: 5px; - width: 27px; + width: 16px; vertical-align: middle; } diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 85ccecdac3..8d846112b6 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -539,7 +539,7 @@ module.exports = React.createClass({ return errorText; }, - serverComponentForStep() { + renderServerComponentForStep() { const ServerTypeSelector = sdk.getComponent("auth.ServerTypeSelector"); const ServerConfig = sdk.getComponent("auth.ServerConfig"); const ModularServerConfig = sdk.getComponent("auth.ModularServerConfig"); @@ -605,7 +605,7 @@ module.exports = React.createClass({ ; }, - loginComponentForStep() { + renderLoginComponentForStep() { if (PHASES_ENABLED && this.state.phase !== PHASE_LOGIN) { return null; } @@ -707,8 +707,8 @@ module.exports = React.createClass({ {loader} { errorTextSection } - { this.serverComponentForStep() } - { this.loginComponentForStep() } + { this.renderServerComponentForStep() } + { this.renderLoginComponentForStep() } { _t('Create account') } diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js index 3a63115a43..ca2d7716a9 100644 --- a/src/components/structures/auth/Registration.js +++ b/src/components/structures/auth/Registration.js @@ -23,13 +23,22 @@ import React from 'react'; import PropTypes from 'prop-types'; import sdk from '../../../index'; -import RegistrationForm from '../../views/auth/RegistrationForm'; import { _t, _td } from '../../../languageHandler'; import SdkConfig from '../../../SdkConfig'; import { messageForResourceLimitError } from '../../../utils/ErrorUtils'; +import * as ServerType from '../../views/auth/ServerTypeSelector'; const MIN_PASSWORD_LENGTH = 6; +// Phases +// Show controls to configure server details +const PHASE_SERVER_DETAILS = 0; +// Show the appropriate registration flow(s) for the server +const PHASE_REGISTRATION = 1; + +// Enable phases for registration +const PHASES_ENABLED = true; + module.exports = React.createClass({ displayName: 'Registration', @@ -82,6 +91,7 @@ module.exports = React.createClass({ // If we've been given a session ID, we're resuming // straight back into UI auth doingUIAuth: Boolean(this.props.sessionId), + serverType: null, hsUrl: this.props.customHsUrl, isUrl: this.props.customIsUrl, flows: null, @@ -107,6 +117,39 @@ module.exports = React.createClass({ }); }, + onServerTypeChange(type) { + this.setState({ + serverType: type, + }); + + // When changing server types, set the HS / IS URLs to reasonable defaults for the + // the new type. + switch (type) { + case ServerType.FREE: { + const { hsUrl, isUrl } = ServerType.TYPES.FREE; + this.onServerConfigChange({ + hsUrl, + isUrl, + }); + // Move directly to the registration phase since the server details are fixed. + this.setState({ + phase: PHASE_REGISTRATION, + }); + break; + } + case ServerType.PREMIUM: + case ServerType.ADVANCED: + this.onServerConfigChange({ + hsUrl: this.props.defaultHsUrl, + isUrl: this.props.defaultIsUrl, + }); + this.setState({ + phase: PHASE_SERVER_DETAILS, + }); + break; + } + }, + _replaceClient: async function() { this._matrixClient = Matrix.createClient({ baseUrl: this.state.hsUrl, @@ -273,6 +316,21 @@ module.exports = React.createClass({ this.props.onLoginClick(); }, + onServerDetailsNextPhaseClick(ev) { + ev.stopPropagation(); + this.setState({ + phase: PHASE_REGISTRATION, + }); + }, + + onEditServerDetailsClick(ev) { + ev.preventDefault(); + ev.stopPropagation(); + this.setState({ + phase: PHASE_SERVER_DETAILS, + }); + }, + _makeRegisterRequest: function(auth) { // Only send the bind params if we're sending username / pw params // (Since we need to send no params at all to use the ones saved in the @@ -300,62 +358,127 @@ module.exports = React.createClass({ }; }, + renderServerComponent() { + const ServerTypeSelector = sdk.getComponent("auth.ServerTypeSelector"); + const ServerConfig = sdk.getComponent("auth.ServerConfig"); + const ModularServerConfig = sdk.getComponent("auth.ModularServerConfig"); + const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); + + // TODO: May need to adjust the behavior of this config option + if (SdkConfig.get()['disable_custom_urls']) { + return null; + } + + // If we're on a different phase, we only show the server type selector, + // which is always shown if we allow custom URLs at all. + if (PHASES_ENABLED && this.state.phase !== PHASE_SERVER_DETAILS) { + return