From 336462366e033a43ac76c133bd74dea1b0222c35 Mon Sep 17 00:00:00 2001
From: Luke Barnard <lukeb@openmarket.com>
Date: Tue, 25 Apr 2017 11:21:47 +0100
Subject: [PATCH] Improve country dropdown UX and expose +prefix

A prefix is now exposed through a change to the API for onOptionChange. This now returns the entire country object which includes iso2, prefix etc.

This also shows the prefix in the Registration and Login screens as a prefix to the phone number field.
---
 src/components/views/login/CountryDropdown.js | 18 +++++++--
 src/components/views/login/PasswordLogin.js   | 40 +++++++++++--------
 .../views/login/RegistrationForm.js           | 28 ++++++++-----
 .../views/settings/AddPhoneNumber.js          |  7 ++--
 4 files changed, 61 insertions(+), 32 deletions(-)

diff --git a/src/components/views/login/CountryDropdown.js b/src/components/views/login/CountryDropdown.js
index 7f6b21650d..da4e770093 100644
--- a/src/components/views/login/CountryDropdown.js
+++ b/src/components/views/login/CountryDropdown.js
@@ -37,6 +37,7 @@ export default class CountryDropdown extends React.Component {
     constructor(props) {
         super(props);
         this._onSearchChange = this._onSearchChange.bind(this);
+        this._onOptionChange = this._onOptionChange.bind(this);
 
         this.state = {
             searchQuery: '',
@@ -48,7 +49,7 @@ export default class CountryDropdown extends React.Component {
             // If no value is given, we start with the first
             // country selected, but our parent component
             // doesn't know this, therefore we do this.
-            this.props.onOptionChange(COUNTRIES[0].iso2);
+            this.props.onOptionChange(COUNTRIES[0]);
         }
     }
 
@@ -58,6 +59,10 @@ export default class CountryDropdown extends React.Component {
         });
     }
 
+    _onOptionChange(iso2) {
+        this.props.onOptionChange(COUNTRIES_BY_ISO2[iso2]);
+    }
+
     _flagImgForIso2(iso2) {
         // Unicode Regional Indicator Symbol letter 'A'
         const RIS_A = 0x1F1E6;
@@ -68,6 +73,10 @@ export default class CountryDropdown extends React.Component {
         );
     }
 
+    getCountryPrefix(iso2) {
+        return COUNTRIES_BY_ISO2[iso2].prefix;
+    }
+
     render() {
         const Dropdown = sdk.getComponent('elements.Dropdown');
 
@@ -102,9 +111,11 @@ export default class CountryDropdown extends React.Component {
         // values between mounting and the initial value propgating
         const value = this.props.value || COUNTRIES[0].iso2;
 
+        const getShortOption = this.props.isSmall ? this._flagImgForIso2 : undefined;
+
         return <Dropdown className={this.props.className}
-            onOptionChange={this.props.onOptionChange} onSearchChange={this._onSearchChange}
-            menuWidth={298} getShortOption={this._flagImgForIso2}
+            onOptionChange={this._onOptionChange} onSearchChange={this._onSearchChange}
+            menuWidth={298} getShortOption={getShortOption}
             value={value} searchEnabled={true}
         >
             {options}
@@ -114,6 +125,7 @@ export default class CountryDropdown extends React.Component {
 
 CountryDropdown.propTypes = {
     className: React.PropTypes.string,
+    isSmall: React.PropTypes.bool,
     onOptionChange: React.PropTypes.func.isRequired,
     value: React.PropTypes.string,
 };
diff --git a/src/components/views/login/PasswordLogin.js b/src/components/views/login/PasswordLogin.js
index 568461817c..349dd0d139 100644
--- a/src/components/views/login/PasswordLogin.js
+++ b/src/components/views/login/PasswordLogin.js
@@ -90,8 +90,11 @@ class PasswordLogin extends React.Component {
     }
 
     onPhoneCountryChanged(country) {
-        this.setState({phoneCountry: country});
-        this.props.onPhoneCountryChanged(country);
+        this.setState({
+            phoneCountry: country.iso2,
+            phonePrefix: country.prefix,
+        });
+        this.props.onPhoneCountryChanged(country.iso2);
     }
 
     onPhoneNumberChanged(ev) {
@@ -121,16 +124,17 @@ class PasswordLogin extends React.Component {
                 const mxidInputClasses = classNames({
                     "mx_Login_field": true,
                     "mx_Login_username": true,
+                    "mx_Login_field_has_prefix": true,
                     "mx_Login_field_has_suffix": Boolean(this.props.hsDomain),
                 });
                 let suffix = null;
                 if (this.props.hsDomain) {
-                    suffix = <div className="mx_Login_username_suffix">
+                    suffix = <div className="mx_Login_field_suffix">
                         :{this.props.hsDomain}
                     </div>;
                 }
-                return <div className="mx_Login_username_group">
-                    <div className="mx_Login_username_prefix">@</div>
+                return <div className="mx_Login_field_group">
+                    <div className="mx_Login_field_prefix">@</div>
                     <input
                         className={mxidInputClasses}
                         key="username_input"
@@ -145,6 +149,7 @@ class PasswordLogin extends React.Component {
                 </div>;
             case PasswordLogin.LOGIN_FIELD_PHONE:
                 const CountryDropdown = sdk.getComponent('views.login.CountryDropdown');
+                const prefix = this.state.phonePrefix;
                 return <div className="mx_Login_phoneSection">
                     <CountryDropdown
                         className="mx_Login_phoneCountry"
@@ -152,17 +157,20 @@ class PasswordLogin extends React.Component {
                         onOptionChange={this.onPhoneCountryChanged}
                         value={this.state.phoneCountry}
                     />
-                    <input
-                        className="mx_Login_phoneNumberField mx_Login_field"
-                        ref="phoneNumber"
-                        key="phone_input"
-                        type="text"
-                        name="phoneNumber"
-                        onChange={this.onPhoneNumberChanged}
-                        placeholder="Mobile phone number"
-                        value={this.state.phoneNumber}
-                        autoFocus
-                    />
+                    <div className="mx_Login_field_group">
+                        <div className="mx_Login_field_prefix">+{prefix}</div>
+                        <input
+                            className="mx_Login_phoneNumberField mx_Login_field mx_Login_field_has_prefix"
+                            ref="phoneNumber"
+                            key="phone_input"
+                            type="text"
+                            name="phoneNumber"
+                            onChange={this.onPhoneNumberChanged}
+                            placeholder="Mobile phone number"
+                            value={this.state.phoneNumber}
+                            autoFocus
+                        />
+                    </div>
                 </div>;
         }
     }
diff --git a/src/components/views/login/RegistrationForm.js b/src/components/views/login/RegistrationForm.js
index 4868c9de63..a0b56e30ac 100644
--- a/src/components/views/login/RegistrationForm.js
+++ b/src/components/views/login/RegistrationForm.js
@@ -270,7 +270,8 @@ module.exports = React.createClass({
 
     _onPhoneCountryChange(newVal) {
         this.setState({
-            phoneCountry: newVal,
+            phoneCountry: newVal.iso2,
+            phonePrefix: newVal.prefix,
         });
     },
 
@@ -316,15 +317,22 @@ module.exports = React.createClass({
                     className="mx_Login_phoneCountry"
                     value={this.state.phoneCountry}
                 />
-                <input type="text" ref="phoneNumber"
-                    placeholder="Mobile phone number (optional)"
-                    defaultValue={this.props.defaultPhoneNumber}
-                    className={this._classForField(
-                        FIELD_PHONE_NUMBER, 'mx_Login_phoneNumberField', 'mx_Login_field'
-                    )}
-                    onBlur={function() {self.validateField(FIELD_PHONE_NUMBER);}}
-                    value={self.state.phoneNumber}
-                />
+
+                <div className="mx_Login_field_group">
+                    <div className="mx_Login_field_prefix">+{this.state.phonePrefix}</div>
+                    <input type="text" ref="phoneNumber"
+                        placeholder="Mobile phone number (optional)"
+                        defaultValue={this.props.defaultPhoneNumber}
+                        className={this._classForField(
+                            FIELD_PHONE_NUMBER,
+                            'mx_Login_phoneNumberField',
+                            'mx_Login_field',
+                            'mx_Login_field_has_prefix'
+                        )}
+                        onBlur={function() {self.validateField(FIELD_PHONE_NUMBER);}}
+                        value={self.state.phoneNumber}
+                    />
+                </div>
             </div>
         );
 
diff --git a/src/components/views/settings/AddPhoneNumber.js b/src/components/views/settings/AddPhoneNumber.js
index 3a348393aa..35dd5548d1 100644
--- a/src/components/views/settings/AddPhoneNumber.js
+++ b/src/components/views/settings/AddPhoneNumber.js
@@ -50,7 +50,7 @@ export default WithMatrixClient(React.createClass({
     },
 
     _onPhoneCountryChange: function(phoneCountry) {
-        this.setState({ phoneCountry: phoneCountry });
+        this.setState({ phoneCountry: phoneCountry.iso2 });
     },
 
     _onPhoneNumberChange: function(ev) {
@@ -149,10 +149,11 @@ export default WithMatrixClient(React.createClass({
                 <div className="mx_UserSettings_profileLabelCell">
                 </div>
                 <div className="mx_UserSettings_profileInputCell">
-                    <div className="mx_Login_phoneSection">
+                    <div className="mx_UserSettings_phoneSection">
                         <CountryDropdown onOptionChange={this._onPhoneCountryChange}
-                            className="mx_Login_phoneCountry"
+                            className="mx_UserSettings_phoneCountry"
                             value={this.state.phoneCountry}
+                            isSmall={true}
                         />
                         <input type="text"
                             ref={this._collectAddMsisdnInput}