From 7b7d0c16caac778f40d457bfce1d3297a05e8143 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Mon, 11 Sep 2017 19:05:48 +0300 Subject: [PATCH] Give Avatar time to load its responsive srcset stuff --- .../ProfileSettingsForm.css | 7 +++ .../ProfileSettingsForm.js | 52 ++++++++++++++++--- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/containers/ProfileSettingsForm/ProfileSettingsForm.css b/src/containers/ProfileSettingsForm/ProfileSettingsForm.css index 5097c3fc..c7237f23 100644 --- a/src/containers/ProfileSettingsForm/ProfileSettingsForm.css +++ b/src/containers/ProfileSettingsForm/ProfileSettingsForm.css @@ -223,6 +223,13 @@ padding-bottom: 100%; } +.avatarInvisible { + visibility: hidden; + position: absolute; + top: -1000px; + left: -1000px; +} + .tip { @apply --marketplaceDefaultFontStyles; color: var(--matterColorAnti); diff --git a/src/containers/ProfileSettingsForm/ProfileSettingsForm.js b/src/containers/ProfileSettingsForm/ProfileSettingsForm.js index f0bf0c89..31c96688 100644 --- a/src/containers/ProfileSettingsForm/ProfileSettingsForm.js +++ b/src/containers/ProfileSettingsForm/ProfileSettingsForm.js @@ -10,6 +10,7 @@ import { Avatar, Button, ImageFromFile, SpinnerIcon, TextInputField } from '../. import css from './ProfileSettingsForm.css'; const ACCEPT_IMAGES = 'image/*'; +const UPLOAD_CHANGE_DELAY = 2000; // Show spinner so that browser has time to load img srcset const RenderAvatar = props => { const { accept, id, input, label, type, disabled, uploadImageError } = props; @@ -59,6 +60,31 @@ RenderAvatar.propTypes = { }; class ProfileSettingsFormComponent extends Component { + constructor(props) { + super(props); + + this.uploadDelayTimeoutId = null; + this.state = { uploadDelay: false }; + } + + componentWillReceiveProps(nextProps) { + // Upload delay is additional time window where Avatar is added to the DOM, + // but not yet visible (time to load image URL from srcset) + if (this.props.uploadInProgress && !nextProps.uploadInProgress) { + this.setState({ uploadDelay: true }); + this.uploadDelayTimeoutId = window.setTimeout( + () => { + this.setState({ uploadDelay: false }); + }, + UPLOAD_CHANGE_DELAY + ); + } + } + + componentWillUnmount() { + window.clearTimeout(this.blurTimeoutId); + } + render() { const { className, @@ -104,7 +130,7 @@ class ProfileSettingsFormComponent extends Component { }); const lastNameRequired = validators.required(lastNameRequiredMessage); - const uploadingOverlay = uploadInProgress + const uploadingOverlay = uploadInProgress || this.state.uploadDelay ?
: null; @@ -112,7 +138,10 @@ class ProfileSettingsFormComponent extends Component { const errorClasses = classNames({ [css.avatarUploadError]: hasUploadError }); const transientUserProfileImage = profileImage.uploadedImage || user.profileImage; const transientUser = { ...user, profileImage: transientUserProfileImage }; - const avatarImage = uploadInProgress && profileImage.file + + const fileUploadInProgress = uploadInProgress && profileImage.file; + const delayAfterUpload = profileImage.imageId && this.state.uploadDelay; + const imageFromFile = fileUploadInProgress || delayAfterUpload ? {uploadingOverlay} - : ; + : null; - const chooseAvatarLabel = profileImage.imageId || (uploadInProgress && profileImage.file) + // Avatar is rendered in hidden during the upload delay + // Upload delay smoothes image change process: + // responsive img has time to load srcset stuff before it is shown to user. + const avatarClasses = classNames(errorClasses, { + [css.avatarInvisible]: this.state.uploadDelay, + }); + const avatarComponent = !fileUploadInProgress && profileImage.imageId + ? + : null; + + const chooseAvatarLabel = profileImage.imageId || fileUploadInProgress ?
- {avatarImage} + {imageFromFile} + {avatarComponent}
@@ -202,7 +242,7 @@ class ProfileSettingsFormComponent extends Component { ); } -}; +} ProfileSettingsFormComponent.defaultProps = { rootClassName: null,