phone editing widget works
This commit is contained in:
@@ -32,7 +32,8 @@ export default class CreateAccountView extends React.PureComponent {
|
||||
newAvatarMime: null,
|
||||
errorCleared: false,
|
||||
buttonDisabled: false,
|
||||
method: '',
|
||||
// method: '',
|
||||
method: 'tel',
|
||||
saveToken: LocalStorageUtil.getObject('keep-logged-in')
|
||||
};
|
||||
|
||||
@@ -53,7 +54,7 @@ export default class CreateAccountView extends React.PureComponent {
|
||||
this.props.onError(err.message, 'err');
|
||||
})
|
||||
// "reqCred":{"auth":["email"]}
|
||||
.finally(_ => this.setState({method: (props.tinode.getServerParam('reqCred', {}).auth || [])[0] || 'email'}));
|
||||
//.finally(_ => this.setState({method: (props.tinode.getServerParam('reqCred', {}).auth || [])[0] || 'email'}));
|
||||
}
|
||||
|
||||
handleLoginChange(e) {
|
||||
@@ -61,7 +62,7 @@ export default class CreateAccountView extends React.PureComponent {
|
||||
}
|
||||
|
||||
handlePasswordChange(password) {
|
||||
this.setState({meth: 'tel', password: password});
|
||||
this.setState({password: password});
|
||||
}
|
||||
|
||||
handleEmailChange(e) {
|
||||
@@ -69,7 +70,8 @@ export default class CreateAccountView extends React.PureComponent {
|
||||
}
|
||||
|
||||
handlePhoneChange(number) {
|
||||
this.setState({tel: number});
|
||||
console.log('handlePhoneChange', number)
|
||||
this.setState({meth: 'tel', tel: number});
|
||||
}
|
||||
|
||||
handleFnChange(e) {
|
||||
@@ -209,8 +211,8 @@ export default class CreateAccountView extends React.PureComponent {
|
||||
description="Message shown when component is loading"/></div>}>
|
||||
<PhoneEdit
|
||||
autoFocus={false}
|
||||
onShowCountrySelector={(code, dial) => console.log('onShowCountrySelector', code, dial)}
|
||||
onSubmit={(code, dial) => console.log('onSubmit', code, dial)} />
|
||||
onShowCountrySelector={this.props.onShowCountrySelector}
|
||||
onSubmit={this.handlePhoneChange} />
|
||||
</Suspense>
|
||||
</div></>
|
||||
: null
|
||||
|
||||
@@ -157,6 +157,7 @@ class SidepanelView extends React.PureComponent {
|
||||
view === 'register' ?
|
||||
<CreateAccountView
|
||||
tinode={this.props.tinode}
|
||||
onShowCountrySelector={this.props.onShowCountrySelector}
|
||||
onCreateAccount={this.props.onCreateAccount}
|
||||
onCancel={this.props.onCancel}
|
||||
onError={this.props.onError} /> :
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// The top-level class to hold all functionality together.
|
||||
import React from 'react';
|
||||
import React, { Suspense } from 'react';
|
||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
import { initializeApp as firebaseInitApp } from 'firebase/app';
|
||||
@@ -12,6 +12,7 @@ import Alert from '../widgets/alert.jsx';
|
||||
import ContextMenu from '../widgets/context-menu.jsx';
|
||||
import ForwardDialog from '../widgets/forward-dialog.jsx';
|
||||
import CallIncoming from '../widgets/call-incoming.jsx';
|
||||
const PhoneCountrySelector = React.lazy(_ => import('../widgets/phone-country-selector.jsx'));
|
||||
|
||||
import InfoView from './info-view.jsx';
|
||||
import MessagesView from './messages-view.jsx';
|
||||
@@ -158,6 +159,7 @@ class TinodeWeb extends React.Component {
|
||||
this.handlePasswordResetRequest = this.handlePasswordResetRequest.bind(this);
|
||||
this.handleResetPassword = this.handleResetPassword.bind(this);
|
||||
this.handleContextMenuAction = this.handleContextMenuAction.bind(this);
|
||||
this.handleShowCountrySelector = this.handleShowCountrySelector.bind(this);
|
||||
|
||||
this.handleShowForwardDialog = this.handleShowForwardDialog.bind(this);
|
||||
this.handleHideForwardDialog = this.handleHideForwardDialog.bind(this);
|
||||
@@ -1725,6 +1727,22 @@ class TinodeWeb extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleShowCountrySelector(code, dial, selectedCallback) {
|
||||
console.log('handleShowCountrySelector', code, dial);
|
||||
this.handleShowAlert("Select country",
|
||||
<Suspense fallback={<div><FormattedMessage id="loading_note" defaultMessage="Loading..."
|
||||
description="Message shown when component is loading"/></div>}>
|
||||
<PhoneCountrySelector
|
||||
selected={code}
|
||||
onSubmit={(c, d) => {
|
||||
console.log("handleShowCountrySelector click", c, d);
|
||||
this.setState({alertVisible: false});
|
||||
selectedCallback(c, d);
|
||||
}} />
|
||||
</Suspense>,
|
||||
null, null, _ => {}, "Cancel");
|
||||
}
|
||||
|
||||
handleStartVideoCall() {
|
||||
this.setState({
|
||||
callTopic: this.state.topicSelected,
|
||||
@@ -1954,12 +1972,12 @@ class TinodeWeb extends React.Component {
|
||||
}
|
||||
{this.state.alertVisible ?
|
||||
<Alert
|
||||
visible={this.state.alertVisible}
|
||||
title={this.state.alertParams.title}
|
||||
content={this.state.alertParams.content}
|
||||
onReject={this.state.alertParams.onReject ? (_ => this.setState({alertVisible: false})) : null}
|
||||
reject={this.state.alertParams.reject}
|
||||
onConfirm={_ => {this.setState({alertVisible: false}); this.state.alertParams.onConfirm();}}
|
||||
onConfirm={this.state.alertParams.onConfirm ?
|
||||
(_ => {this.setState({alertVisible: false}); this.state.alertParams.onConfirm();}) : null}
|
||||
confirm={this.state.alertParams.confirm}
|
||||
/> : null}
|
||||
<SidepanelView
|
||||
@@ -2025,6 +2043,7 @@ class TinodeWeb extends React.Component {
|
||||
onResetPassword={this.handleResetPassword}
|
||||
onShowArchive={this.handleShowArchive}
|
||||
onShowBlocked={this.handleShowBlocked}
|
||||
onShowCountrySelector={this.handleShowCountrySelector}
|
||||
|
||||
onInitFind={this.tnInitFind}
|
||||
searchResults={this.state.searchResults}
|
||||
|
||||
@@ -15,9 +15,13 @@ export default class Alert extends React.PureComponent {
|
||||
:
|
||||
null
|
||||
}
|
||||
<button className="primary" onClick={this.props.onConfirm}>
|
||||
{this.props.confirm || <FormattedMessage id="button_ok" defaultMessage="OK" description="Button [OK]" />}
|
||||
</button>
|
||||
{this.props.onConfirm ?
|
||||
<button className="primary" onClick={this.props.onConfirm}>
|
||||
{this.props.confirm || <FormattedMessage id="button_ok" defaultMessage="OK" description="Button [OK]" />}
|
||||
</button>
|
||||
:
|
||||
null
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
|
||||
@@ -1,39 +1,47 @@
|
||||
// Selector for country dialing code.
|
||||
|
||||
import React from 'react';
|
||||
import { FormattedDisplayName } from 'react-intl';
|
||||
import { injectIntl } from 'react-intl';
|
||||
|
||||
import * as dcodes from '../dcodes.json';
|
||||
|
||||
import { flagEmoji } from '../lib/strformat';
|
||||
|
||||
export default class PhoneCountrySelector extends React.PureComponent {
|
||||
class PhoneCountrySelector extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.codeMap = {};
|
||||
dcodes.default.forEach(dc => { this.codeMap[dc.code] = dc.dial; });
|
||||
this.countries = [];
|
||||
const { formatDisplayName } = props.intl;
|
||||
dcodes.default.forEach(dc => {
|
||||
const parts = dc.dial.split(',');
|
||||
parts.forEach(part => {
|
||||
this.countries.push({
|
||||
dial: part.trim(),
|
||||
code: dc.code,
|
||||
flag: flagEmoji(dc.code),
|
||||
name: formatDisplayName(dc.code, {type: 'region'})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
handleClick(e) {
|
||||
e.preventDefault();
|
||||
this.props.onSubmit(e.target.dataset.code, e.target.dataset.dial);
|
||||
this.countries.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
|
||||
render() {
|
||||
const countries = [];
|
||||
const selected = this.props.selected || 'US';
|
||||
dcodes.default.forEach((dc, idx) => {
|
||||
const style = (dc.code == selected ? 'selected ' : '');
|
||||
countries.push(<li className={style} key={idx} data-code={dc.code} data-dial={dc.dial} onClick={this.handleClick}>
|
||||
<span className="country-flag">{flagEmoji(dc.code)}</span>
|
||||
<FormattedDisplayName type="region" value={dc.code} />
|
||||
<span className="dial-code">+{dc.dial}</span>
|
||||
this.countries.forEach((c, idx) => {
|
||||
const style = (c.code == selected ? 'selected ' : '');
|
||||
countries.push(<li className={style} key={idx} onClick={_ => this.props.onSubmit(c.code, c.dial)}>
|
||||
<span className="country-flag">{c.flag}</span>
|
||||
<span className="country"> {c.name}</span>
|
||||
<span className="dial-code"> +{c.dial}</span>
|
||||
</li>);
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="scrollable-panel">
|
||||
<div className="scrollable-panel" style={{height: '30rem'}}>
|
||||
<ul className="phone-country-selector">
|
||||
{countries}
|
||||
</ul>
|
||||
@@ -41,3 +49,5 @@ export default class PhoneCountrySelector extends React.PureComponent {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(PhoneCountrySelector);
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
import React from 'react';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { getExampleNumber, parsePhoneNumber } from 'libphonenumber-js/mobile';
|
||||
import examples from 'libphonenumber-js/mobile/examples'
|
||||
|
||||
import * as dcodes from '../dcodes.json';
|
||||
import { flagEmoji } from '../lib/strformat';
|
||||
|
||||
@@ -12,10 +15,14 @@ class PhoneEdit extends React.PureComponent {
|
||||
this.codeMap = {};
|
||||
dcodes.default.forEach(dc => { this.codeMap[dc.code] = dc.dial; });
|
||||
|
||||
const code = props.countryCode || 'US';
|
||||
const dial = this.codeMap[code];
|
||||
|
||||
this.state = {
|
||||
countryCode: props.countryCode || 'US',
|
||||
dialCode: this.codeMap[props.countryCode || 'US'],
|
||||
localNumber: ''
|
||||
countryCode: code,
|
||||
dialCode: dial,
|
||||
localNumber: '',
|
||||
placeholderNumber: this.placeholderNumber(code, dial)
|
||||
};
|
||||
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
@@ -29,10 +36,18 @@ class PhoneEdit extends React.PureComponent {
|
||||
}
|
||||
|
||||
handleFinished(e) {
|
||||
// this.setCustomValidity("Mobile phone number required");
|
||||
e.preventDefault();
|
||||
const number = `${this.state.dialCode}${this.state.localNumber.trim()}`.replace(/[^\d]/g, '')
|
||||
this.props.onSubmit(`+${number}`);
|
||||
const raw = `${this.state.dialCode}${this.state.localNumber.trim()}`.replace(/[^\d]/g, '')
|
||||
let number = null;
|
||||
try {
|
||||
number = parsePhoneNumber(raw);
|
||||
} catch (err) {}
|
||||
|
||||
if (!number || !number.isValid()) {
|
||||
this.inputField.setCustomValidity("Mobile phone number required");
|
||||
return;
|
||||
}
|
||||
this.props.onSubmit(number.format('E.164'));
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +58,15 @@ class PhoneEdit extends React.PureComponent {
|
||||
}
|
||||
|
||||
showCountrySelector() {
|
||||
this.props.onShowCountrySelector(this.state.countryCode, this.state.dialCode);
|
||||
this.props.onShowCountrySelector(this.state.countryCode, this.state.dialCode,
|
||||
(code, dial) => {
|
||||
console.log('Callback', code, dial);
|
||||
this.setState({
|
||||
countryCode: code,
|
||||
dialCode: dial,
|
||||
placeholderNumber: this.placeholderNumber(code, dial)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// Filter out characters not permitted in a phone number.
|
||||
@@ -56,13 +79,20 @@ class PhoneEdit extends React.PureComponent {
|
||||
return number.replace(/[^-\s().\d]/g, '');
|
||||
}
|
||||
|
||||
placeholderNumber(code, dial) {
|
||||
console.log('In nplaceholder', code, dial);
|
||||
const number = getExampleNumber(code, examples).formatInternational();
|
||||
return number.substring(dial.length + 1).trim();
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log('placeholder:', this.state.placeholderNumber);
|
||||
return (
|
||||
<>
|
||||
<span className="dial-code" onClick={this.showCountrySelector}>
|
||||
<span className="country-flag">{flagEmoji(this.state.countryCode)} </span>
|
||||
+{this.state.dialCode} </span>
|
||||
<input type="tel" placeholder={this.state.placeholder}
|
||||
<input type="tel" ref={ref => {this.inputField = ref}} placeholder={this.state.placeholderNumber}
|
||||
value={this.state.localNumber} onChange={this.handleChange}
|
||||
maxLength={17} onKeyDown={this.handleKeyDown} onBlur={this.handleFinished}
|
||||
required autoFocus={this.props.autoFocus} />
|
||||
|
||||
Reference in New Issue
Block a user