diff --git a/android/app/build.gradle b/android/app/build.gradle index e734773..e02980a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -136,8 +136,8 @@ android { applicationId 'fr.amicaleinsat.application' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 32 - versionName "3.1.4" + versionCode 34 + versionName "4.0.1" missingDimensionStrategy 'react-native-camera', 'general' } splits { diff --git a/src/components/Lists/PlanexGroups/GroupListAccordion.js b/src/components/Lists/PlanexGroups/GroupListAccordion.js index 1a15bfe..f9788b4 100644 --- a/src/components/Lists/PlanexGroups/GroupListAccordion.js +++ b/src/components/Lists/PlanexGroups/GroupListAccordion.js @@ -14,22 +14,23 @@ import type {CustomThemeType} from '../../../managers/ThemeManager'; type PropsType = { item: PlanexGroupCategoryType, + favorites: Array, onGroupPress: (PlanexGroupType) => void, onFavoritePress: (PlanexGroupType) => void, currentSearchString: string, - favoriteNumber: number, height: number, theme: CustomThemeType, }; const LIST_ITEM_HEIGHT = 64; +const REPLACE_REGEX = /_/g; class GroupListAccordion extends React.Component { shouldComponentUpdate(nextProps: PropsType): boolean { const {props} = this; return ( nextProps.currentSearchString !== props.currentSearchString || - nextProps.favoriteNumber !== props.favoriteNumber || + nextProps.favorites.length !== props.favorites.length || nextProps.item.content.length !== props.item.content.length ); } @@ -46,6 +47,7 @@ class GroupListAccordion extends React.Component { @@ -80,7 +82,7 @@ class GroupListAccordion extends React.Component { return ( { /> ) : null } - unmountWhenCollapsed // Only render list if expanded for increased performance - opened={props.item.id === 0 || props.currentSearchString.length > 0}> + unmountWhenCollapsed={item.id !== 0} // Only render list if expanded for increased performance + opened={props.currentSearchString.length > 0}> void, onStarPress: () => void, item: PlanexGroupType, + favorites: Array, height: number, }; -type StateType = { - isFav: boolean, -}; +const REPLACE_REGEX = /_/g; + +class GroupListItem extends React.Component { + isFav: boolean; -class GroupListItem extends React.Component { constructor(props: PropsType) { super(props); - this.state = { - isFav: props.item.isFav !== undefined && props.item.isFav, - }; + this.isFav = this.isGroupInFavorites(props.favorites); } - shouldComponentUpdate(prevProps: PropsType, prevState: StateType): boolean { - const {isFav} = this.state; - return prevState.isFav !== isFav; + shouldComponentUpdate(nextProps: PropsType): boolean { + const {favorites} = this.props; + const favChanged = favorites.length !== nextProps.favorites.length; + let newFavState = this.isFav; + if (favChanged) newFavState = this.isGroupInFavorites(nextProps.favorites); + const shouldUpdate = this.isFav !== newFavState; + this.isFav = newFavState; + return shouldUpdate; } - onStarPress = () => { - const {props} = this; - this.setState((prevState: StateType): StateType => ({ - isFav: !prevState.isFav, - })); - props.onStarPress(); - }; + isGroupInFavorites(favorites: Array): boolean { + const {item} = this.props; + for (let i = 0; i < favorites.length; i += 1) { + if (favorites[i].id === item.id) return true; + } + return false; + } render(): React.Node { - const {props, state} = this; + const {props} = this; const {colors} = props.theme; return ( ( @@ -52,8 +56,8 @@ class GroupListItem extends React.Component { )} style={{ diff --git a/src/screens/Planex/GroupSelectionScreen.js b/src/screens/Planex/GroupSelectionScreen.js index 5cbecf5..682cf40 100644 --- a/src/screens/Planex/GroupSelectionScreen.js +++ b/src/screens/Planex/GroupSelectionScreen.js @@ -15,7 +15,6 @@ const LIST_ITEM_HEIGHT = 70; export type PlanexGroupType = { name: string, id: number, - isFav: boolean, }; export type PlanexGroupCategoryType = { @@ -43,46 +42,11 @@ function sortName( } const GROUPS_URL = 'http://planex.insa-toulouse.fr/wsAdeGrp.php?projectId=1'; -const REPLACE_REGEX = /_/g; /** * Class defining planex group selection screen. */ class GroupSelectionScreen extends React.Component { - /** - * Removes the given group from the given array - * - * @param favorites The array containing favorites groups - * @param group The group to remove from the array - */ - static removeGroupFromFavorites( - favorites: Array, - group: PlanexGroupType, - ) { - for (let i = 0; i < favorites.length; i += 1) { - if (group.id === favorites[i].id) { - favorites.splice(i, 1); - break; - } - } - } - - /** - * Adds the given group to the given array - * - * @param favorites The array containing favorites groups - * @param group The group to add to the array - */ - static addGroupToFavorites( - favorites: Array, - group: PlanexGroupType, - ) { - const favGroup = {...group}; - favGroup.isFav = true; - favorites.push(favGroup); - favorites.sort(sortName); - } - constructor(props: PropsType) { super(props); this.state = { @@ -130,14 +94,17 @@ class GroupSelectionScreen extends React.Component { */ getRenderItem = ({item}: {item: PlanexGroupCategoryType}): React.Node => { const {currentSearchString, favoriteGroups} = this.state; - if (this.shouldDisplayAccordion(item)) { + if ( + this.shouldDisplayAccordion(item) || + (item.id === 0 && item.content.length === 0) + ) { return ( ); @@ -145,21 +112,6 @@ class GroupSelectionScreen extends React.Component { return null; }; - /** - * Replaces underscore by spaces and sets the favorite state of every group in the given category - * - * @param groups The groups to format - * @return {Array} - */ - getFormattedGroups(groups: Array): Array { - return groups.map((group: PlanexGroupType): PlanexGroupType => { - const newGroup = {...group}; - newGroup.name = group.name.replace(REPLACE_REGEX, ' '); - newGroup.isFav = this.isGroupInFavorites(group); - return newGroup; - }); - } - /** * Creates the dataset to be used in the FlatList * @@ -231,16 +183,8 @@ class GroupSelectionScreen extends React.Component { * @param group The group to add/remove to favorites */ updateGroupFavorites(group: PlanexGroupType) { - const {favoriteGroups} = this.state; - const newFavorites = [...favoriteGroups]; - if (this.isGroupInFavorites(group)) - GroupSelectionScreen.removeGroupFromFavorites(newFavorites, group); - else GroupSelectionScreen.addGroupToFavorites(newFavorites, group); - this.setState({favoriteGroups: newFavorites}); - AsyncStorageManager.set( - AsyncStorageManager.PREFERENCES.planexFavoriteGroups.key, - newFavorites, - ); + if (this.isGroupInFavorites(group)) this.removeGroupFromFavorites(group); + else this.addGroupToFavorites(group); } /** @@ -276,9 +220,7 @@ class GroupSelectionScreen extends React.Component { // eslint-disable-next-line flowtype/no-weak-types (Object.values(fetchedData): Array).forEach( (category: PlanexGroupCategoryType) => { - const newCat = {...category}; - newCat.content = this.getFormattedGroups(category.content); - data.push(newCat); + data.push(category); }, ); data.sort(sortName); @@ -290,6 +232,50 @@ class GroupSelectionScreen extends React.Component { return data; } + /** + * Removes the given group from the favorites + * + * @param group The group to remove from the array + */ + removeGroupFromFavorites(group: PlanexGroupType) { + this.setState((prevState: StateType): { + favoriteGroups: Array, + } => { + const {favoriteGroups} = prevState; + for (let i = 0; i < favoriteGroups.length; i += 1) { + if (group.id === favoriteGroups[i].id) { + favoriteGroups.splice(i, 1); + break; + } + } + AsyncStorageManager.set( + AsyncStorageManager.PREFERENCES.planexFavoriteGroups.key, + favoriteGroups, + ); + return {favoriteGroups}; + }); + } + + /** + * Adds the given group to favorites + * + * @param group The group to add to the array + */ + addGroupToFavorites(group: PlanexGroupType) { + this.setState((prevState: StateType): { + favoriteGroups: Array, + } => { + const {favoriteGroups} = prevState; + favoriteGroups.push(group); + favoriteGroups.sort(sortName); + AsyncStorageManager.set( + AsyncStorageManager.PREFERENCES.planexFavoriteGroups.key, + favoriteGroups, + ); + return {favoriteGroups}; + }); + } + render(): React.Node { const {props, state} = this; return (