Skip to content
This repository was archived by the owner on Jun 16, 2022. It is now read-only.

Commit 926792c

Browse files
authored
Merge pull request #474 from meriadec/design/sync-state-feedbacks
Feedbacks integration on sync state
2 parents 808607c + 978f760 commit 926792c

File tree

4 files changed

+72
-60
lines changed

4 files changed

+72
-60
lines changed

src/components/TopBar/ActivityIndicator.js

Lines changed: 65 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -20,39 +20,48 @@ import IconExclamationCircle from 'icons/ExclamationCircle'
2020
import IconCheckCircle from 'icons/CheckCircle'
2121
import ItemContainer from './ItemContainer'
2222

23-
const DISPLAY_SUCCESS_TIME = 2 * 1000
24-
2523
const mapStateToProps = createStructuredSelector({ globalSyncState: globalSyncStateSelector })
2624

27-
type Props = { isPending: boolean, isError: boolean, onClick: void => void, t: T }
28-
type State = { hasClicked: boolean, displaySuccess: boolean }
25+
type Props = {
26+
// FIXME: eslint should see that it is used in static method
27+
isGlobalSyncStatePending: boolean, // eslint-disable-line react/no-unused-prop-types
28+
29+
isPending: boolean,
30+
isError: boolean,
31+
onClick: void => void,
32+
t: T,
33+
}
34+
35+
type State = {
36+
hasClicked: boolean,
37+
isGlobalSyncStatePending: boolean,
38+
isFirstSync: boolean,
39+
}
2940

3041
class ActivityIndicatorInner extends Component<Props, State> {
3142
state = {
3243
hasClicked: false,
33-
displaySuccess: false,
34-
}
44+
isFirstSync: true,
3545

36-
_timeout = null
46+
// FIXME: eslint should see that it is used in static method
47+
isGlobalSyncStatePending: false, // eslint-disable-line react/no-unused-state
48+
}
3749

3850
static getDerivedStateFromProps(nextProps: Props, prevState: State) {
39-
if (prevState.hasClicked && !nextProps.isPending) {
40-
return { hasClicked: false, displaySuccess: !nextProps.isError }
51+
const nextState = {
52+
...prevState,
53+
isGlobalSyncStatePending: nextProps.isGlobalSyncStatePending,
4154
}
4255

43-
return null
44-
}
56+
if (prevState.hasClicked && !nextProps.isGlobalSyncStatePending) {
57+
nextState.hasClicked = false
58+
}
4559

46-
componentDidUpdate(prevProps: Props, prevState: State) {
47-
if (!prevState.displaySuccess && this.state.displaySuccess) {
48-
if (this._timeout) {
49-
clearTimeout(this._timeout)
50-
}
51-
this._timeout = setTimeout(
52-
() => this.setState({ displaySuccess: false }),
53-
DISPLAY_SUCCESS_TIME,
54-
)
60+
if (prevState.isGlobalSyncStatePending && !nextProps.isGlobalSyncStatePending) {
61+
nextState.isFirstSync = false
5562
}
63+
64+
return nextState
5665
}
5766

5867
handleRefresh = () => {
@@ -63,51 +72,51 @@ class ActivityIndicatorInner extends Component<Props, State> {
6372

6473
render() {
6574
const { isPending, isError, t } = this.props
66-
const { hasClicked, displaySuccess } = this.state
67-
const isDisabled = hasClicked || displaySuccess || isError
75+
const { hasClicked, isFirstSync } = this.state
76+
const isDisabled = hasClicked || isError
77+
const isRotating = isPending && (hasClicked || isFirstSync)
78+
6879
return (
6980
<ItemContainer isDisabled={isDisabled} onClick={isDisabled ? undefined : this.handleRefresh}>
7081
<Rotating
7182
size={16}
72-
isRotating={isPending && hasClicked}
73-
color={isError ? 'alertRed' : displaySuccess ? 'positiveGreen' : undefined}
83+
isRotating={isRotating}
84+
color={isError ? 'alertRed' : isRotating ? undefined : 'positiveGreen'}
7485
>
7586
{isError ? (
7687
<IconExclamationCircle size={16} />
77-
) : displaySuccess ? (
78-
<IconCheckCircle size={16} />
79-
) : (
88+
) : isRotating ? (
8089
<IconRefresh size={16} />
90+
) : (
91+
<IconCheckCircle size={16} />
8192
)}
8293
</Rotating>
83-
{(displaySuccess || isError || (isPending && hasClicked)) && (
84-
<Box
85-
ml={2}
86-
ff="Open Sans|SemiBold"
87-
color={isError ? 'alertRed' : undefined}
88-
fontSize={4}
89-
horizontal
90-
align="center"
91-
>
92-
{displaySuccess ? (
93-
t('common:sync.upToDate')
94-
) : isError ? (
95-
<Fragment>
96-
<Box>{t('common:sync.error')}</Box>
97-
<Box
98-
ml={2}
99-
cursor="pointer"
100-
style={{ textDecoration: 'underline', pointerEvents: 'all' }}
101-
onClick={this.handleRefresh}
102-
>
103-
{t('common:sync.refresh')}
104-
</Box>
105-
</Fragment>
106-
) : (
107-
t('common:sync.syncing')
108-
)}
109-
</Box>
110-
)}
94+
<Box
95+
ml={2}
96+
ff="Open Sans|SemiBold"
97+
color={isError ? 'alertRed' : undefined}
98+
fontSize={4}
99+
horizontal
100+
align="center"
101+
>
102+
{isRotating ? (
103+
t('common:sync.syncing')
104+
) : isError ? (
105+
<Fragment>
106+
<Box>{t('common:sync.error')}</Box>
107+
<Box
108+
ml={2}
109+
cursor="pointer"
110+
style={{ textDecoration: 'underline', pointerEvents: 'all' }}
111+
onClick={this.handleRefresh}
112+
>
113+
{t('common:sync.refresh')}
114+
</Box>
115+
</Fragment>
116+
) : (
117+
t('common:sync.upToDate')
118+
)}
119+
</Box>
111120
</ItemContainer>
112121
)
113122
}
@@ -124,6 +133,7 @@ const ActivityIndicator = ({ globalSyncState, t }: { globalSyncState: AsyncState
124133
<ActivityIndicatorInner
125134
t={t}
126135
isPending={isPending}
136+
isGlobalSyncStatePending={globalSyncState.pending}
127137
isError={!!isError && !isPending}
128138
onClick={() => {
129139
cvPolling.poll()

src/components/TopBar/ItemContainer.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,18 @@ export default styled(Tabbable).attrs({
1212
alignItems: 'center',
1313
cursor: p => (p.isDisabled ? 'default' : 'pointer'),
1414
horizontal: true,
15+
borderRadius: 1,
1516
})`
16-
min-height: 40px;
17+
height: 40px;
1718
border: 1px dashed transparent;
1819
1920
&:hover {
20-
color: ${p => (p.isDisabled ? '' : p.theme.colors.wallet)};
21-
background: ${p => (p.isDisabled ? '' : rgba(p.theme.colors.wallet, 0.05))};
21+
color: ${p => (p.isDisabled ? '' : p.theme.colors.dark)};
22+
background: ${p => (p.isDisabled ? '' : rgba(p.theme.colors.fog, 0.2))};
2223
}
2324
2425
&:active {
25-
background: ${p => (p.isDisabled ? '' : rgba(p.theme.colors.wallet, 0.1))};
26+
background: ${p => (p.isDisabled ? '' : rgba(p.theme.colors.fog, 0.3))};
2627
}
2728
2829
&:focus {

src/components/TopBar/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const Inner = styled(Box).attrs({
3838
horizontal: true,
3939
grow: true,
4040
flow: 4,
41+
align: 'center',
4142
})`
4243
border-bottom: 1px solid ${p => p.theme.colors.fog};
4344
`

src/config/constants.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @flow
22

3-
export const SYNC_BOOT_DELAY = 5 * 1000
3+
export const SYNC_BOOT_DELAY = 2 * 1000
44
export const SYNC_INTERVAL = 30 * 1000
55
export const CHECK_APP_INTERVAL_WHEN_INVALID = 600
66
export const CHECK_APP_INTERVAL_WHEN_VALID = 1200

0 commit comments

Comments
 (0)