From 978f76068bc7aa58f62f98576bac43f917c75429 Mon Sep 17 00:00:00 2001 From: meriadec Date: Thu, 7 Jun 2018 18:22:47 +0200 Subject: [PATCH] Feedbacks integration on sync state --- src/components/TopBar/ActivityIndicator.js | 120 +++++++++++---------- src/components/TopBar/ItemContainer.js | 9 +- src/components/TopBar/index.js | 1 + src/config/constants.js | 2 +- 4 files changed, 72 insertions(+), 60 deletions(-) diff --git a/src/components/TopBar/ActivityIndicator.js b/src/components/TopBar/ActivityIndicator.js index ef061b71..e88e900b 100644 --- a/src/components/TopBar/ActivityIndicator.js +++ b/src/components/TopBar/ActivityIndicator.js @@ -20,39 +20,48 @@ import IconExclamationCircle from 'icons/ExclamationCircle' import IconCheckCircle from 'icons/CheckCircle' import ItemContainer from './ItemContainer' -const DISPLAY_SUCCESS_TIME = 2 * 1000 - const mapStateToProps = createStructuredSelector({ globalSyncState: globalSyncStateSelector }) -type Props = { isPending: boolean, isError: boolean, onClick: void => void, t: T } -type State = { hasClicked: boolean, displaySuccess: boolean } +type Props = { + // FIXME: eslint should see that it is used in static method + isGlobalSyncStatePending: boolean, // eslint-disable-line react/no-unused-prop-types + + isPending: boolean, + isError: boolean, + onClick: void => void, + t: T, +} + +type State = { + hasClicked: boolean, + isGlobalSyncStatePending: boolean, + isFirstSync: boolean, +} class ActivityIndicatorInner extends Component { state = { hasClicked: false, - displaySuccess: false, - } + isFirstSync: true, - _timeout = null + // FIXME: eslint should see that it is used in static method + isGlobalSyncStatePending: false, // eslint-disable-line react/no-unused-state + } static getDerivedStateFromProps(nextProps: Props, prevState: State) { - if (prevState.hasClicked && !nextProps.isPending) { - return { hasClicked: false, displaySuccess: !nextProps.isError } + const nextState = { + ...prevState, + isGlobalSyncStatePending: nextProps.isGlobalSyncStatePending, } - return null - } + if (prevState.hasClicked && !nextProps.isGlobalSyncStatePending) { + nextState.hasClicked = false + } - componentDidUpdate(prevProps: Props, prevState: State) { - if (!prevState.displaySuccess && this.state.displaySuccess) { - if (this._timeout) { - clearTimeout(this._timeout) - } - this._timeout = setTimeout( - () => this.setState({ displaySuccess: false }), - DISPLAY_SUCCESS_TIME, - ) + if (prevState.isGlobalSyncStatePending && !nextProps.isGlobalSyncStatePending) { + nextState.isFirstSync = false } + + return nextState } handleRefresh = () => { @@ -63,51 +72,51 @@ class ActivityIndicatorInner extends Component { render() { const { isPending, isError, t } = this.props - const { hasClicked, displaySuccess } = this.state - const isDisabled = hasClicked || displaySuccess || isError + const { hasClicked, isFirstSync } = this.state + const isDisabled = hasClicked || isError + const isRotating = isPending && (hasClicked || isFirstSync) + return ( {isError ? ( - ) : displaySuccess ? ( - - ) : ( + ) : isRotating ? ( + ) : ( + )} - {(displaySuccess || isError || (isPending && hasClicked)) && ( - - {displaySuccess ? ( - t('common:sync.upToDate') - ) : isError ? ( - - {t('common:sync.error')} - - {t('common:sync.refresh')} - - - ) : ( - t('common:sync.syncing') - )} - - )} + + {isRotating ? ( + t('common:sync.syncing') + ) : isError ? ( + + {t('common:sync.error')} + + {t('common:sync.refresh')} + + + ) : ( + t('common:sync.upToDate') + )} + ) } @@ -124,6 +133,7 @@ const ActivityIndicator = ({ globalSyncState, t }: { globalSyncState: AsyncState { cvPolling.poll() diff --git a/src/components/TopBar/ItemContainer.js b/src/components/TopBar/ItemContainer.js index 70c958df..f0b693d0 100644 --- a/src/components/TopBar/ItemContainer.js +++ b/src/components/TopBar/ItemContainer.js @@ -12,17 +12,18 @@ export default styled(Tabbable).attrs({ alignItems: 'center', cursor: p => (p.isDisabled ? 'default' : 'pointer'), horizontal: true, + borderRadius: 1, })` - min-height: 40px; + height: 40px; border: 1px dashed transparent; &:hover { - color: ${p => (p.isDisabled ? '' : p.theme.colors.wallet)}; - background: ${p => (p.isDisabled ? '' : rgba(p.theme.colors.wallet, 0.05))}; + color: ${p => (p.isDisabled ? '' : p.theme.colors.dark)}; + background: ${p => (p.isDisabled ? '' : rgba(p.theme.colors.fog, 0.2))}; } &:active { - background: ${p => (p.isDisabled ? '' : rgba(p.theme.colors.wallet, 0.1))}; + background: ${p => (p.isDisabled ? '' : rgba(p.theme.colors.fog, 0.3))}; } &:focus { diff --git a/src/components/TopBar/index.js b/src/components/TopBar/index.js index 9db8c194..19faec18 100644 --- a/src/components/TopBar/index.js +++ b/src/components/TopBar/index.js @@ -38,6 +38,7 @@ const Inner = styled(Box).attrs({ horizontal: true, grow: true, flow: 4, + align: 'center', })` border-bottom: 1px solid ${p => p.theme.colors.fog}; ` diff --git a/src/config/constants.js b/src/config/constants.js index 82762d5b..6fc7c4b6 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -1,6 +1,6 @@ // @flow -export const SYNC_BOOT_DELAY = 5 * 1000 +export const SYNC_BOOT_DELAY = 2 * 1000 export const SYNC_INTERVAL = 30 * 1000 export const CHECK_APP_INTERVAL_WHEN_INVALID = 600 export const CHECK_APP_INTERVAL_WHEN_VALID = 1200