forked from vergnet/application-amicale
Improve planex group favorite handling
This commit is contained in:
parent
eef6f75414
commit
327488a470
4 changed files with 87 additions and 95 deletions
|
@ -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 {
|
||||
|
|
|
@ -14,22 +14,23 @@ import type {CustomThemeType} from '../../../managers/ThemeManager';
|
|||
|
||||
type PropsType = {
|
||||
item: PlanexGroupCategoryType,
|
||||
favorites: Array<PlanexGroupType>,
|
||||
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<PropsType> {
|
||||
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<PropsType> {
|
|||
<GroupListItem
|
||||
height={LIST_ITEM_HEIGHT}
|
||||
item={item}
|
||||
favorites={props.favorites}
|
||||
onPress={onPress}
|
||||
onStarPress={onStarPress}
|
||||
/>
|
||||
|
@ -80,7 +82,7 @@ class GroupListAccordion extends React.Component<PropsType> {
|
|||
return (
|
||||
<View>
|
||||
<AnimatedAccordion
|
||||
title={item.name}
|
||||
title={item.name.replace(REPLACE_REGEX, ' ')}
|
||||
style={{
|
||||
height: props.height,
|
||||
justifyContent: 'center',
|
||||
|
@ -94,11 +96,11 @@ class GroupListAccordion extends React.Component<PropsType> {
|
|||
/>
|
||||
) : 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}>
|
||||
<FlatList
|
||||
data={this.getData()}
|
||||
extraData={props.currentSearchString}
|
||||
extraData={props.currentSearchString + props.favorites.length}
|
||||
renderItem={this.getRenderItem}
|
||||
keyExtractor={this.keyExtractor}
|
||||
listKey={item.id.toString()}
|
||||
|
|
|
@ -10,40 +10,44 @@ type PropsType = {
|
|||
onPress: () => void,
|
||||
onStarPress: () => void,
|
||||
item: PlanexGroupType,
|
||||
favorites: Array<PlanexGroupType>,
|
||||
height: number,
|
||||
};
|
||||
|
||||
type StateType = {
|
||||
isFav: boolean,
|
||||
};
|
||||
const REPLACE_REGEX = /_/g;
|
||||
|
||||
class GroupListItem extends React.Component<PropsType> {
|
||||
isFav: boolean;
|
||||
|
||||
class GroupListItem extends React.Component<PropsType, StateType> {
|
||||
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<PlanexGroupType>): 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 (
|
||||
<List.Item
|
||||
title={props.item.name}
|
||||
title={props.item.name.replace(REPLACE_REGEX, ' ')}
|
||||
onPress={props.onPress}
|
||||
left={({size}: {size: number}): React.Node => (
|
||||
<List.Icon size={size} icon="chevron-right" />
|
||||
|
@ -52,8 +56,8 @@ class GroupListItem extends React.Component<PropsType, StateType> {
|
|||
<IconButton
|
||||
size={size}
|
||||
icon="star"
|
||||
onPress={this.onStarPress}
|
||||
color={state.isFav ? colors.tetrisScore : color}
|
||||
onPress={props.onStarPress}
|
||||
color={this.isFav ? colors.tetrisScore : color}
|
||||
/>
|
||||
)}
|
||||
style={{
|
||||
|
|
|
@ -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<PropsType, StateType> {
|
||||
/**
|
||||
* 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<PlanexGroupType>,
|
||||
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<PlanexGroupType>,
|
||||
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<PropsType, StateType> {
|
|||
*/
|
||||
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 (
|
||||
<GroupListAccordion
|
||||
item={item}
|
||||
favorites={[...favoriteGroups]}
|
||||
onGroupPress={this.onListItemPress}
|
||||
onFavoritePress={this.onListFavoritePress}
|
||||
currentSearchString={currentSearchString}
|
||||
favoriteNumber={favoriteGroups.length}
|
||||
height={LIST_ITEM_HEIGHT}
|
||||
/>
|
||||
);
|
||||
|
@ -145,21 +112,6 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> {
|
|||
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<PlanexGroupType>}
|
||||
*/
|
||||
getFormattedGroups(groups: Array<PlanexGroupType>): Array<PlanexGroupType> {
|
||||
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<PropsType, StateType> {
|
|||
* @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<PropsType, StateType> {
|
|||
// eslint-disable-next-line flowtype/no-weak-types
|
||||
(Object.values(fetchedData): Array<any>).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<PropsType, StateType> {
|
|||
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<PlanexGroupType>,
|
||||
} => {
|
||||
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<PlanexGroupType>,
|
||||
} => {
|
||||
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 (
|
||||
|
|
Loading…
Reference in a new issue