Browse Source

Improved flow typing

Arnaud Vergnet 4 years ago
parent
commit
dc3aed8bda

+ 2
- 10
src/components/Lists/Clubs/ClubListHeader.js View File

@@ -1,7 +1,7 @@
1 1
 // @flow
2 2
 
3 3
 import * as React from 'react';
4
-import {Card, List, Text, withTheme} from 'react-native-paper';
4
+import {Card, List, Text} from 'react-native-paper';
5 5
 import {StyleSheet, View} from "react-native";
6 6
 import i18n from 'i18n-js';
7 7
 import AnimatedAccordion from "../../Animations/AnimatedAccordion";
@@ -13,14 +13,6 @@ type Props = {
13 13
 
14 14
 class ClubListHeader extends React.Component<Props> {
15 15
 
16
-
17
-    colors: Object;
18
-
19
-    constructor(props) {
20
-        super(props);
21
-        this.colors = props.theme.colors;
22
-    }
23
-
24 16
     getCategoriesRender() {
25 17
         let final = [];
26 18
         for (let i = 0; i < this.props.categories.length; i++) {
@@ -67,4 +59,4 @@ const styles = StyleSheet.create({
67 59
     },
68 60
 });
69 61
 
70
-export default withTheme(ClubListHeader);
62
+export default ClubListHeader;

+ 10
- 8
src/components/Lists/Clubs/ClubListItem.js View File

@@ -3,22 +3,23 @@
3 3
 import * as React from 'react';
4 4
 import {Avatar, Chip, List, withTheme} from 'react-native-paper';
5 5
 import {View} from "react-native";
6
+import type {category, club} from "../../../screens/Amicale/Clubs/ClubListScreen";
7
+import type {CustomTheme} from "../../../managers/ThemeManager";
6 8
 
7 9
 type Props = {
8
-    onPress: Function,
9
-    categoryTranslator: Function,
10
-    item: Object,
10
+    onPress: () => void,
11
+    categoryTranslator: (id: number) => category,
12
+    item: club,
11 13
     height: number,
14
+    theme: CustomTheme,
12 15
 }
13 16
 
14 17
 class ClubListItem extends React.Component<Props> {
15 18
 
16
-    colors: Object;
17 19
     hasManagers: boolean;
18 20
 
19 21
     constructor(props) {
20 22
         super(props);
21
-        this.colors = props.theme.colors;
22 23
         this.hasManagers = props.item.responsibles.length > 0;
23 24
     }
24 25
 
@@ -29,8 +30,8 @@ class ClubListItem extends React.Component<Props> {
29 30
     getCategoriesRender(categories: Array<number | null>) {
30 31
         let final = [];
31 32
         for (let i = 0; i < categories.length; i++) {
32
-            if (categories[i] !== null){
33
-                const category = this.props.categoryTranslator(categories[i]);
33
+            if (categories[i] !== null) {
34
+                const category: category = this.props.categoryTranslator(categories[i]);
34 35
                 final.push(
35 36
                     <Chip
36 37
                         style={{marginRight: 5, marginBottom: 5}}
@@ -46,6 +47,7 @@ class ClubListItem extends React.Component<Props> {
46 47
 
47 48
     render() {
48 49
         const categoriesRender = this.getCategoriesRender.bind(this, this.props.item.category);
50
+        const colors = this.props.theme.colors;
49 51
         return (
50 52
             <List.Item
51 53
                 title={this.props.item.name}
@@ -65,7 +67,7 @@ class ClubListItem extends React.Component<Props> {
65 67
                     }}
66 68
                     size={48}
67 69
                     icon={this.hasManagers ? "check-circle-outline" : "alert-circle-outline"}
68
-                    color={this.hasManagers ? this.colors.success : this.colors.primary}
70
+                    color={this.hasManagers ? colors.success : colors.primary}
69 71
                 />}
70 72
                 style={{
71 73
                     height: this.props.height,

+ 13
- 15
src/components/Lists/PlanexGroups/GroupListAccordion.js View File

@@ -4,18 +4,19 @@ import * as React from 'react';
4 4
 import {List, withTheme} from 'react-native-paper';
5 5
 import {FlatList, View} from "react-native";
6 6
 import {stringMatchQuery} from "../../../utils/Search";
7
-import * as Animatable from "react-native-animatable";
8 7
 import GroupListItem from "./GroupListItem";
9 8
 import AnimatedAccordion from "../../Animations/AnimatedAccordion";
9
+import type {group, groupCategory} from "../../../screens/Planex/GroupSelectionScreen";
10
+import type {CustomTheme} from "../../../managers/ThemeManager";
10 11
 
11 12
 type Props = {
12
-    item: Object,
13
-    onGroupPress: Function,
14
-    onFavoritePress: Function,
13
+    item: groupCategory,
14
+    onGroupPress: (group) => void,
15
+    onFavoritePress: (group) => void,
15 16
     currentSearchString: string,
16 17
     favoriteNumber: number,
17 18
     height: number,
18
-    theme: Object,
19
+    theme: CustomTheme,
19 20
 }
20 21
 
21 22
 type State = {
@@ -23,18 +24,14 @@ type State = {
23 24
 }
24 25
 
25 26
 const LIST_ITEM_HEIGHT = 64;
26
-const AnimatedListIcon = Animatable.createAnimatableComponent(List.Icon);
27 27
 
28 28
 class GroupListAccordion extends React.Component<Props, State> {
29 29
 
30
-    chevronRef: Object;
31
-
32 30
     constructor(props) {
33 31
         super(props);
34 32
         this.state = {
35 33
             expanded: props.item.id === "0",
36 34
         }
37
-        this.chevronRef = React.createRef();
38 35
     }
39 36
 
40 37
     shouldComponentUpdate(nextProps: Props, nextSate: State) {
@@ -47,24 +44,24 @@ class GroupListAccordion extends React.Component<Props, State> {
47 44
             || (nextProps.item.content.length !== this.props.item.content.length);
48 45
     }
49 46
 
50
-    keyExtractor = (item: Object) => item.id.toString();
47
+    keyExtractor = (item: group) => item.id.toString();
51 48
 
52
-    renderItem = ({item}: Object) => {
49
+    renderItem = ({item}: {item: group}) => {
53 50
         if (stringMatchQuery(item.name, this.props.currentSearchString)) {
54 51
             const onPress = () => this.props.onGroupPress(item);
55
-            const onStartPress = () => this.props.onFavoritePress(item);
52
+            const onStarPress = () => this.props.onFavoritePress(item);
56 53
             return (
57 54
                 <GroupListItem
58 55
                     height={LIST_ITEM_HEIGHT}
59 56
                     item={item}
60 57
                     onPress={onPress}
61
-                    onStartPress={onStartPress}/>
58
+                    onStarPress={onStarPress}/>
62 59
             );
63 60
         } else
64 61
             return null;
65 62
     }
66 63
 
67
-    itemLayout = (data: Object, index: number) => ({length: LIST_ITEM_HEIGHT, offset: LIST_ITEM_HEIGHT * index, index});
64
+    itemLayout = (data, index) => ({length: LIST_ITEM_HEIGHT, offset: LIST_ITEM_HEIGHT * index, index});
68 65
 
69 66
     render() {
70 67
         const item = this.props.item;
@@ -86,12 +83,13 @@ class GroupListAccordion extends React.Component<Props, State> {
86 83
                             : null}
87 84
                     unmountWhenCollapsed={true}// Only render list if expanded for increased performance
88 85
                 >
86
+                    {/*$FlowFixMe*/}
89 87
                     <FlatList
90 88
                         data={item.content}
91 89
                         extraData={this.props.currentSearchString}
92 90
                         renderItem={this.renderItem}
93 91
                         keyExtractor={this.keyExtractor}
94
-                        listKey={item.id}
92
+                        listKey={item.id.toString()}
95 93
                         // Performance props, see https://reactnative.dev/docs/optimizing-flatlist-configuration
96 94
                         getItemLayout={this.itemLayout} // Broken with search
97 95
                         removeClippedSubviews={true}

+ 9
- 9
src/components/Lists/PlanexGroups/GroupListItem.js View File

@@ -2,12 +2,14 @@
2 2
 
3 3
 import * as React from 'react';
4 4
 import {IconButton, List, withTheme} from 'react-native-paper';
5
+import type {CustomTheme} from "../../../managers/ThemeManager";
6
+import type {group} from "../../../screens/Planex/GroupSelectionScreen";
5 7
 
6 8
 type Props = {
7
-    theme: Object,
8
-    onPress: Function,
9
-    onStartPress: Function,
10
-    item: Object,
9
+    theme: CustomTheme,
10
+    onPress: () => void,
11
+    onStarPress: () => void,
12
+    item: group,
11 13
     height: number,
12 14
 }
13 15
 
@@ -17,11 +19,8 @@ type State = {
17 19
 
18 20
 class GroupListItem extends React.Component<Props, State> {
19 21
 
20
-    colors: Object;
21
-
22 22
     constructor(props) {
23 23
         super(props);
24
-        this.colors = props.theme.colors;
25 24
         this.state = {
26 25
             isFav: (props.item.isFav !== undefined && props.item.isFav),
27 26
         }
@@ -33,10 +32,11 @@ class GroupListItem extends React.Component<Props, State> {
33 32
 
34 33
     onStarPress = () => {
35 34
         this.setState({isFav: !this.state.isFav});
36
-        this.props.onStartPress();
35
+        this.props.onStarPress();
37 36
     }
38 37
 
39 38
     render() {
39
+        const colors = this.props.theme.colors;
40 40
         return (
41 41
             <List.Item
42 42
                 title={this.props.item.name}
@@ -51,7 +51,7 @@ class GroupListItem extends React.Component<Props, State> {
51 51
                         icon={"star"}
52 52
                         onPress={this.onStarPress}
53 53
                         color={this.state.isFav
54
-                            ? this.props.theme.colors.tetrisScore
54
+                            ? colors.tetrisScore
55 55
                             : props.color}
56 56
                     />}
57 57
                 style={{

+ 38
- 21
src/screens/Amicale/Clubs/ClubListScreen.js View File

@@ -2,7 +2,7 @@
2 2
 
3 3
 import * as React from 'react';
4 4
 import {Animated, Platform} from "react-native";
5
-import {Chip, Searchbar, withTheme} from 'react-native-paper';
5
+import {Chip, Searchbar} from 'react-native-paper';
6 6
 import AuthenticatedScreen from "../../../components/Amicale/AuthenticatedScreen";
7 7
 import i18n from "i18n-js";
8 8
 import ClubListItem from "../../../components/Lists/Clubs/ClubListItem";
@@ -10,11 +10,29 @@ import {isItemInCategoryFilter, stringMatchQuery} from "../../../utils/Search";
10 10
 import ClubListHeader from "../../../components/Lists/Clubs/ClubListHeader";
11 11
 import MaterialHeaderButtons, {Item} from "../../../components/Overrides/CustomHeaderButton";
12 12
 import {withCollapsible} from "../../../utils/withCollapsible";
13
+import {StackNavigationProp} from "@react-navigation/stack";
14
+import type {CustomTheme} from "../../../managers/ThemeManager";
15
+import {Collapsible} from "react-navigation-collapsible";
16
+
17
+export type category = {
18
+    id: number,
19
+    name: string,
20
+};
21
+
22
+export type club = {
23
+    id: number,
24
+    name: string,
25
+    description: string,
26
+    logo: string,
27
+    email:string,
28
+    category: [number, number],
29
+    responsibles: Array<string>,
30
+};
13 31
 
14 32
 type Props = {
15
-    navigation: Object,
16
-    theme: Object,
17
-    collapsibleStack: Object,
33
+    navigation: StackNavigationProp,
34
+    theme: CustomTheme,
35
+    collapsibleStack: Collapsible,
18 36
 }
19 37
 
20 38
 type State = {
@@ -31,14 +49,7 @@ class ClubListScreen extends React.Component<Props, State> {
31 49
         currentSearchString: '',
32 50
     };
33 51
 
34
-    colors: Object;
35
-
36
-    categories: Array<Object>;
37
-
38
-    constructor(props) {
39
-        super(props);
40
-        this.colors = props.theme.colors;
41
-    }
52
+    categories: Array<category>;
42 53
 
43 54
     /**
44 55
      * Creates the header content
@@ -88,19 +99,25 @@ class ClubListScreen extends React.Component<Props, State> {
88 99
         this.updateFilteredData(str, null);
89 100
     };
90 101
 
91
-    keyExtractor = (item: Object) => {
102
+    keyExtractor = (item: club) => {
92 103
         return item.id.toString();
93 104
     };
94 105
 
95 106
     itemLayout = (data, index) => ({length: LIST_ITEM_HEIGHT, offset: LIST_ITEM_HEIGHT * index, index});
96 107
 
97
-    getScreen = (data: Object) => {
98
-        this.categories = data[0].categories;
108
+    getScreen = (data: Array<{categories: Array<category>, clubs: Array<club>} | null>) => {
109
+        let categoryList = [];
110
+        let clubList = [];
111
+        if (data[0] != null) {
112
+            categoryList = data[0].categories;
113
+            clubList = data[0].clubs;
114
+        }
115
+        this.categories = categoryList;
99 116
         const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
100 117
         return (
101 118
             //$FlowFixMe
102 119
             <Animated.FlatList
103
-                data={data[0].clubs}
120
+                data={clubList}
104 121
                 keyExtractor={this.keyExtractor}
105 122
                 renderItem={this.getRenderItem}
106 123
                 ListHeaderComponent={this.getListHeader()}
@@ -138,7 +155,7 @@ class ClubListScreen extends React.Component<Props, State> {
138 155
             })
139 156
     }
140 157
 
141
-    getChipRender = (category: Object, key: string) => {
158
+    getChipRender = (category: category, key: string) => {
142 159
         const onPress = this.onChipSelect.bind(this, category.id);
143 160
         return <Chip
144 161
             selected={isItemInCategoryFilter(this.state.currentlySelectedCategories, [category.id])}
@@ -165,7 +182,7 @@ class ClubListScreen extends React.Component<Props, State> {
165 182
         }
166 183
     };
167 184
 
168
-    shouldRenderItem(item) {
185
+    shouldRenderItem(item: club) {
169 186
         let shouldRender = this.state.currentlySelectedCategories.length === 0
170 187
             || isItemInCategoryFilter(this.state.currentlySelectedCategories, item.category);
171 188
         if (shouldRender)
@@ -173,7 +190,7 @@ class ClubListScreen extends React.Component<Props, State> {
173 190
         return shouldRender;
174 191
     }
175 192
 
176
-    getRenderItem = ({item}: Object) => {
193
+    getRenderItem = ({item}: {item: club}) => {
177 194
         const onPress = this.onListItemPress.bind(this, item);
178 195
         if (this.shouldRenderItem(item)) {
179 196
             return (
@@ -194,7 +211,7 @@ class ClubListScreen extends React.Component<Props, State> {
194 211
      *
195 212
      * @param item The article pressed
196 213
      */
197
-    onListItemPress(item: Object) {
214
+    onListItemPress(item: club) {
198 215
         this.props.navigation.navigate("club-information", {data: item, categories: this.categories});
199 216
     }
200 217
 
@@ -215,4 +232,4 @@ class ClubListScreen extends React.Component<Props, State> {
215 232
     }
216 233
 }
217 234
 
218
-export default withCollapsible(withTheme(ClubListScreen));
235
+export default withCollapsible(ClubListScreen);

+ 31
- 20
src/screens/Planex/GroupSelectionScreen.js View File

@@ -3,26 +3,37 @@
3 3
 import * as React from 'react';
4 4
 import {Platform} from "react-native";
5 5
 import i18n from "i18n-js";
6
-import {Searchbar, withTheme} from "react-native-paper";
6
+import {Searchbar} from "react-native-paper";
7 7
 import {stringMatchQuery} from "../../utils/Search";
8 8
 import WebSectionList from "../../components/Screens/WebSectionList";
9 9
 import GroupListAccordion from "../../components/Lists/PlanexGroups/GroupListAccordion";
10 10
 import AsyncStorageManager from "../../managers/AsyncStorageManager";
11
+import {StackNavigationProp} from "@react-navigation/stack";
11 12
 
12 13
 const LIST_ITEM_HEIGHT = 70;
13 14
 
15
+export type group = {
16
+    name: string,
17
+    id: number,
18
+    isFav: boolean,
19
+};
20
+
21
+export type groupCategory = {
22
+    name: string,
23
+    id: number,
24
+    content: Array<group>,
25
+};
26
+
14 27
 type Props = {
15
-    navigation: Object,
16
-    route: Object,
17
-    theme: Object,
28
+    navigation: StackNavigationProp,
18 29
 }
19 30
 
20 31
 type State = {
21 32
     currentSearchString: string,
22
-    favoriteGroups: Array<Object>,
33
+    favoriteGroups: Array<group>,
23 34
 };
24 35
 
25
-function sortName(a, b) {
36
+function sortName(a: group | groupCategory, b: group | groupCategory) {
26 37
     if (a.name.toLowerCase() < b.name.toLowerCase())
27 38
         return -1;
28 39
     if (a.name.toLowerCase() > b.name.toLowerCase())
@@ -38,7 +49,7 @@ const REPLACE_REGEX = /_/g;
38 49
  */
39 50
 class GroupSelectionScreen extends React.Component<Props, State> {
40 51
 
41
-    constructor(props) {
52
+    constructor(props: Props) {
42 53
         super(props);
43 54
         this.state = {
44 55
             currentSearchString: '',
@@ -88,18 +99,18 @@ class GroupSelectionScreen extends React.Component<Props, State> {
88 99
      *
89 100
      * @param item The article pressed
90 101
      */
91
-    onListItemPress = (item: Object) => {
102
+    onListItemPress = (item: group) => {
92 103
         this.props.navigation.navigate("planex", {
93 104
             screen: "index",
94 105
             params: {group: item}
95 106
         });
96 107
     };
97 108
 
98
-    onListFavoritePress = (item: Object) => {
109
+    onListFavoritePress = (item: group) => {
99 110
         this.updateGroupFavorites(item);
100 111
     };
101 112
 
102
-    isGroupInFavorites(group: Object) {
113
+    isGroupInFavorites(group: group) {
103 114
         let isFav = false;
104 115
         for (let i = 0; i < this.state.favoriteGroups.length; i++) {
105 116
             if (group.id === this.state.favoriteGroups[i].id) {
@@ -110,7 +121,7 @@ class GroupSelectionScreen extends React.Component<Props, State> {
110 121
         return isFav;
111 122
     }
112 123
 
113
-    removeGroupFromFavorites(favorites: Array<Object>, group: Object) {
124
+    removeGroupFromFavorites(favorites: Array<group>, group: group) {
114 125
         for (let i = 0; i < favorites.length; i++) {
115 126
             if (group.id === favorites[i].id) {
116 127
                 favorites.splice(i, 1);
@@ -119,13 +130,13 @@ class GroupSelectionScreen extends React.Component<Props, State> {
119 130
         }
120 131
     }
121 132
 
122
-    addGroupToFavorites(favorites: Array<Object>, group: Object) {
133
+    addGroupToFavorites(favorites: Array<group>, group: group) {
123 134
         group.isFav = true;
124 135
         favorites.push(group);
125 136
         favorites.sort(sortName);
126 137
     }
127 138
 
128
-    updateGroupFavorites(group: Object) {
139
+    updateGroupFavorites(group: group) {
129 140
         let newFavorites = [...this.state.favoriteGroups]
130 141
         if (this.isGroupInFavorites(group))
131 142
             this.removeGroupFromFavorites(newFavorites, group);
@@ -137,7 +148,7 @@ class GroupSelectionScreen extends React.Component<Props, State> {
137 148
             JSON.stringify(newFavorites));
138 149
     }
139 150
 
140
-    shouldDisplayAccordion(item: Object) {
151
+    shouldDisplayAccordion(item: groupCategory) {
141 152
         let shouldDisplay = false;
142 153
         for (let i = 0; i < item.content.length; i++) {
143 154
             if (stringMatchQuery(item.content[i].name, this.state.currentSearchString)) {
@@ -154,7 +165,7 @@ class GroupSelectionScreen extends React.Component<Props, State> {
154 165
      * @param item The article to render
155 166
      * @return {*}
156 167
      */
157
-    renderItem = ({item}: Object) => {
168
+    renderItem = ({item}: { item: groupCategory }) => {
158 169
         if (this.shouldDisplayAccordion(item)) {
159 170
             return (
160 171
                 <GroupListAccordion
@@ -170,18 +181,18 @@ class GroupSelectionScreen extends React.Component<Props, State> {
170 181
             return null;
171 182
     };
172 183
 
173
-    generateData(fetchedData: Object) {
184
+    generateData(fetchedData: { [key: string]: groupCategory }) {
174 185
         let data = [];
175 186
         for (let key in fetchedData) {
176 187
             this.formatGroups(fetchedData[key]);
177 188
             data.push(fetchedData[key]);
178 189
         }
179 190
         data.sort(sortName);
180
-        data.unshift({name: "FAVORITES", id: "0", content: this.state.favoriteGroups});
191
+        data.unshift({name: "FAVORITES", id: 0, content: this.state.favoriteGroups});
181 192
         return data;
182 193
     }
183 194
 
184
-    formatGroups(item: Object) {
195
+    formatGroups(item: groupCategory) {
185 196
         for (let i = 0; i < item.content.length; i++) {
186 197
             item.content[i].name = item.content[i].name.replace(REPLACE_REGEX, " ")
187 198
             item.content[i].isFav = this.isGroupInFavorites(item.content[i]);
@@ -194,7 +205,7 @@ class GroupSelectionScreen extends React.Component<Props, State> {
194 205
      * @param fetchedData
195 206
      * @return {*}
196 207
      * */
197
-    createDataset = (fetchedData: Object) => {
208
+    createDataset = (fetchedData: { [key: string]: groupCategory }) => {
198 209
         return [
199 210
             {
200 211
                 title: '',
@@ -219,4 +230,4 @@ class GroupSelectionScreen extends React.Component<Props, State> {
219 230
     }
220 231
 }
221 232
 
222
-export default withTheme(GroupSelectionScreen);
233
+export default GroupSelectionScreen;

Loading…
Cancel
Save