@@ -20,39 +20,48 @@ import IconExclamationCircle from 'icons/ExclamationCircle'
20
20
import IconCheckCircle from 'icons/CheckCircle'
21
21
import ItemContainer from './ItemContainer'
22
22
23
- const DISPLAY_SUCCESS_TIME = 2 * 1000
24
-
25
23
const mapStateToProps = createStructuredSelector ( { globalSyncState : globalSyncStateSelector } )
26
24
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
+ }
29
40
30
41
class ActivityIndicatorInner extends Component < Props , State > {
31
42
state = {
32
43
hasClicked : false ,
33
- displaySuccess : false ,
34
- }
44
+ isFirstSync : true ,
35
45
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
+ }
37
49
38
50
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 ,
41
54
}
42
55
43
- return null
44
- }
56
+ if ( prevState . hasClicked && ! nextProps . isGlobalSyncStatePending ) {
57
+ nextState . hasClicked = false
58
+ }
45
59
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
55
62
}
63
+
64
+ return nextState
56
65
}
57
66
58
67
handleRefresh = ( ) => {
@@ -63,51 +72,51 @@ class ActivityIndicatorInner extends Component<Props, State> {
63
72
64
73
render ( ) {
65
74
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
+
68
79
return (
69
80
< ItemContainer isDisabled = { isDisabled } onClick = { isDisabled ? undefined : this . handleRefresh } >
70
81
< Rotating
71
82
size = { 16 }
72
- isRotating = { isPending && hasClicked }
73
- color = { isError ? 'alertRed' : displaySuccess ? 'positiveGreen' : undefined }
83
+ isRotating = { isRotating }
84
+ color = { isError ? 'alertRed' : isRotating ? undefined : 'positiveGreen' }
74
85
>
75
86
{ isError ? (
76
87
< IconExclamationCircle size = { 16 } />
77
- ) : displaySuccess ? (
78
- < IconCheckCircle size = { 16 } />
79
- ) : (
88
+ ) : isRotating ? (
80
89
< IconRefresh size = { 16 } />
90
+ ) : (
91
+ < IconCheckCircle size = { 16 } />
81
92
) }
82
93
</ 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 >
111
120
</ ItemContainer >
112
121
)
113
122
}
@@ -124,6 +133,7 @@ const ActivityIndicator = ({ globalSyncState, t }: { globalSyncState: AsyncState
124
133
< ActivityIndicatorInner
125
134
t = { t }
126
135
isPending = { isPending }
136
+ isGlobalSyncStatePending = { globalSyncState . pending }
127
137
isError = { ! ! isError && ! isPending }
128
138
onClick = { ( ) => {
129
139
cvPolling . poll ( )
0 commit comments