Improve remaining files to match linter

This commit is contained in:
Arnaud Vergnet 2020-08-05 20:58:28 +02:00
parent cbe3777957
commit 1e81b2cd7b
39 changed files with 362 additions and 323 deletions

4
App.js
View file

@ -10,7 +10,7 @@ import {OverflowMenuProvider} from 'react-navigation-header-buttons';
import LocaleManager from './src/managers/LocaleManager'; import LocaleManager from './src/managers/LocaleManager';
import AsyncStorageManager from './src/managers/AsyncStorageManager'; import AsyncStorageManager from './src/managers/AsyncStorageManager';
import CustomIntroSlider from './src/components/Overrides/CustomIntroSlider'; import CustomIntroSlider from './src/components/Overrides/CustomIntroSlider';
import type {CustomTheme} from './src/managers/ThemeManager'; import type {CustomThemeType} from './src/managers/ThemeManager';
import ThemeManager from './src/managers/ThemeManager'; import ThemeManager from './src/managers/ThemeManager';
import MainNavigator from './src/navigation/MainNavigator'; import MainNavigator from './src/navigation/MainNavigator';
import AprilFoolsManager from './src/managers/AprilFoolsManager'; import AprilFoolsManager from './src/managers/AprilFoolsManager';
@ -35,7 +35,7 @@ type StateType = {
showIntro: boolean, showIntro: boolean,
showUpdate: boolean, showUpdate: boolean,
showAprilFools: boolean, showAprilFools: boolean,
currentTheme: CustomTheme | null, currentTheme: CustomThemeType | null,
}; };
export default class App extends React.Component<null, StateType> { export default class App extends React.Component<null, StateType> {

View file

@ -6,4 +6,5 @@ import {AppRegistry} from 'react-native';
import App from './App'; import App from './App';
import {name as appName} from './app.json'; import {name as appName} from './app.json';
// eslint-disable-next-line flowtype/require-return-type
AppRegistry.registerComponent(appName, () => App); AppRegistry.registerComponent(appName, () => App);

View file

@ -6,12 +6,13 @@
*/ */
module.exports = { module.exports = {
transformer: { transformer: {
getTransformOptions: async () => ({ // eslint-disable-next-line flowtype/require-return-type
transform: { getTransformOptions: async () => ({
experimentalImportSupport: false, transform: {
inlineRequires: false, experimentalImportSupport: false,
}, inlineRequires: false,
}), },
}, }),
},
}; };

View file

@ -4,10 +4,10 @@ import * as React from 'react';
import {View} from 'react-native'; import {View} from 'react-native';
import {Headline, withTheme} from 'react-native-paper'; import {Headline, withTheme} from 'react-native-paper';
import i18n from 'i18n-js'; import i18n from 'i18n-js';
import type {CustomTheme} from '../../../managers/ThemeManager'; import type {CustomThemeType} from '../../../managers/ThemeManager';
type PropsType = { type PropsType = {
theme: CustomTheme, theme: CustomThemeType,
}; };
class VoteNotAvailable extends React.Component<PropsType> { class VoteNotAvailable extends React.Component<PropsType> {

View file

@ -12,12 +12,12 @@ import {
import {FlatList, StyleSheet} from 'react-native'; import {FlatList, StyleSheet} from 'react-native';
import i18n from 'i18n-js'; import i18n from 'i18n-js';
import type {VoteTeamType} from '../../../screens/Amicale/VoteScreen'; import type {VoteTeamType} from '../../../screens/Amicale/VoteScreen';
import type {CustomTheme} from '../../../managers/ThemeManager'; import type {CustomThemeType} from '../../../managers/ThemeManager';
type PropsType = { type PropsType = {
teams: Array<VoteTeamType>, teams: Array<VoteTeamType>,
dateEnd: string, dateEnd: string,
theme: CustomTheme, theme: CustomThemeType,
}; };
const styles = StyleSheet.create({ const styles = StyleSheet.create({

View file

@ -9,14 +9,14 @@ import {
} from 'react-native-paper'; } from 'react-native-paper';
import {StyleSheet} from 'react-native'; import {StyleSheet} from 'react-native';
import i18n from 'i18n-js'; import i18n from 'i18n-js';
import type {CustomTheme} from '../../../managers/ThemeManager'; import type {CustomThemeType} from '../../../managers/ThemeManager';
type PropsType = { type PropsType = {
startDate: string | null, startDate: string | null,
justVoted: boolean, justVoted: boolean,
hasVoted: boolean, hasVoted: boolean,
isVoteRunning: boolean, isVoteRunning: boolean,
theme: CustomTheme, theme: CustomThemeType,
}; };
const styles = StyleSheet.create({ const styles = StyleSheet.create({

View file

@ -5,10 +5,10 @@ import {View} from 'react-native';
import {List, withTheme} from 'react-native-paper'; import {List, withTheme} from 'react-native-paper';
import Collapsible from 'react-native-collapsible'; import Collapsible from 'react-native-collapsible';
import * as Animatable from 'react-native-animatable'; import * as Animatable from 'react-native-animatable';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
type PropsType = { type PropsType = {
theme: CustomTheme, theme: CustomThemeType,
title: string, title: string,
subtitle?: string, subtitle?: string,
left?: () => React.Node, left?: () => React.Node,

View file

@ -7,13 +7,14 @@ import * as Animatable from 'react-native-animatable';
import {StackNavigationProp} from '@react-navigation/stack'; import {StackNavigationProp} from '@react-navigation/stack';
import AutoHideHandler from '../../utils/AutoHideHandler'; import AutoHideHandler from '../../utils/AutoHideHandler';
import CustomTabBar from '../Tabbar/CustomTabBar'; import CustomTabBar from '../Tabbar/CustomTabBar';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
import type {OnScrollType} from '../../utils/AutoHideHandler';
const AnimatedFAB = Animatable.createAnimatableComponent(FAB); const AnimatedFAB = Animatable.createAnimatableComponent(FAB);
type PropsType = { type PropsType = {
navigation: StackNavigationProp, navigation: StackNavigationProp,
theme: CustomTheme, theme: CustomThemeType,
onPress: (action: string, data?: string) => void, onPress: (action: string, data?: string) => void,
seekAttention: boolean, seekAttention: boolean,
}; };
@ -94,7 +95,7 @@ class AnimatedBottomBar extends React.Component<PropsType, StateType> {
} }
}; };
onScroll = (event: SyntheticEvent<EventTarget>) => { onScroll = (event: OnScrollType) => {
this.hideHandler.onScroll(event); this.hideHandler.onScroll(event);
}; };

View file

@ -2,7 +2,7 @@
import * as React from 'react'; import * as React from 'react';
import {Collapsible} from 'react-navigation-collapsible'; import {Collapsible} from 'react-navigation-collapsible';
import {withCollapsible} from '../../utils/withCollapsible'; import withCollapsible from '../../utils/withCollapsible';
import CustomTabBar from '../Tabbar/CustomTabBar'; import CustomTabBar from '../Tabbar/CustomTabBar';
export type CollapsibleComponentPropsType = { export type CollapsibleComponentPropsType = {

View file

@ -5,11 +5,11 @@ import {List, withTheme} from 'react-native-paper';
import {View} from 'react-native'; import {View} from 'react-native';
import i18n from 'i18n-js'; import i18n from 'i18n-js';
import {StackNavigationProp} from '@react-navigation/stack'; import {StackNavigationProp} from '@react-navigation/stack';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
type PropsType = { type PropsType = {
navigation: StackNavigationProp, navigation: StackNavigationProp,
theme: CustomTheme, theme: CustomThemeType,
}; };
class ActionsDashBoardItem extends React.Component<PropsType> { class ActionsDashBoardItem extends React.Component<PropsType> {

View file

@ -10,12 +10,12 @@ import {
} from 'react-native-paper'; } from 'react-native-paper';
import {StyleSheet, View} from 'react-native'; import {StyleSheet, View} from 'react-native';
import i18n from 'i18n-js'; import i18n from 'i18n-js';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
type PropsType = { type PropsType = {
eventNumber: number, eventNumber: number,
clickAction: () => void, clickAction: () => void,
theme: CustomTheme, theme: CustomThemeType,
children?: React.Node, children?: React.Node,
}; };

View file

@ -4,13 +4,13 @@ import * as React from 'react';
import {Badge, TouchableRipple, withTheme} from 'react-native-paper'; import {Badge, TouchableRipple, withTheme} from 'react-native-paper';
import {Dimensions, Image, View} from 'react-native'; import {Dimensions, Image, View} from 'react-native';
import * as Animatable from 'react-native-animatable'; import * as Animatable from 'react-native-animatable';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
type PropsType = { type PropsType = {
image: string | null, image: string | null,
onPress: () => void | null, onPress: () => void | null,
badgeCount: number | null, badgeCount: number | null,
theme: CustomTheme, theme: CustomThemeType,
}; };
const AnimatableBadge = Animatable.createAnimatableComponent(Badge); const AnimatableBadge = Animatable.createAnimatableComponent(Badge);

View file

@ -7,14 +7,14 @@ import type {
ClubCategoryType, ClubCategoryType,
ClubType, ClubType,
} from '../../../screens/Amicale/Clubs/ClubListScreen'; } from '../../../screens/Amicale/Clubs/ClubListScreen';
import type {CustomTheme} from '../../../managers/ThemeManager'; import type {CustomThemeType} from '../../../managers/ThemeManager';
type PropsType = { type PropsType = {
onPress: () => void, onPress: () => void,
categoryTranslator: (id: number) => ClubCategoryType, categoryTranslator: (id: number) => ClubCategoryType,
item: ClubType, item: ClubType,
height: number, height: number,
theme: CustomTheme, theme: CustomThemeType,
}; };
class ClubListItem extends React.Component<PropsType> { class ClubListItem extends React.Component<PropsType> {

View file

@ -10,13 +10,13 @@ import type {
ServiceCategoryType, ServiceCategoryType,
ServiceItemType, ServiceItemType,
} from '../../../managers/ServicesManager'; } from '../../../managers/ServicesManager';
import type {CustomTheme} from '../../../managers/ThemeManager'; import type {CustomThemeType} from '../../../managers/ThemeManager';
type PropsType = { type PropsType = {
item: ServiceCategoryType, item: ServiceCategoryType,
activeDashboard: Array<string>, activeDashboard: Array<string>,
onPress: (service: ServiceItemType) => void, onPress: (service: ServiceItemType) => void,
theme: CustomTheme, theme: CustomThemeType,
}; };
const LIST_ITEM_HEIGHT = 64; const LIST_ITEM_HEIGHT = 64;

View file

@ -3,7 +3,7 @@
import * as React from 'react'; import * as React from 'react';
import {Image} from 'react-native'; import {Image} from 'react-native';
import {List, withTheme} from 'react-native-paper'; import {List, withTheme} from 'react-native-paper';
import type {CustomTheme} from '../../../managers/ThemeManager'; import type {CustomThemeType} from '../../../managers/ThemeManager';
import type {ServiceItemType} from '../../../managers/ServicesManager'; import type {ServiceItemType} from '../../../managers/ServicesManager';
type PropsType = { type PropsType = {
@ -11,7 +11,7 @@ type PropsType = {
isActive: boolean, isActive: boolean,
height: number, height: number,
onPress: () => void, onPress: () => void,
theme: CustomTheme, theme: CustomThemeType,
}; };
class DashboardEditItem extends React.Component<PropsType> { class DashboardEditItem extends React.Component<PropsType> {

View file

@ -3,13 +3,13 @@
import * as React from 'react'; import * as React from 'react';
import {TouchableRipple, withTheme} from 'react-native-paper'; import {TouchableRipple, withTheme} from 'react-native-paper';
import {Dimensions, Image, View} from 'react-native'; import {Dimensions, Image, View} from 'react-native';
import type {CustomTheme} from '../../../managers/ThemeManager'; import type {CustomThemeType} from '../../../managers/ThemeManager';
type PropsType = { type PropsType = {
image: string, image: string,
isActive: boolean, isActive: boolean,
onPress: () => void, onPress: () => void,
theme: CustomTheme, theme: CustomThemeType,
}; };
/** /**

View file

@ -4,7 +4,7 @@ import * as React from 'react';
import {Avatar, List, withTheme} from 'react-native-paper'; import {Avatar, List, withTheme} from 'react-native-paper';
import i18n from 'i18n-js'; import i18n from 'i18n-js';
import {StackNavigationProp} from '@react-navigation/stack'; import {StackNavigationProp} from '@react-navigation/stack';
import type {CustomTheme} from '../../../managers/ThemeManager'; import type {CustomThemeType} from '../../../managers/ThemeManager';
import type {DeviceType} from '../../../screens/Amicale/Equipment/EquipmentListScreen'; import type {DeviceType} from '../../../screens/Amicale/Equipment/EquipmentListScreen';
import { import {
getFirstEquipmentAvailability, getFirstEquipmentAvailability,
@ -17,7 +17,7 @@ type PropsType = {
userDeviceRentDates: [string, string], userDeviceRentDates: [string, string],
item: DeviceType, item: DeviceType,
height: number, height: number,
theme: CustomTheme, theme: CustomThemeType,
}; };
class EquipmentListItem extends React.Component<PropsType> { class EquipmentListItem extends React.Component<PropsType> {

View file

@ -10,7 +10,7 @@ import type {
PlanexGroupType, PlanexGroupType,
PlanexGroupCategoryType, PlanexGroupCategoryType,
} from '../../../screens/Planex/GroupSelectionScreen'; } from '../../../screens/Planex/GroupSelectionScreen';
import type {CustomTheme} from '../../../managers/ThemeManager'; import type {CustomThemeType} from '../../../managers/ThemeManager';
type PropsType = { type PropsType = {
item: PlanexGroupCategoryType, item: PlanexGroupCategoryType,
@ -19,7 +19,7 @@ type PropsType = {
currentSearchString: string, currentSearchString: string,
favoriteNumber: number, favoriteNumber: number,
height: number, height: number,
theme: CustomTheme, theme: CustomThemeType,
}; };
const LIST_ITEM_HEIGHT = 64; const LIST_ITEM_HEIGHT = 64;

View file

@ -2,11 +2,11 @@
import * as React from 'react'; import * as React from 'react';
import {IconButton, List, withTheme} from 'react-native-paper'; import {IconButton, List, withTheme} from 'react-native-paper';
import type {CustomTheme} from '../../../managers/ThemeManager'; import type {CustomThemeType} from '../../../managers/ThemeManager';
import type {PlanexGroupType} from '../../../screens/Planex/GroupSelectionScreen'; import type {PlanexGroupType} from '../../../screens/Planex/GroupSelectionScreen';
type PropsType = { type PropsType = {
theme: CustomTheme, theme: CustomThemeType,
onPress: () => void, onPress: () => void,
onStarPress: () => void, onStarPress: () => void,
item: PlanexGroupType, item: PlanexGroupType,

View file

@ -18,12 +18,12 @@ import {
View, View,
} from 'react-native'; } from 'react-native';
import Mascot from './Mascot'; import Mascot from './Mascot';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
import SpeechArrow from './SpeechArrow'; import SpeechArrow from './SpeechArrow';
import AsyncStorageManager from '../../managers/AsyncStorageManager'; import AsyncStorageManager from '../../managers/AsyncStorageManager';
type PropsType = { type PropsType = {
theme: CustomTheme, theme: CustomThemeType,
icon: string, icon: string,
title: string, title: string,
message: string, message: string,

View file

@ -4,10 +4,10 @@ import * as React from 'react';
import {View} from 'react-native'; import {View} from 'react-native';
import {withTheme} from 'react-native-paper'; import {withTheme} from 'react-native-paper';
import {Agenda} from 'react-native-calendars'; import {Agenda} from 'react-native-calendars';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
type PropsType = { type PropsType = {
theme: CustomTheme, theme: CustomThemeType,
onRef: (ref: Agenda) => void, onRef: (ref: Agenda) => void,
}; };

View file

@ -5,10 +5,10 @@ import * as React from 'react';
import {Text, withTheme} from 'react-native-paper'; import {Text, withTheme} from 'react-native-paper';
import HTML from 'react-native-render-html'; import HTML from 'react-native-render-html';
import {Linking} from 'react-native'; import {Linking} from 'react-native';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
type PropsType = { type PropsType = {
theme: CustomTheme, theme: CustomThemeType,
html: string, html: string,
}; };

View file

@ -4,10 +4,10 @@ import * as React from 'react';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import {HeaderButton, HeaderButtons} from 'react-navigation-header-buttons'; import {HeaderButton, HeaderButtons} from 'react-navigation-header-buttons';
import {withTheme} from 'react-native-paper'; import {withTheme} from 'react-native-paper';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
const MaterialHeaderButton = (props: { const MaterialHeaderButton = (props: {
theme: CustomTheme, theme: CustomThemeType,
color: string, color: string,
}): React.Node => { }): React.Node => {
const {color, theme} = props; const {color, theme} = props;

View file

@ -5,7 +5,7 @@ import {withTheme} from 'react-native-paper';
import {Modalize} from 'react-native-modalize'; import {Modalize} from 'react-native-modalize';
import {View} from 'react-native-animatable'; import {View} from 'react-native-animatable';
import CustomTabBar from '../Tabbar/CustomTabBar'; import CustomTabBar from '../Tabbar/CustomTabBar';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
/** /**
* Abstraction layer for Modalize component, using custom configuration * Abstraction layer for Modalize component, using custom configuration
@ -14,7 +14,7 @@ import type {CustomTheme} from '../../managers/ThemeManager';
* @return {*} * @return {*}
*/ */
function CustomModal(props: { function CustomModal(props: {
theme: CustomTheme, theme: CustomThemeType,
onRef: (re: Modalize) => void, onRef: (re: Modalize) => void,
children?: React.Node, children?: React.Node,
}): React.Node { }): React.Node {

View file

@ -4,10 +4,10 @@ import * as React from 'react';
import {Text, withTheme} from 'react-native-paper'; import {Text, withTheme} from 'react-native-paper';
import {View} from 'react-native-animatable'; import {View} from 'react-native-animatable';
import Slider, {SliderProps} from '@react-native-community/slider'; import Slider, {SliderProps} from '@react-native-community/slider';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
type PropsType = { type PropsType = {
theme: CustomTheme, theme: CustomThemeType,
valueSuffix?: string, valueSuffix?: string,
...SliderProps, ...SliderProps,
}; };

View file

@ -3,7 +3,7 @@
import * as React from 'react'; import * as React from 'react';
import {View} from 'react-native'; import {View} from 'react-native';
import {ActivityIndicator, withTheme} from 'react-native-paper'; import {ActivityIndicator, withTheme} from 'react-native-paper';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
/** /**
* Component used to display a header button * Component used to display a header button
@ -12,7 +12,7 @@ import type {CustomTheme} from '../../managers/ThemeManager';
* @return {*} * @return {*}
*/ */
function BasicLoadingScreen(props: { function BasicLoadingScreen(props: {
theme: CustomTheme, theme: CustomThemeType,
isAbsolute: boolean, isAbsolute: boolean,
}): React.Node { }): React.Node {
const {theme, isAbsolute} = props; const {theme, isAbsolute} = props;

View file

@ -8,11 +8,11 @@ import i18n from 'i18n-js';
import * as Animatable from 'react-native-animatable'; import * as Animatable from 'react-native-animatable';
import {StackNavigationProp} from '@react-navigation/stack'; import {StackNavigationProp} from '@react-navigation/stack';
import {ERROR_TYPE} from '../../utils/WebData'; import {ERROR_TYPE} from '../../utils/WebData';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
type PropsType = { type PropsType = {
navigation: StackNavigationProp, navigation: StackNavigationProp,
theme: CustomTheme, theme: CustomThemeType,
route: {name: string}, route: {name: string},
onRefresh?: () => void, onRefresh?: () => void,
errorCode?: number, errorCode?: number,
@ -47,7 +47,7 @@ const styles = StyleSheet.create({
class ErrorView extends React.PureComponent<PropsType> { class ErrorView extends React.PureComponent<PropsType> {
static defaultProps = { static defaultProps = {
onRefresh: (): void => null, onRefresh: () => {},
errorCode: 0, errorCode: 0,
icon: '', icon: '',
message: '', message: '',
@ -141,10 +141,12 @@ class ErrorView extends React.PureComponent<PropsType> {
this.icon = 'alert-circle-outline'; this.icon = 'alert-circle-outline';
break; break;
} }
this.message += `\n\nCode ${props.errorCode}`; this.message += `\n\nCode ${
props.errorCode != null ? props.errorCode : -1
}`;
} else { } else {
this.message = props.message; this.message = props.message != null ? props.message : '';
this.icon = props.icon; this.icon = props.icon != null ? props.icon : '';
} }
} }
@ -168,6 +170,7 @@ class ErrorView extends React.PureComponent<PropsType> {
<View style={styles.inner}> <View style={styles.inner}>
<View style={styles.iconContainer}> <View style={styles.iconContainer}>
<MaterialCommunityIcons <MaterialCommunityIcons
// $FlowFixMe
name={this.icon} name={this.icon}
size={150} size={150}
color={props.theme.colors.textDisabled} color={props.theme.colors.textDisabled}

View file

@ -9,7 +9,7 @@ import {Collapsible} from 'react-navigation-collapsible';
import {StackNavigationProp} from '@react-navigation/stack'; import {StackNavigationProp} from '@react-navigation/stack';
import ErrorView from './ErrorView'; import ErrorView from './ErrorView';
import BasicLoadingScreen from './BasicLoadingScreen'; import BasicLoadingScreen from './BasicLoadingScreen';
import {withCollapsible} from '../../utils/withCollapsible'; import withCollapsible from '../../utils/withCollapsible';
import CustomTabBar from '../Tabbar/CustomTabBar'; import CustomTabBar from '../Tabbar/CustomTabBar';
import {ERROR_TYPE, readData} from '../../utils/WebData'; import {ERROR_TYPE, readData} from '../../utils/WebData';
import CollapsibleSectionList from '../Collapsible/CollapsibleSectionList'; import CollapsibleSectionList from '../Collapsible/CollapsibleSectionList';

View file

@ -14,7 +14,7 @@ import {withTheme} from 'react-native-paper';
import {StackNavigationProp} from '@react-navigation/stack'; import {StackNavigationProp} from '@react-navigation/stack';
import {Collapsible} from 'react-navigation-collapsible'; import {Collapsible} from 'react-navigation-collapsible';
import type {CustomThemeType} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
import {withCollapsible} from '../../utils/withCollapsible'; import withCollapsible from '../../utils/withCollapsible';
import MaterialHeaderButtons, {Item} from '../Overrides/CustomHeaderButton'; import MaterialHeaderButtons, {Item} from '../Overrides/CustomHeaderButton';
import {ERROR_TYPE} from '../../utils/WebData'; import {ERROR_TYPE} from '../../utils/WebData';
import ErrorView from './ErrorView'; import ErrorView from './ErrorView';

View file

@ -7,7 +7,7 @@ import {Collapsible} from 'react-navigation-collapsible';
import {StackNavigationProp} from '@react-navigation/stack'; import {StackNavigationProp} from '@react-navigation/stack';
import TabIcon from './TabIcon'; import TabIcon from './TabIcon';
import TabHomeIcon from './TabHomeIcon'; import TabHomeIcon from './TabHomeIcon';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
type RouteType = { type RouteType = {
name: string, name: string,
@ -33,7 +33,7 @@ type PropsType = {
}, },
}, },
navigation: StackNavigationProp, navigation: StackNavigationProp,
theme: CustomTheme, theme: CustomThemeType,
}; };
type StateType = { type StateType = {

View file

@ -6,13 +6,13 @@ import {FAB, TouchableRipple, withTheme} from 'react-native-paper';
import * as Animatable from 'react-native-animatable'; import * as Animatable from 'react-native-animatable';
import FOCUSED_ICON from '../../../assets/tab-icon.png'; import FOCUSED_ICON from '../../../assets/tab-icon.png';
import UNFOCUSED_ICON from '../../../assets/tab-icon-outline.png'; import UNFOCUSED_ICON from '../../../assets/tab-icon-outline.png';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
type PropsType = { type PropsType = {
focused: boolean, focused: boolean,
onPress: () => void, onPress: () => void,
onLongPress: () => void, onLongPress: () => void,
theme: CustomTheme, theme: CustomThemeType,
tabBarHeight: number, tabBarHeight: number,
}; };

View file

@ -6,7 +6,7 @@ import {TouchableRipple, withTheme} from 'react-native-paper';
import type {MaterialCommunityIconsGlyphs} from 'react-native-vector-icons/MaterialCommunityIcons'; import type {MaterialCommunityIconsGlyphs} from 'react-native-vector-icons/MaterialCommunityIcons';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import * as Animatable from 'react-native-animatable'; import * as Animatable from 'react-native-animatable';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
type PropsType = { type PropsType = {
focused: boolean, focused: boolean,
@ -15,7 +15,7 @@ type PropsType = {
icon: MaterialCommunityIconsGlyphs, icon: MaterialCommunityIconsGlyphs,
onPress: () => void, onPress: () => void,
onLongPress: () => void, onLongPress: () => void,
theme: CustomTheme, theme: CustomThemeType,
extraData: null | boolean | number | string, extraData: null | boolean | number | string,
}; };

View file

@ -145,9 +145,7 @@ class AboutScreen extends React.Component<PropsType> {
*/ */
additionalDevData = [ additionalDevData = [
{ {
onPressCallback: () => { onPressCallback: () => {},
console.log('Meme this');
},
icon: 'account', icon: 'account',
text: 'Yohan SIMARD', text: 'Yohan SIMARD',
showChevron: false, showChevron: false,

View file

@ -1,14 +1,16 @@
import ShapeL from "../Shapes/ShapeL"; // @flow
import ShapeI from "../Shapes/ShapeI";
import ShapeJ from "../Shapes/ShapeJ"; import ShapeL from '../Shapes/ShapeL';
import ShapeO from "../Shapes/ShapeO"; import ShapeI from '../Shapes/ShapeI';
import ShapeS from "../Shapes/ShapeS"; import ShapeJ from '../Shapes/ShapeJ';
import ShapeT from "../Shapes/ShapeT"; import ShapeO from '../Shapes/ShapeO';
import ShapeZ from "../Shapes/ShapeZ"; import ShapeS from '../Shapes/ShapeS';
import type {Coordinates} from '../Shapes/BaseShape'; import ShapeT from '../Shapes/ShapeT';
import BaseShape from "../Shapes/BaseShape"; import ShapeZ from '../Shapes/ShapeZ';
import type {Grid} from "../components/GridComponent"; import type {CoordinatesType} from '../Shapes/BaseShape';
import type {CustomTheme} from "../../../managers/ThemeManager"; import BaseShape from '../Shapes/BaseShape';
import type {GridType} from '../components/GridComponent';
import type {CustomThemeType} from '../../../managers/ThemeManager';
/** /**
* Class used as an abstraction layer for shapes. * Class used as an abstraction layer for shapes.
@ -16,157 +18,167 @@ import type {CustomTheme} from "../../../managers/ThemeManager";
* *
*/ */
export default class Piece { export default class Piece {
shapes = [ShapeL, ShapeI, ShapeJ, ShapeO, ShapeS, ShapeT, ShapeZ];
#shapes = [ currentShape: BaseShape;
ShapeL,
ShapeI,
ShapeJ,
ShapeO,
ShapeS,
ShapeT,
ShapeZ,
];
#currentShape: BaseShape;
#theme: CustomTheme;
/** theme: CustomThemeType;
* Initializes this piece's color and shape
* /**
* @param theme Object containing current theme * Initializes this piece's color and shape
*/ *
constructor(theme: CustomTheme) { * @param theme Object containing current theme
this.#currentShape = this.getRandomShape(theme); */
this.#theme = theme; constructor(theme: CustomThemeType) {
this.currentShape = this.getRandomShape(theme);
this.theme = theme;
}
/**
* Gets a random shape object
*
* @param theme Object containing current theme
*/
getRandomShape(theme: CustomThemeType): BaseShape {
return new this.shapes[Math.floor(Math.random() * 7)](theme);
}
/**
* Removes the piece from the given grid
*
* @param grid The grid to remove the piece from
*/
removeFromGrid(grid: GridType) {
const pos: Array<CoordinatesType> = this.currentShape.getCellsCoordinates(
true,
);
pos.forEach((coordinates: CoordinatesType) => {
// eslint-disable-next-line no-param-reassign
grid[coordinates.y][coordinates.x] = {
color: this.theme.colors.tetrisBackground,
isEmpty: true,
key: grid[coordinates.y][coordinates.x].key,
};
});
}
/**
* Adds this piece to the given grid
*
* @param grid The grid to add the piece to
* @param isPreview Should we use this piece's current position to determine the cells?
*/
toGrid(grid: GridType, isPreview: boolean) {
const pos: Array<CoordinatesType> = this.currentShape.getCellsCoordinates(
!isPreview,
);
pos.forEach((coordinates: CoordinatesType) => {
// eslint-disable-next-line no-param-reassign
grid[coordinates.y][coordinates.x] = {
color: this.currentShape.getColor(),
isEmpty: false,
key: grid[coordinates.y][coordinates.x].key,
};
});
}
/**
* Checks if the piece's current position is valid
*
* @param grid The current game grid
* @param width The grid's width
* @param height The grid's height
* @return {boolean} If the position is valid
*/
isPositionValid(grid: GridType, width: number, height: number): boolean {
let isValid = true;
const pos: Array<CoordinatesType> = this.currentShape.getCellsCoordinates(
true,
);
for (let i = 0; i < pos.length; i += 1) {
if (
pos[i].x >= width ||
pos[i].x < 0 ||
pos[i].y >= height ||
pos[i].y < 0 ||
!grid[pos[i].y][pos[i].x].isEmpty
) {
isValid = false;
break;
}
} }
return isValid;
}
/** /**
* Gets a random shape object * Tries to move the piece by the given offset on the given grid
* *
* @param theme Object containing current theme * @param x Position X offset
*/ * @param y Position Y offset
getRandomShape(theme: CustomTheme) { * @param grid The grid to move the piece on
return new this.#shapes[Math.floor(Math.random() * 7)](theme); * @param width The grid's width
* @param height The grid's height
* @param freezeCallback Callback to use if the piece should freeze itself
* @return {boolean} True if the move was valid, false otherwise
*/
tryMove(
x: number,
y: number,
grid: GridType,
width: number,
height: number,
freezeCallback: () => void,
): boolean {
let newX = x;
let newY = y;
if (x > 1) newX = 1; // Prevent moving from more than one tile
if (x < -1) newX = -1;
if (y > 1) newY = 1;
if (y < -1) newY = -1;
if (x !== 0 && y !== 0) newY = 0; // Prevent diagonal movement
this.removeFromGrid(grid);
this.currentShape.move(newX, newY);
const isValid = this.isPositionValid(grid, width, height);
if (!isValid) this.currentShape.move(-newX, -newY);
const shouldFreeze = !isValid && newY !== 0;
this.toGrid(grid, false);
if (shouldFreeze) freezeCallback();
return isValid;
}
/**
* Tries to rotate the piece
*
* @param grid The grid to rotate the piece on
* @param width The grid's width
* @param height The grid's height
* @return {boolean} True if the rotation was valid, false otherwise
*/
tryRotate(grid: GridType, width: number, height: number): boolean {
this.removeFromGrid(grid);
this.currentShape.rotate(true);
if (!this.isPositionValid(grid, width, height)) {
this.currentShape.rotate(false);
this.toGrid(grid, false);
return false;
} }
this.toGrid(grid, false);
return true;
}
/** /**
* Removes the piece from the given grid * Gets this piece used cells coordinates
* *
* @param grid The grid to remove the piece from * @return {Array<CoordinatesType>} An array of coordinates
*/ */
removeFromGrid(grid: Grid) { getCoordinates(): Array<CoordinatesType> {
const pos: Array<Coordinates> = this.#currentShape.getCellsCoordinates(true); return this.currentShape.getCellsCoordinates(true);
for (let i = 0; i < pos.length; i++) { }
grid[pos[i].y][pos[i].x] = {
color: this.#theme.colors.tetrisBackground,
isEmpty: true,
key: grid[pos[i].y][pos[i].x].key
};
}
}
/** getCurrentShape(): BaseShape {
* Adds this piece to the given grid return this.currentShape;
* }
* @param grid The grid to add the piece to
* @param isPreview Should we use this piece's current position to determine the cells?
*/
toGrid(grid: Grid, isPreview: boolean) {
const pos: Array<Coordinates> = this.#currentShape.getCellsCoordinates(!isPreview);
for (let i = 0; i < pos.length; i++) {
grid[pos[i].y][pos[i].x] = {
color: this.#currentShape.getColor(),
isEmpty: false,
key: grid[pos[i].y][pos[i].x].key
};
}
}
/**
* Checks if the piece's current position is valid
*
* @param grid The current game grid
* @param width The grid's width
* @param height The grid's height
* @return {boolean} If the position is valid
*/
isPositionValid(grid: Grid, width: number, height: number) {
let isValid = true;
const pos: Array<Coordinates> = this.#currentShape.getCellsCoordinates(true);
for (let i = 0; i < pos.length; i++) {
if (pos[i].x >= width
|| pos[i].x < 0
|| pos[i].y >= height
|| pos[i].y < 0
|| !grid[pos[i].y][pos[i].x].isEmpty) {
isValid = false;
break;
}
}
return isValid;
}
/**
* Tries to move the piece by the given offset on the given grid
*
* @param x Position X offset
* @param y Position Y offset
* @param grid The grid to move the piece on
* @param width The grid's width
* @param height The grid's height
* @param freezeCallback Callback to use if the piece should freeze itself
* @return {boolean} True if the move was valid, false otherwise
*/
tryMove(x: number, y: number, grid: Grid, width: number, height: number, freezeCallback: () => void) {
if (x > 1) x = 1; // Prevent moving from more than one tile
if (x < -1) x = -1;
if (y > 1) y = 1;
if (y < -1) y = -1;
if (x !== 0 && y !== 0) y = 0; // Prevent diagonal movement
this.removeFromGrid(grid);
this.#currentShape.move(x, y);
let isValid = this.isPositionValid(grid, width, height);
if (!isValid)
this.#currentShape.move(-x, -y);
let shouldFreeze = !isValid && y !== 0;
this.toGrid(grid, false);
if (shouldFreeze)
freezeCallback();
return isValid;
}
/**
* Tries to rotate the piece
*
* @param grid The grid to rotate the piece on
* @param width The grid's width
* @param height The grid's height
* @return {boolean} True if the rotation was valid, false otherwise
*/
tryRotate(grid: Grid, width: number, height: number) {
this.removeFromGrid(grid);
this.#currentShape.rotate(true);
if (!this.isPositionValid(grid, width, height)) {
this.#currentShape.rotate(false);
this.toGrid(grid, false);
return false;
}
this.toGrid(grid, false);
return true;
}
/**
* Gets this piece used cells coordinates
*
* @return {Array<Coordinates>} An array of coordinates
*/
getCoordinates(): Array<Coordinates> {
return this.#currentShape.getCellsCoordinates(true);
}
getCurrentShape() {
return this.#currentShape;
}
} }

View file

@ -19,7 +19,7 @@ import MaterialHeaderButtons, {
Item, Item,
} from '../../components/Overrides/CustomHeaderButton'; } from '../../components/Overrides/CustomHeaderButton';
import AnimatedFAB from '../../components/Animations/AnimatedFAB'; import AnimatedFAB from '../../components/Animations/AnimatedFAB';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
import ConnectionManager from '../../managers/ConnectionManager'; import ConnectionManager from '../../managers/ConnectionManager';
import LogoutDialog from '../../components/Amicale/LogoutDialog'; import LogoutDialog from '../../components/Amicale/LogoutDialog';
import AsyncStorageManager from '../../managers/AsyncStorageManager'; import AsyncStorageManager from '../../managers/AsyncStorageManager';
@ -78,7 +78,7 @@ type RawDashboardType = {
type PropsType = { type PropsType = {
navigation: StackNavigationProp, navigation: StackNavigationProp,
route: {params: {nextScreen: string, data: {...}}}, route: {params: {nextScreen: string, data: {...}}},
theme: CustomTheme, theme: CustomThemeType,
}; };
type StateType = { type StateType = {

View file

@ -6,7 +6,7 @@ import i18n from 'i18n-js';
import {View} from 'react-native'; import {View} from 'react-native';
import {CommonActions} from '@react-navigation/native'; import {CommonActions} from '@react-navigation/native';
import {StackNavigationProp} from '@react-navigation/stack'; import {StackNavigationProp} from '@react-navigation/stack';
import type {CustomTheme} from '../../managers/ThemeManager'; import type {CustomThemeType} from '../../managers/ThemeManager';
import ThemeManager from '../../managers/ThemeManager'; import ThemeManager from '../../managers/ThemeManager';
import WebViewScreen from '../../components/Screens/WebViewScreen'; import WebViewScreen from '../../components/Screens/WebViewScreen';
import AsyncStorageManager from '../../managers/AsyncStorageManager'; import AsyncStorageManager from '../../managers/AsyncStorageManager';
@ -22,7 +22,7 @@ import MascotPopup from '../../components/Mascot/MascotPopup';
type PropsType = { type PropsType = {
navigation: StackNavigationProp, navigation: StackNavigationProp,
route: {params: {group: PlanexGroupType}}, route: {params: {group: PlanexGroupType}},
theme: CustomTheme, theme: CustomThemeType,
}; };
type StateType = { type StateType = {

View file

@ -6,7 +6,7 @@ import {CommonActions} from '@react-navigation/native';
import {StackNavigationProp} from '@react-navigation/stack'; import {StackNavigationProp} from '@react-navigation/stack';
import CardList from '../../components/Lists/CardList/CardList'; import CardList from '../../components/Lists/CardList/CardList';
import CustomTabBar from '../../components/Tabbar/CustomTabBar'; import CustomTabBar from '../../components/Tabbar/CustomTabBar';
import {withCollapsible} from '../../utils/withCollapsible'; import withCollapsible from '../../utils/withCollapsible';
import type {ServiceCategoryType} from '../../managers/ServicesManager'; import type {ServiceCategoryType} from '../../managers/ServicesManager';
type PropsType = { type PropsType = {

View file

@ -1,70 +1,85 @@
// @flow // @flow
import * as React from 'react';
const speedOffset = 5; const speedOffset = 5;
type ListenerFunctionType = (shouldHide: boolean) => void;
export type OnScrollType = {
nativeEvent: {
contentInset: {bottom: number, left: number, right: number, top: number},
contentOffset: {x: number, y: number},
contentSize: {height: number, width: number},
layoutMeasurement: {height: number, width: number},
zoomScale: number,
},
};
/** /**
* Class used to detect when to show or hide a component based on scrolling * Class used to detect when to show or hide a component based on scrolling
*/ */
export default class AutoHideHandler { export default class AutoHideHandler {
lastOffset: number;
lastOffset: number; isHidden: boolean;
isHidden: boolean;
listeners: Array<Function>; listeners: Array<ListenerFunctionType>;
constructor(startHidden: boolean) { constructor(startHidden: boolean) {
this.listeners = []; this.listeners = [];
this.isHidden = startHidden; this.isHidden = startHidden;
}
/**
* Adds a listener to the hide event
*
* @param listener
*/
addListener(listener: (shouldHide: boolean) => void) {
this.listeners.push(listener);
}
/**
* Notifies every listener whether they should hide or show.
*
* @param shouldHide
*/
notifyListeners(shouldHide: boolean) {
this.listeners.forEach((func: ListenerFunctionType) => {
func(shouldHide);
});
}
/**
* Callback to be used on the onScroll animated component event.
*
* Detects if the current speed exceeds a threshold and notifies listeners to hide or show.
*
* The hide even is triggered when the user scrolls down, and the show event on scroll up.
* This does not take into account the speed when the y coordinate is negative, to prevent hiding on over scroll.
* (When scrolling up and hitting the top on ios for example)
*
* //TODO Known issue:
* When refreshing a list with the pull down gesture on ios,
* this can trigger the hide event as it scrolls down the list to show the refresh indicator.
* Android shows the refresh indicator on top of the list so this is not an issue.
*
* @param event The scroll event generated by the animated component onScroll prop
*/
onScroll(event: OnScrollType) {
const {nativeEvent} = event;
const speed =
nativeEvent.contentOffset.y < 0
? 0
: this.lastOffset - nativeEvent.contentOffset.y;
if (speed < -speedOffset && !this.isHidden) {
// Go down
this.notifyListeners(true);
this.isHidden = true;
} else if (speed > speedOffset && this.isHidden) {
// Go up
this.notifyListeners(false);
this.isHidden = false;
} }
this.lastOffset = nativeEvent.contentOffset.y;
/** }
* Adds a listener to the hide event
*
* @param listener
*/
addListener(listener: Function) {
this.listeners.push(listener);
}
/**
* Notifies every listener whether they should hide or show.
*
* @param shouldHide
*/
notifyListeners(shouldHide: boolean) {
for (let i = 0; i < this.listeners.length; i++) {
this.listeners[i](shouldHide);
}
}
/**
* Callback to be used on the onScroll animated component event.
*
* Detects if the current speed exceeds a threshold and notifies listeners to hide or show.
*
* The hide even is triggered when the user scrolls down, and the show event on scroll up.
* This does not take into account the speed when the y coordinate is negative, to prevent hiding on over scroll.
* (When scrolling up and hitting the top on ios for example)
*
* //TODO Known issue:
* When refreshing a list with the pull down gesture on ios,
* this can trigger the hide event as it scrolls down the list to show the refresh indicator.
* Android shows the refresh indicator on top of the list so this is not an issue.
*
* @param nativeEvent The scroll event generated by the animated component onScroll prop
*/
onScroll({nativeEvent}: Object) {
const speed = nativeEvent.contentOffset.y < 0 ? 0 : this.lastOffset - nativeEvent.contentOffset.y;
if (speed < -speedOffset && !this.isHidden) { // Go down
this.notifyListeners(true);
this.isHidden = true;
} else if (speed > speedOffset && this.isHidden) { // Go up
this.notifyListeners(false);
this.isHidden = false;
}
this.lastOffset = nativeEvent.contentOffset.y;
}
} }

View file

@ -1,9 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import {useTheme} from "react-native-paper"; import {useTheme} from 'react-native-paper';
import {createCollapsibleStack} from "react-navigation-collapsible"; import {createCollapsibleStack} from 'react-navigation-collapsible';
import StackNavigator, {StackNavigationOptions} from "@react-navigation/stack"; import StackNavigator, {StackNavigationOptions} from '@react-navigation/stack';
/** /**
* Creates a navigation stack with the collapsible library, allowing the header to collapse on scroll. * Creates a navigation stack with the collapsible library, allowing the header to collapse on scroll.
@ -22,32 +22,34 @@ import StackNavigator, {StackNavigationOptions} from "@react-navigation/stack";
* @returns {JSX.Element} * @returns {JSX.Element}
*/ */
export function createScreenCollapsibleStack( export function createScreenCollapsibleStack(
name: string, name: string,
Stack: StackNavigator, Stack: StackNavigator,
component: React.ComponentType<any>, // eslint-disable-next-line flowtype/no-weak-types
title: string, component: React.ComponentType<any>,
useNativeDriver?: boolean, title: string,
options?: StackNavigationOptions, useNativeDriver?: boolean,
headerColor?: string) { options?: StackNavigationOptions,
const {colors} = useTheme(); headerColor?: string,
const screenOptions = options != null ? options : {}; ): React.Node {
return createCollapsibleStack( const {colors} = useTheme();
<Stack.Screen const screenOptions = options != null ? options : {};
name={name} return createCollapsibleStack(
component={component} <Stack.Screen
options={{ name={name}
title: title, component={component}
headerStyle: { options={{
backgroundColor: headerColor!=null ? headerColor :colors.surface, title,
}, headerStyle: {
...screenOptions, backgroundColor: headerColor != null ? headerColor : colors.surface,
}} },
/>, ...screenOptions,
{ }}
collapsedColor: headerColor!=null ? headerColor :colors.surface, />,
useNativeDriver: useNativeDriver != null ? useNativeDriver : true, // native driver does not work with webview {
} collapsedColor: headerColor != null ? headerColor : colors.surface,
) useNativeDriver: useNativeDriver != null ? useNativeDriver : true, // native driver does not work with webview
},
);
} }
/** /**
@ -62,6 +64,12 @@ export function createScreenCollapsibleStack(
* @param title * @param title
* @returns {JSX.Element} * @returns {JSX.Element}
*/ */
export function getWebsiteStack(name: string, Stack: any, component: any, title: string) { export function getWebsiteStack(
return createScreenCollapsibleStack(name, Stack, component, title, false); name: string,
Stack: StackNavigator,
// eslint-disable-next-line flowtype/no-weak-types
component: React.ComponentType<any>,
title: string,
): React.Node {
return createScreenCollapsibleStack(name, Stack, component, title, false);
} }