Update custom tab bar to use TypeScript

This commit is contained in:
Arnaud Vergnet 2020-09-22 15:16:25 +02:00
parent e4adcd0057
commit 5261e85254
3 changed files with 63 additions and 77 deletions

View file

@ -17,8 +17,6 @@
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
*/
// @flow
import * as React from 'react';
import {Animated} from 'react-native';
import {withTheme} from 'react-native-paper';
@ -26,40 +24,40 @@ import {Collapsible} from 'react-navigation-collapsible';
import {StackNavigationProp} from '@react-navigation/stack';
import TabIcon from './TabIcon';
import TabHomeIcon from './TabHomeIcon';
import type {CustomThemeType} from '../../managers/ThemeManager';
type RouteType = {
name: string,
key: string,
params: {collapsible: Collapsible},
name: string;
key: string;
params: {collapsible: Collapsible};
state: {
index: number,
routes: Array<RouteType>,
},
index: number;
routes: Array<RouteType>;
};
};
type PropsType = {
state: {
index: number,
routes: Array<RouteType>,
},
index: number;
routes: Array<RouteType>;
};
descriptors: {
[key: string]: {
options: {
tabBarLabel: string,
title: string,
},
},
},
navigation: StackNavigationProp,
theme: CustomThemeType,
tabBarLabel: string;
title: string;
};
};
};
navigation: StackNavigationProp<any>;
theme: ReactNativePaper.Theme;
};
type StateType = {
// eslint-disable-next-line flowtype/no-weak-types
translateY: any,
translateY: any;
};
type validRoutes = 'proxiwash' | 'services' | 'planning' | 'planex';
const TAB_ICONS = {
proxiwash: 'tshirt-crew',
services: 'account-circle',
@ -70,8 +68,8 @@ const TAB_ICONS = {
class CustomTabBar extends React.Component<PropsType, StateType> {
static TAB_BAR_HEIGHT = 48;
constructor() {
super();
constructor(props: PropsType) {
super(props);
this.state = {
translateY: new Animated.Value(0),
};
@ -86,14 +84,10 @@ class CustomTabBar extends React.Component<PropsType, StateType> {
*/
onItemPress(route: RouteType, currentIndex: number, destIndex: number) {
const {navigation} = this.props;
const event = navigation.emit({
type: 'tabPress',
target: route.key,
canPreventDefault: true,
});
if (currentIndex !== destIndex && !event.defaultPrevented)
if (currentIndex !== destIndex) {
navigation.navigate(route.name);
}
}
/**
* Navigates to tetris screen on home button long press
@ -102,14 +96,10 @@ class CustomTabBar extends React.Component<PropsType, StateType> {
*/
onItemLongPress(route: RouteType) {
const {navigation} = this.props;
const event = navigation.emit({
type: 'tabLongPress',
target: route.key,
canPreventDefault: true,
});
if (route.name === 'home' && !event.defaultPrevented)
if (route.name === 'home') {
navigation.navigate('game-start');
}
}
/**
* Finds the active route and syncs the tab bar animation with the header bar
@ -126,11 +116,13 @@ class CustomTabBar extends React.Component<PropsType, StateType> {
* @param focused
* @returns {null}
*/
getTabBarIcon = (route: RouteType, focused: boolean): React.Node => {
let icon = TAB_ICONS[route.name];
getTabBarIcon = (route: RouteType, focused: boolean) => {
let icon = TAB_ICONS[route.name as validRoutes];
icon = focused ? icon : `${icon}-outline`;
if (route.name !== 'home') return icon;
return null;
if (route.name !== 'home') {
return icon;
}
return '';
};
/**
@ -141,14 +133,18 @@ class CustomTabBar extends React.Component<PropsType, StateType> {
* @param index The index of the current route
* @returns {*}
*/
getRenderIcon = (route: RouteType, index: number): React.Node => {
getRenderIcon = (route: RouteType, index: number) => {
const {props} = this;
const {state} = props;
const {options} = props.descriptors[route.key];
let label;
if (options.tabBarLabel != null) label = options.tabBarLabel;
else if (options.title != null) label = options.title;
else label = route.name;
if (options.tabBarLabel != null) {
label = options.tabBarLabel;
} else if (options.title != null) {
label = options.title;
} else {
label = route.name;
}
const onPress = () => {
this.onItemPress(route, state.index, index);
@ -186,7 +182,7 @@ class CustomTabBar extends React.Component<PropsType, StateType> {
);
};
getIcons(): React.Node {
getIcons() {
const {props} = this;
return props.state.routes.map(this.getRenderIcon);
}
@ -209,14 +205,12 @@ class CustomTabBar extends React.Component<PropsType, StateType> {
}
};
render(): React.Node {
render() {
const {props, state} = this;
props.navigation.addListener('state', this.onRouteChange);
const icons = this.getIcons();
return (
// $FlowFixMe
<Animated.View
useNativeDriver
style={{
flexDirection: 'row',
height: CustomTabBar.TAB_BAR_HEIGHT,

View file

@ -17,20 +17,18 @@
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
*/
// @flow
import * as React from 'react';
import {Image, View} from 'react-native';
import {FAB} from 'react-native-paper';
import * as Animatable from 'react-native-animatable';
import FOCUSED_ICON from '../../../assets/tab-icon.png';
import UNFOCUSED_ICON from '../../../assets/tab-icon-outline.png';
const FOCUSED_ICON = require('../../../assets/tab-icon.png');
const UNFOCUSED_ICON = require('../../../assets/tab-icon-outline.png');
type PropsType = {
focused: boolean,
onPress: () => void,
onLongPress: () => void,
tabBarHeight: number,
focused: boolean;
onPress: () => void;
onLongPress: () => void;
tabBarHeight: number;
};
const AnimatedFAB = Animatable.createAnimatableComponent(FAB);
@ -44,6 +42,7 @@ class TabHomeIcon extends React.Component<PropsType> {
Animatable.initializeRegistryWithDefinitions({
fabFocusIn: {
'0': {
// @ts-ignore
scale: 1,
translateY: 0,
},
@ -58,6 +57,7 @@ class TabHomeIcon extends React.Component<PropsType> {
},
fabFocusOut: {
'0': {
// @ts-ignore
scale: 1.1,
translateY: -6,
},
@ -74,13 +74,7 @@ class TabHomeIcon extends React.Component<PropsType> {
return nextProps.focused !== focused;
}
getIconRender = ({
size,
color,
}: {
size: number,
color: string,
}): React.Node => {
getIconRender = ({size, color}: {size: number; color: string}) => {
const {focused} = this.props;
return (
<Image
@ -94,7 +88,7 @@ class TabHomeIcon extends React.Component<PropsType> {
);
};
render(): React.Node {
render() {
const {props} = this;
return (
<View

View file

@ -17,25 +17,21 @@
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
*/
// @flow
import * as React from 'react';
import {View} from 'react-native';
import {TouchableRipple, withTheme} from 'react-native-paper';
import type {MaterialCommunityIconsGlyphs} from 'react-native-vector-icons/MaterialCommunityIcons';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import * as Animatable from 'react-native-animatable';
import type {CustomThemeType} from '../../managers/ThemeManager';
type PropsType = {
focused: boolean,
color: string,
label: string,
icon: MaterialCommunityIconsGlyphs,
onPress: () => void,
onLongPress: () => void,
theme: CustomThemeType,
extraData: null | boolean | number | string,
focused: boolean;
color: string;
label: string;
icon: string;
onPress: () => void;
onLongPress: () => void;
theme: ReactNativePaper.Theme;
extraData: null | boolean | number | string;
};
/**
@ -49,6 +45,7 @@ class TabIcon extends React.Component<PropsType> {
Animatable.initializeRegistryWithDefinitions({
focusIn: {
'0': {
// @ts-ignore
scale: 1,
translateY: 0,
},
@ -63,6 +60,7 @@ class TabIcon extends React.Component<PropsType> {
},
focusOut: {
'0': {
// @ts-ignore
scale: 1.2,
translateY: 6,
},
@ -88,7 +86,7 @@ class TabIcon extends React.Component<PropsType> {
);
}
render(): React.Node {
render() {
const {props} = this;
return (
<TouchableRipple
@ -99,7 +97,7 @@ class TabIcon extends React.Component<PropsType> {
style={{
flex: 1,
justifyContent: 'center',
borderRadius: 10
borderRadius: 10,
}}>
<View>
<Animatable.View