From 4afbbd0efbbfac24a03a3f5ab2657cdd5e31d9b1 Mon Sep 17 00:00:00 2001 From: SleepWalker Date: Sun, 19 Nov 2017 22:17:23 +0200 Subject: [PATCH] #366: add loader for qr code and remove layout jumps after content was loaded --- .../multiFactorAuth/keyForm/KeyForm.js | 6 +- .../multiFactorAuth/keyForm/key-form.scss | 2 + src/components/ui/loader/ComponentLoader.js | 18 ++---- src/components/ui/loader/ImageLoader.js | 64 +++++++++++++++++++ src/components/ui/loader/imageLoader.scss | 25 ++++++++ src/components/ui/loader/index.js | 7 +- 6 files changed, 104 insertions(+), 18 deletions(-) create mode 100644 src/components/ui/loader/ImageLoader.js create mode 100644 src/components/ui/loader/imageLoader.scss diff --git a/src/components/profile/multiFactorAuth/keyForm/KeyForm.js b/src/components/profile/multiFactorAuth/keyForm/KeyForm.js index 8630685..e842cf4 100644 --- a/src/components/profile/multiFactorAuth/keyForm/KeyForm.js +++ b/src/components/profile/multiFactorAuth/keyForm/KeyForm.js @@ -5,6 +5,7 @@ import classNames from 'classnames'; import { FormattedMessage as Message } from 'react-intl'; +import { ImageLoader } from 'components/ui/loader'; import profileForm from 'components/profile/profileForm.scss'; import messages from '../MultiFactorAuth.intl.json'; @@ -14,7 +15,8 @@ export default function KeyForm({secret, qrCodeSrc}: { secret: string, qrCodeSrc: string }) { - const formattedSecret = formatSecret(secret); + // we are using invisible symbol (\u2063) as a placeholder till we get actual secret + const formattedSecret = formatSecret(secret) || '\u2063'; return (
@@ -26,7 +28,7 @@ export default function KeyForm({secret, qrCodeSrc}: {
- {secret} +
diff --git a/src/components/profile/multiFactorAuth/keyForm/key-form.scss b/src/components/profile/multiFactorAuth/keyForm/key-form.scss index 23ecb3b..ce85e01 100644 --- a/src/components/profile/multiFactorAuth/keyForm/key-form.scss +++ b/src/components/profile/multiFactorAuth/keyForm/key-form.scss @@ -1,5 +1,7 @@ .qrCode { text-align: center; + width: 242px; + margin: 0 auto; img { width: 242px; diff --git a/src/components/ui/loader/ComponentLoader.js b/src/components/ui/loader/ComponentLoader.js index 9b03919..1e41f21 100644 --- a/src/components/ui/loader/ComponentLoader.js +++ b/src/components/ui/loader/ComponentLoader.js @@ -1,14 +1,13 @@ -import PropTypes from 'prop-types'; +// @flow +import type { Skin } from 'components/ui'; import React from 'react'; - import classNames from 'classnames'; -import { skins, SKIN_DARK } from 'components/ui'; - import styles from './componentLoader.scss'; -export default function ComponentLoader(props) { - const {skin} = props; +export default function ComponentLoader({ skin }: { + skin: Skin, +}) { return (
@@ -20,11 +19,6 @@ export default function ComponentLoader(props) { ); } - -ComponentLoader.propTypes = { - skin: PropTypes.oneOf(skins), -}; - ComponentLoader.defaultProps = { - skin: SKIN_DARK + skin: 'dark' }; diff --git a/src/components/ui/loader/ImageLoader.js b/src/components/ui/loader/ImageLoader.js new file mode 100644 index 0000000..e156090 --- /dev/null +++ b/src/components/ui/loader/ImageLoader.js @@ -0,0 +1,64 @@ +// @flow +import React from 'react'; +import classNames from 'classnames'; +import { ComponentLoader } from 'components/ui/loader'; + +import styles from './imageLoader.scss'; + +export default class ImageLoader extends React.Component<{ + src: string, + alt: string, + ratio: number, // width:height ratio + onLoad?: Function, +}, { + isLoading: bool +}> { + state = { + isLoading: true + }; + + componentWillMount() { + this.preloadImage(); + } + + preloadImage() { + const img = new Image(); + img.onload = () => this.imageLoaded(); + img.onerror = () => this.preloadImage(); + img.src = this.props.src; + } + + imageLoaded() { + this.setState({ isLoading: false }); + + if (this.props.onLoad) { + this.props.onLoad(); + } + } + + render() { + const { isLoading } = this.state; + const { src, alt, ratio } = this.props; + + return ( +
+
+ + {isLoading && ( +
+ +
+ )} + +
+ {alt} +
+
+ ); + } +} diff --git a/src/components/ui/loader/imageLoader.scss b/src/components/ui/loader/imageLoader.scss new file mode 100644 index 0000000..76d55ed --- /dev/null +++ b/src/components/ui/loader/imageLoader.scss @@ -0,0 +1,25 @@ +.container { + position: relative; + z-index: 1; +} + +.loader { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.image { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + + opacity: 0; + transition: 0.4s ease-in; +} + +.imageLoaded { + opacity: 1; +} diff --git a/src/components/ui/loader/index.js b/src/components/ui/loader/index.js index c1db8c6..18d2bb2 100644 --- a/src/components/ui/loader/index.js +++ b/src/components/ui/loader/index.js @@ -1,5 +1,4 @@ -import ComponentLoader from './ComponentLoader'; +// @flow -export { - ComponentLoader -}; +export {default as ImageLoader} from './ImageLoader'; +export {default as ComponentLoader} from './ComponentLoader';