Browse Source

Improve animated components to match linter

Arnaud Vergnet 1 year ago
parent
commit
9d92a88627

+ 92
- 79
src/components/Animations/AnimatedAccordion.js View File

@@ -1,101 +1,114 @@
1 1
 // @flow
2 2
 
3 3
 import * as React from 'react';
4
-import {View} from "react-native";
4
+import {View} from 'react-native';
5 5
 import {List, withTheme} from 'react-native-paper';
6
-import Collapsible from "react-native-collapsible";
7
-import * as Animatable from "react-native-animatable";
8
-import type {CustomTheme} from "../../managers/ThemeManager";
6
+import Collapsible from 'react-native-collapsible';
7
+import * as Animatable from 'react-native-animatable';
8
+import type {CustomTheme} from '../../managers/ThemeManager';
9 9
 
10
-type Props = {
11
-    theme: CustomTheme,
12
-    title: string,
13
-    subtitle?: string,
14
-    left?: (props: { [keys: string]: any }) =>  React.Node,
15
-    opened?: boolean,
16
-    unmountWhenCollapsed: boolean,
17
-    children?: React.Node,
18
-}
10
+type PropsType = {
11
+  theme: CustomTheme,
12
+  title: string,
13
+  subtitle?: string,
14
+  left?: () => React.Node,
15
+  opened?: boolean,
16
+  unmountWhenCollapsed?: boolean,
17
+  children?: React.Node,
18
+};
19 19
 
20
-type State = {
21
-    expanded: boolean,
22
-}
20
+type StateType = {
21
+  expanded: boolean,
22
+};
23 23
 
24 24
 const AnimatedListIcon = Animatable.createAnimatableComponent(List.Icon);
25 25
 
26
-class AnimatedAccordion extends React.Component<Props, State> {
26
+class AnimatedAccordion extends React.Component<PropsType, StateType> {
27
+  static defaultProps = {
28
+    subtitle: '',
29
+    left: null,
30
+    opened: null,
31
+    unmountWhenCollapsed: false,
32
+    children: null,
33
+  };
27 34
 
28
-    static defaultProps = {
29
-        unmountWhenCollapsed: false,
30
-    }
31
-    chevronRef: { current: null | AnimatedListIcon };
32
-    chevronIcon: string;
33
-    animStart: string;
34
-    animEnd: string;
35
+  chevronRef: {current: null | AnimatedListIcon};
35 36
 
36
-    state = {
37
-        expanded: this.props.opened != null ? this.props.opened : false,
38
-    }
37
+  chevronIcon: string;
39 38
 
40
-    constructor(props) {
41
-        super(props);
42
-        this.chevronRef = React.createRef();
43
-        this.setupChevron();
44
-    }
39
+  animStart: string;
45 40
 
46
-    setupChevron() {
47
-        if (this.state.expanded) {
48
-            this.chevronIcon = "chevron-up";
49
-            this.animStart = "180deg";
50
-            this.animEnd = "0deg";
51
-        } else {
52
-            this.chevronIcon = "chevron-down";
53
-            this.animStart = "0deg";
54
-            this.animEnd = "180deg";
55
-        }
56
-    }
41
+  animEnd: string;
57 42
 
58
-    toggleAccordion = () => {
59
-        if (this.chevronRef.current != null) {
60
-            this.chevronRef.current.transitionTo({rotate: this.state.expanded ? this.animStart : this.animEnd});
61
-            this.setState({expanded: !this.state.expanded})
62
-        }
43
+  constructor(props: PropsType) {
44
+    super(props);
45
+    this.state = {
46
+      expanded: props.opened != null ? props.opened : false,
63 47
     };
48
+    this.chevronRef = React.createRef();
49
+    this.setupChevron();
50
+  }
51
+
52
+  shouldComponentUpdate(nextProps: PropsType): boolean {
53
+    const {state, props} = this;
54
+    if (nextProps.opened != null && nextProps.opened !== props.opened)
55
+      state.expanded = nextProps.opened;
56
+    return true;
57
+  }
64 58
 
65
-    shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
66
-        if (nextProps.opened != null && nextProps.opened !== this.props.opened)
67
-            this.state.expanded = nextProps.opened;
68
-        return true;
59
+  setupChevron() {
60
+    const {state} = this;
61
+    if (state.expanded) {
62
+      this.chevronIcon = 'chevron-up';
63
+      this.animStart = '180deg';
64
+      this.animEnd = '0deg';
65
+    } else {
66
+      this.chevronIcon = 'chevron-down';
67
+      this.animStart = '0deg';
68
+      this.animEnd = '180deg';
69 69
     }
70
+  }
70 71
 
71
-    render() {
72
-        const colors = this.props.theme.colors;
73
-        return (
74
-            <View>
75
-                <List.Item
76
-                    {...this.props}
77
-                    title={this.props.title}
78
-                    subtitle={this.props.subtitle}
79
-                    titleStyle={this.state.expanded ? {color: colors.primary} : undefined}
80
-                    onPress={this.toggleAccordion}
81
-                    right={(props) => <AnimatedListIcon
82
-                        ref={this.chevronRef}
83
-                        {...props}
84
-                        icon={this.chevronIcon}
85
-                        color={this.state.expanded ? colors.primary : undefined}
86
-                        useNativeDriver
87
-                    />}
88
-                    left={this.props.left}
89
-                />
90
-                <Collapsible collapsed={!this.state.expanded}>
91
-                    {!this.props.unmountWhenCollapsed || (this.props.unmountWhenCollapsed && this.state.expanded)
92
-                        ? this.props.children
93
-                        : null}
94
-                </Collapsible>
95
-            </View>
96
-        );
72
+  toggleAccordion = () => {
73
+    const {state} = this;
74
+    if (this.chevronRef.current != null) {
75
+      this.chevronRef.current.transitionTo({
76
+        rotate: state.expanded ? this.animStart : this.animEnd,
77
+      });
78
+      this.setState({expanded: !state.expanded});
97 79
     }
80
+  };
98 81
 
82
+  render(): React.Node {
83
+    const {props, state} = this;
84
+    const {colors} = props.theme;
85
+    return (
86
+      <View>
87
+        <List.Item
88
+          title={props.title}
89
+          subtitle={props.subtitle}
90
+          titleStyle={state.expanded ? {color: colors.primary} : undefined}
91
+          onPress={this.toggleAccordion}
92
+          right={({size}: {size: number}): React.Node => (
93
+            <AnimatedListIcon
94
+              ref={this.chevronRef}
95
+              size={size}
96
+              icon={this.chevronIcon}
97
+              color={state.expanded ? colors.primary : undefined}
98
+              useNativeDriver
99
+            />
100
+          )}
101
+          left={props.left}
102
+        />
103
+        <Collapsible collapsed={!state.expanded}>
104
+          {!props.unmountWhenCollapsed ||
105
+          (props.unmountWhenCollapsed && state.expanded)
106
+            ? props.children
107
+            : null}
108
+        </Collapsible>
109
+      </View>
110
+    );
111
+  }
99 112
 }
100 113
 
101
-export default withTheme(AnimatedAccordion);
114
+export default withTheme(AnimatedAccordion);

+ 158
- 150
src/components/Animations/AnimatedBottomBar.js View File

@@ -1,170 +1,178 @@
1 1
 // @flow
2 2
 
3 3
 import * as React from 'react';
4
-import {StyleSheet, View} from "react-native";
5
-import {FAB, IconButton, Surface, withTheme} from "react-native-paper";
6
-import AutoHideHandler from "../../utils/AutoHideHandler";
4
+import {StyleSheet, View} from 'react-native';
5
+import {FAB, IconButton, Surface, withTheme} from 'react-native-paper';
7 6
 import * as Animatable from 'react-native-animatable';
8
-import CustomTabBar from "../Tabbar/CustomTabBar";
9
-import {StackNavigationProp} from "@react-navigation/stack";
10
-import type {CustomTheme} from "../../managers/ThemeManager";
7
+import {StackNavigationProp} from '@react-navigation/stack';
8
+import AutoHideHandler from '../../utils/AutoHideHandler';
9
+import CustomTabBar from '../Tabbar/CustomTabBar';
10
+import type {CustomTheme} from '../../managers/ThemeManager';
11 11
 
12 12
 const AnimatedFAB = Animatable.createAnimatableComponent(FAB);
13 13
 
14
-type Props = {
15
-    navigation: StackNavigationProp,
16
-    theme: CustomTheme,
17
-    onPress: (action: string, data: any) => void,
18
-    seekAttention: boolean,
19
-}
14
+type PropsType = {
15
+  navigation: StackNavigationProp,
16
+  theme: CustomTheme,
17
+  onPress: (action: string, data?: string) => void,
18
+  seekAttention: boolean,
19
+};
20 20
 
21
-type State = {
22
-    currentMode: string,
23
-}
21
+type StateType = {
22
+  currentMode: string,
23
+};
24 24
 
25 25
 const DISPLAY_MODES = {
26
-    DAY: "agendaDay",
27
-    WEEK: "agendaWeek",
28
-    MONTH: "month",
29
-}
30
-
31
-class AnimatedBottomBar extends React.Component<Props, State> {
32
-
33
-    ref: { current: null | Animatable.View };
34
-    hideHandler: AutoHideHandler;
35
-
36
-    displayModeIcons: { [key: string]: string };
26
+  DAY: 'agendaDay',
27
+  WEEK: 'agendaWeek',
28
+  MONTH: 'month',
29
+};
37 30
 
38
-    state = {
39
-        currentMode: DISPLAY_MODES.WEEK,
40
-    }
41
-
42
-    constructor() {
43
-        super();
44
-        this.ref = React.createRef();
45
-        this.hideHandler = new AutoHideHandler(false);
46
-        this.hideHandler.addListener(this.onHideChange);
47
-
48
-        this.displayModeIcons = {};
49
-        this.displayModeIcons[DISPLAY_MODES.DAY] = "calendar-text";
50
-        this.displayModeIcons[DISPLAY_MODES.WEEK] = "calendar-week";
51
-        this.displayModeIcons[DISPLAY_MODES.MONTH] = "calendar-range";
52
-    }
31
+const styles = StyleSheet.create({
32
+  container: {
33
+    position: 'absolute',
34
+    left: '5%',
35
+    width: '90%',
36
+  },
37
+  surface: {
38
+    position: 'relative',
39
+    flexDirection: 'row',
40
+    justifyContent: 'space-between',
41
+    alignItems: 'center',
42
+    borderRadius: 50,
43
+    elevation: 2,
44
+  },
45
+  fabContainer: {
46
+    position: 'absolute',
47
+    left: 0,
48
+    right: 0,
49
+    alignItems: 'center',
50
+    width: '100%',
51
+    height: '100%',
52
+  },
53
+  fab: {
54
+    position: 'absolute',
55
+    alignSelf: 'center',
56
+    top: '-25%',
57
+  },
58
+});
53 59
 
54
-    shouldComponentUpdate(nextProps: Props, nextState: State) {
55
-        return (nextProps.seekAttention !== this.props.seekAttention)
56
-            || (nextState.currentMode !== this.state.currentMode);
57
-    }
60
+class AnimatedBottomBar extends React.Component<PropsType, StateType> {
61
+  ref: {current: null | Animatable.View};
58 62
 
59
-    onHideChange = (shouldHide: boolean) => {
60
-        if (this.ref.current != null) {
61
-            if (shouldHide)
62
-                this.ref.current.fadeOutDown(500);
63
-            else
64
-                this.ref.current.fadeInUp(500);
65
-        }
66
-    }
63
+  hideHandler: AutoHideHandler;
67 64
 
68
-    onScroll = (event: SyntheticEvent<EventTarget>) => {
69
-        this.hideHandler.onScroll(event);
70
-    };
65
+  displayModeIcons: {[key: string]: string};
71 66
 
72
-    changeDisplayMode = () => {
73
-        let newMode;
74
-        switch (this.state.currentMode) {
75
-            case DISPLAY_MODES.DAY:
76
-                newMode = DISPLAY_MODES.WEEK;
77
-                break;
78
-            case DISPLAY_MODES.WEEK:
79
-                newMode = DISPLAY_MODES.MONTH;
80
-
81
-                break;
82
-            case DISPLAY_MODES.MONTH:
83
-                newMode = DISPLAY_MODES.DAY;
84
-                break;
85
-        }
86
-        this.setState({currentMode: newMode});
87
-        this.props.onPress("changeView", newMode);
67
+  constructor() {
68
+    super();
69
+    this.state = {
70
+      currentMode: DISPLAY_MODES.WEEK,
88 71
     };
89
-
90
-    render() {
91
-        const buttonColor = this.props.theme.colors.primary;
92
-        return (
93
-            <Animatable.View
94
-                ref={this.ref}
95
-                useNativeDriver
96
-                style={{
97
-                    ...styles.container,
98
-                    bottom: 10 + CustomTabBar.TAB_BAR_HEIGHT
99
-                }}>
100
-                <Surface style={styles.surface}>
101
-                    <View style={styles.fabContainer}>
102
-                        <AnimatedFAB
103
-                            animation={this.props.seekAttention ? "bounce" : undefined}
104
-                            easing="ease-out"
105
-                            iterationDelay={500}
106
-                            iterationCount="infinite"
107
-                            useNativeDriver
108
-                            style={styles.fab}
109
-                            icon="account-clock"
110
-                            onPress={() => this.props.navigation.navigate('group-select')}
111
-                        />
112
-                    </View>
113
-                    <View style={{flexDirection: 'row'}}>
114
-                        <IconButton
115
-                            icon={this.displayModeIcons[this.state.currentMode]}
116
-                            color={buttonColor}
117
-                            onPress={this.changeDisplayMode}/>
118
-                        <IconButton
119
-                            icon="clock-in"
120
-                            color={buttonColor}
121
-                            style={{marginLeft: 5}}
122
-                            onPress={() => this.props.onPress('today', undefined)}/>
123
-                    </View>
124
-                    <View style={{flexDirection: 'row'}}>
125
-                        <IconButton
126
-                            icon="chevron-left"
127
-                            color={buttonColor}
128
-                            onPress={() => this.props.onPress('prev', undefined)}/>
129
-                        <IconButton
130
-                            icon="chevron-right"
131
-                            color={buttonColor}
132
-                            style={{marginLeft: 5}}
133
-                            onPress={() => this.props.onPress('next', undefined)}/>
134
-                    </View>
135
-                </Surface>
136
-            </Animatable.View>
137
-        );
72
+    this.ref = React.createRef();
73
+    this.hideHandler = new AutoHideHandler(false);
74
+    this.hideHandler.addListener(this.onHideChange);
75
+
76
+    this.displayModeIcons = {};
77
+    this.displayModeIcons[DISPLAY_MODES.DAY] = 'calendar-text';
78
+    this.displayModeIcons[DISPLAY_MODES.WEEK] = 'calendar-week';
79
+    this.displayModeIcons[DISPLAY_MODES.MONTH] = 'calendar-range';
80
+  }
81
+
82
+  shouldComponentUpdate(nextProps: PropsType, nextState: StateType): boolean {
83
+    const {props, state} = this;
84
+    return (
85
+      nextProps.seekAttention !== props.seekAttention ||
86
+      nextState.currentMode !== state.currentMode
87
+    );
88
+  }
89
+
90
+  onHideChange = (shouldHide: boolean) => {
91
+    if (this.ref.current != null) {
92
+      if (shouldHide) this.ref.current.fadeOutDown(500);
93
+      else this.ref.current.fadeInUp(500);
138 94
     }
139
-}
140
-
141
-const styles = StyleSheet.create({
142
-    container: {
143
-        position: 'absolute',
144
-        left: '5%',
145
-        width: '90%',
146
-    },
147
-    surface: {
148
-        position: 'relative',
149
-        flexDirection: 'row',
150
-        justifyContent: 'space-between',
151
-        alignItems: 'center',
152
-        borderRadius: 50,
153
-        elevation: 2,
154
-    },
155
-    fabContainer: {
156
-        position: "absolute",
157
-        left: 0,
158
-        right: 0,
159
-        alignItems: "center",
160
-        width: '100%',
161
-        height: '100%'
162
-    },
163
-    fab: {
164
-        position: 'absolute',
165
-        alignSelf: 'center',
166
-        top: '-25%',
95
+  };
96
+
97
+  onScroll = (event: SyntheticEvent<EventTarget>) => {
98
+    this.hideHandler.onScroll(event);
99
+  };
100
+
101
+  changeDisplayMode = () => {
102
+    const {props, state} = this;
103
+    let newMode;
104
+    switch (state.currentMode) {
105
+      case DISPLAY_MODES.DAY:
106
+        newMode = DISPLAY_MODES.WEEK;
107
+        break;
108
+      case DISPLAY_MODES.WEEK:
109
+        newMode = DISPLAY_MODES.MONTH;
110
+        break;
111
+      case DISPLAY_MODES.MONTH:
112
+        newMode = DISPLAY_MODES.DAY;
113
+        break;
114
+      default:
115
+        newMode = DISPLAY_MODES.WEEK;
116
+        break;
167 117
     }
168
-});
118
+    this.setState({currentMode: newMode});
119
+    props.onPress('changeView', newMode);
120
+  };
121
+
122
+  render(): React.Node {
123
+    const {props, state} = this;
124
+    const buttonColor = props.theme.colors.primary;
125
+    return (
126
+      <Animatable.View
127
+        ref={this.ref}
128
+        useNativeDriver
129
+        style={{
130
+          ...styles.container,
131
+          bottom: 10 + CustomTabBar.TAB_BAR_HEIGHT,
132
+        }}>
133
+        <Surface style={styles.surface}>
134
+          <View style={styles.fabContainer}>
135
+            <AnimatedFAB
136
+              animation={props.seekAttention ? 'bounce' : undefined}
137
+              easing="ease-out"
138
+              iterationDelay={500}
139
+              iterationCount="infinite"
140
+              useNativeDriver
141
+              style={styles.fab}
142
+              icon="account-clock"
143
+              onPress={(): void => props.navigation.navigate('group-select')}
144
+            />
145
+          </View>
146
+          <View style={{flexDirection: 'row'}}>
147
+            <IconButton
148
+              icon={this.displayModeIcons[state.currentMode]}
149
+              color={buttonColor}
150
+              onPress={this.changeDisplayMode}
151
+            />
152
+            <IconButton
153
+              icon="clock-in"
154
+              color={buttonColor}
155
+              style={{marginLeft: 5}}
156
+              onPress={(): void => props.onPress('today')}
157
+            />
158
+          </View>
159
+          <View style={{flexDirection: 'row'}}>
160
+            <IconButton
161
+              icon="chevron-left"
162
+              color={buttonColor}
163
+              onPress={(): void => props.onPress('prev')}
164
+            />
165
+            <IconButton
166
+              icon="chevron-right"
167
+              color={buttonColor}
168
+              style={{marginLeft: 5}}
169
+              onPress={(): void => props.onPress('next')}
170
+            />
171
+          </View>
172
+        </Surface>
173
+      </Animatable.View>
174
+    );
175
+  }
176
+}
169 177
 
170 178
 export default withTheme(AnimatedBottomBar);

+ 48
- 51
src/components/Animations/AnimatedFAB.js View File

@@ -1,66 +1,63 @@
1 1
 // @flow
2 2
 
3 3
 import * as React from 'react';
4
-import {StyleSheet} from "react-native";
5
-import {FAB} from "react-native-paper";
6
-import AutoHideHandler from "../../utils/AutoHideHandler";
4
+import {StyleSheet} from 'react-native';
5
+import {FAB} from 'react-native-paper';
7 6
 import * as Animatable from 'react-native-animatable';
8
-import CustomTabBar from "../Tabbar/CustomTabBar";
9
-import {StackNavigationProp} from "@react-navigation/stack";
7
+import AutoHideHandler from '../../utils/AutoHideHandler';
8
+import CustomTabBar from '../Tabbar/CustomTabBar';
10 9
 
11
-type Props = {
12
-    navigation: StackNavigationProp,
13
-    icon: string,
14
-    onPress: () => void,
15
-}
10
+type PropsType = {
11
+  icon: string,
12
+  onPress: () => void,
13
+};
16 14
 
17 15
 const AnimatedFab = Animatable.createAnimatableComponent(FAB);
18 16
 
19
-export default class AnimatedFAB extends React.Component<Props> {
17
+const styles = StyleSheet.create({
18
+  fab: {
19
+    position: 'absolute',
20
+    margin: 16,
21
+    right: 0,
22
+  },
23
+});
20 24
 
21
-    ref: { current: null | Animatable.View };
22
-    hideHandler: AutoHideHandler;
25
+export default class AnimatedFAB extends React.Component<PropsType> {
26
+  ref: {current: null | Animatable.View};
23 27
 
24
-    constructor() {
25
-        super();
26
-        this.ref = React.createRef();
27
-        this.hideHandler = new AutoHideHandler(false);
28
-        this.hideHandler.addListener(this.onHideChange);
29
-    }
28
+  hideHandler: AutoHideHandler;
30 29
 
31
-    onScroll = (event: SyntheticEvent<EventTarget>) => {
32
-        this.hideHandler.onScroll(event);
33
-    };
30
+  constructor() {
31
+    super();
32
+    this.ref = React.createRef();
33
+    this.hideHandler = new AutoHideHandler(false);
34
+    this.hideHandler.addListener(this.onHideChange);
35
+  }
34 36
 
35
-    onHideChange = (shouldHide: boolean) => {
36
-        if (this.ref.current != null) {
37
-            if (shouldHide)
38
-                this.ref.current.bounceOutDown(1000);
39
-            else
40
-                this.ref.current.bounceInUp(1000);
41
-        }
42
-    }
37
+  onScroll = (event: SyntheticEvent<EventTarget>) => {
38
+    this.hideHandler.onScroll(event);
39
+  };
43 40
 
44
-    render() {
45
-        return (
46
-            <AnimatedFab
47
-                ref={this.ref}
48
-                useNativeDriver
49
-                icon={this.props.icon}
50
-                onPress={this.props.onPress}
51
-                style={{
52
-                    ...styles.fab,
53
-                    bottom: CustomTabBar.TAB_BAR_HEIGHT
54
-                }}
55
-            />
56
-        );
41
+  onHideChange = (shouldHide: boolean) => {
42
+    if (this.ref.current != null) {
43
+      if (shouldHide) this.ref.current.bounceOutDown(1000);
44
+      else this.ref.current.bounceInUp(1000);
57 45
     }
46
+  };
47
+
48
+  render(): React.Node {
49
+    const {props} = this;
50
+    return (
51
+      <AnimatedFab
52
+        ref={this.ref}
53
+        useNativeDriver
54
+        icon={props.icon}
55
+        onPress={props.onPress}
56
+        style={{
57
+          ...styles.fab,
58
+          bottom: CustomTabBar.TAB_BAR_HEIGHT,
59
+        }}
60
+      />
61
+    );
62
+  }
58 63
 }
59
-
60
-const styles = StyleSheet.create({
61
-    fab: {
62
-        position: 'absolute',
63
-        margin: 16,
64
-        right: 0,
65
-    },
66
-});

Loading…
Cancel
Save