// Account registration. import React from 'react'; import { FormattedMessage } from 'react-intl'; import AvatarCrop from '../widgets/avatar-crop.jsx'; import AvatarUpload from '../widgets/avatar-upload.jsx'; import CheckBox from '../widgets/checkbox.jsx'; import VisiblePassword from '../widgets/visible-password.jsx'; import LocalStorageUtil from '../lib/local-storage.js'; import { imageScaled, blobToBase64, makeImageUrl } from '../lib/blob-helpers.js'; import { theCard } from '../lib/utils.js'; import { AVATAR_SIZE, MAX_AVATAR_BYTES, MAX_EXTERN_ATTACHMENT_SIZE, MAX_TITLE_LENGTH } from '../config.js'; export default class CreateAccountView extends React.PureComponent { constructor(props) { super(props); this.state = { login: '', password: '', email: '', fn: '', // full/formatted name imageUrl: null, uploadUrl: null, newAvatar: null, newAvatarMime: null, errorCleared: false, buttonDisabled: false, saveToken: LocalStorageUtil.getObject('keep-logged-in') }; this.handleLoginChange = this.handleLoginChange.bind(this); this.handlePasswordChange = this.handlePasswordChange.bind(this); this.handleEmailChange = this.handleEmailChange.bind(this); this.handleFnChange = this.handleFnChange.bind(this); this.handleImageChanged = this.handleImageChanged.bind(this); this.handleToggleSaveToken = this.handleToggleSaveToken.bind(this); this.handleAvatarCropped = this.handleAvatarCropped.bind(this); this.handleAvatarCropCancel = this.handleAvatarCropCancel.bind(this); this.uploadAvatar = this.uploadAvatar.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleLoginChange(e) { this.setState({login: e.target.value}); } handlePasswordChange(password) { this.setState({password: password}); } handleEmailChange(e) { this.setState({email: e.target.value}) } handleFnChange(e) { this.setState({fn: e.target.value}); } handleImageChanged(mime, img) { this.setState({newAvatar: img, newAvatarMime: mime}); } handleToggleSaveToken() { LocalStorageUtil.setObject('keep-logged-in', !this.state.saveToken); this.setState({saveToken: !this.state.saveToken}); } handleSubmit(e) { e.preventDefault(); this.setState({errorCleared: false}); this.props.onCreateAccount( this.state.login.trim(), this.state.password.trim(), theCard(this.state.fn.trim().substring(0, MAX_TITLE_LENGTH), this.state.uploadUrl), {'meth': 'email', 'val': this.state.email}); } // AvatarCropView calls this method when the user has cropped the image. handleAvatarCropped(mime, blob, width, height) { const url = blob ? URL.createObjectURL(blob) : null; this.setState({avatar: url, newAvatar: null, newAvatarMime: null}); if (blob) { this.uploadAvatar(mime, blob, width, height); } } handleAvatarCropCancel() { this.setState({newAvatar: null, newAvatarMime: null}); } // Utility method for converting cropped avatar blob to bytes for sending inband or // for uploading it to the server out of band. uploadAvatar(mime, blob, width, height) { const readyToUpload = (image) => { let {mime, blob} = image; this.setState({imageUrl: URL.createObjectURL(blob), buttonDisabled: true}); if (blob.size > MAX_AVATAR_BYTES) { // Too large to send inband - uploading out of band and sending as a link. const uploader = this.props.tinode.getLargeFileHelper(); uploader.upload(blob, 'newacc') .then(url => this.setState({uploadUrl: url})) .catch(err => this.props.onError(err.message, 'err')) .finally(_ => this.setState({buttonDisabled: false})); } else { // Convert blob to base64-encoded bits. blobToBase64(blob) .then(b64 => this.setState({uploadUrl: makeImageUrl({data: b64.bits, type: mime})})) .finally(_ => this.setState({buttonDisabled: false})); } }; if (width > AVATAR_SIZE || height > AVATAR_SIZE || width != height) { // Avatar is not square or too large even after cropping. Shrink it and make square. imageScaled(blob, AVATAR_SIZE, AVATAR_SIZE, MAX_EXTERN_ATTACHMENT_SIZE, true) .then(scaled => readyToUpload(scaled)) .catch(err => this.props.onError(err.message, 'err')); } else { readyToUpload({mime: mime, blob: blob, width: width, height: height}); } } render() { if (this.state.newAvatar) { return ( ); } let submitClasses = 'primary'; if (this.props.disabled) { submitClasses += ' disabled'; } return (
{ (login_prompt) => } { (password_prompt) => }
{ (full_name_prompt) => }
{ (email_prompt) => }
{ (stay_logged_in) => }
); } };