1 | function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
2 |
|
3 | import * as React from 'react';
|
4 | import { Animated, Platform, StyleSheet, View, I18nManager } from 'react-native';
|
5 | import setColor from 'color';
|
6 | import { withTheme } from '../core/theming';
|
7 | const INDETERMINATE_DURATION = 2000;
|
8 | const INDETERMINATE_MAX_WIDTH = 0.6;
|
9 | const {
|
10 | isRTL
|
11 | } = I18nManager;
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 | const ProgressBar = _ref => {
|
33 | let {
|
34 | color,
|
35 | indeterminate,
|
36 | style,
|
37 | progress = 0,
|
38 | visible = true,
|
39 | theme,
|
40 | ...rest
|
41 | } = _ref;
|
42 | const {
|
43 | current: timer
|
44 | } = React.useRef(new Animated.Value(0));
|
45 | const {
|
46 | current: fade
|
47 | } = React.useRef(new Animated.Value(0));
|
48 | const [width, setWidth] = React.useState(0);
|
49 | const [prevWidth, setPrevWidth] = React.useState(0);
|
50 | const indeterminateAnimation = React.useRef(null);
|
51 | const {
|
52 | scale
|
53 | } = theme.animation;
|
54 | const startAnimation = React.useCallback(() => {
|
55 |
|
56 | Animated.timing(fade, {
|
57 | duration: 200 * scale,
|
58 | toValue: 1,
|
59 | useNativeDriver: true,
|
60 | isInteraction: false
|
61 | }).start();
|
62 |
|
63 | if (indeterminate) {
|
64 | if (!indeterminateAnimation.current) {
|
65 | indeterminateAnimation.current = Animated.timing(timer, {
|
66 | duration: INDETERMINATE_DURATION,
|
67 | toValue: 1,
|
68 |
|
69 | useNativeDriver: Platform.OS !== 'web',
|
70 | isInteraction: false
|
71 | });
|
72 | }
|
73 |
|
74 |
|
75 | timer.setValue(0);
|
76 | Animated.loop(indeterminateAnimation.current).start();
|
77 | } else {
|
78 | Animated.timing(timer, {
|
79 | duration: 200 * scale,
|
80 | toValue: progress ? progress : 0,
|
81 | useNativeDriver: true,
|
82 | isInteraction: false
|
83 | }).start();
|
84 | }
|
85 | }, [scale, timer, progress, indeterminate, fade]);
|
86 | const stopAnimation = React.useCallback(() => {
|
87 |
|
88 | if (indeterminateAnimation.current) {
|
89 | indeterminateAnimation.current.stop();
|
90 | }
|
91 |
|
92 | Animated.timing(fade, {
|
93 | duration: 200 * scale,
|
94 | toValue: 0,
|
95 | useNativeDriver: true,
|
96 | isInteraction: false
|
97 | }).start();
|
98 | }, [fade, scale]);
|
99 | React.useEffect(() => {
|
100 | if (visible) startAnimation();else stopAnimation();
|
101 | }, [visible, startAnimation, stopAnimation]);
|
102 | React.useEffect(() => {
|
103 |
|
104 | if (visible && prevWidth === 0) {
|
105 | startAnimation();
|
106 | }
|
107 | }, [prevWidth, startAnimation, visible]);
|
108 |
|
109 | const onLayout = event => {
|
110 | setPrevWidth(width);
|
111 | setWidth(event.nativeEvent.layout.width);
|
112 | };
|
113 |
|
114 | const tintColor = color || theme.colors.primary;
|
115 | const trackTintColor = setColor(tintColor).alpha(0.38).rgb().string();
|
116 | return React.createElement(View, _extends({
|
117 | onLayout: onLayout
|
118 | }, rest, {
|
119 | accessible: true,
|
120 | accessibilityRole: "progressbar",
|
121 | accessibilityState: {
|
122 | busy: visible
|
123 | },
|
124 | accessibilityValue: indeterminate ? {} : {
|
125 | min: 0,
|
126 | max: 100,
|
127 | now: progress * 100
|
128 | }
|
129 | }), React.createElement(Animated.View, {
|
130 | style: [styles.container, {
|
131 | backgroundColor: trackTintColor,
|
132 | opacity: fade
|
133 | }, style]
|
134 | }, width ? React.createElement(Animated.View, {
|
135 | style: [styles.progressBar, {
|
136 | width,
|
137 | backgroundColor: tintColor,
|
138 | transform: [{
|
139 | translateX: timer.interpolate(indeterminate ? {
|
140 | inputRange: [0, 0.5, 1],
|
141 | outputRange: [(isRTL ? 1 : -1) * 0.5 * width, (isRTL ? 1 : -1) * 0.5 * INDETERMINATE_MAX_WIDTH * width, (isRTL ? -1 : 1) * 0.7 * width]
|
142 | } : {
|
143 | inputRange: [0, 1],
|
144 | outputRange: [(isRTL ? 1 : -1) * 0.5 * width, 0]
|
145 | })
|
146 | }, {
|
147 |
|
148 | scaleX: timer.interpolate(indeterminate ? {
|
149 | inputRange: [0, 0.5, 1],
|
150 | outputRange: [0.0001, INDETERMINATE_MAX_WIDTH, 0.0001]
|
151 | } : {
|
152 | inputRange: [0, 1],
|
153 | outputRange: [0.0001, 1]
|
154 | })
|
155 | }]
|
156 | }]
|
157 | }) : null));
|
158 | };
|
159 |
|
160 | const styles = StyleSheet.create({
|
161 | container: {
|
162 | height: 4,
|
163 | overflow: 'hidden'
|
164 | },
|
165 | progressBar: {
|
166 | flex: 1
|
167 | }
|
168 | });
|
169 | export default withTheme(ProgressBar);
|
170 |
|
\ | No newline at end of file |