From 4db4516296f6c217f7c821c5a1608846c0bd812e Mon Sep 17 00:00:00 2001
From: Arnaud Vergnet
Date: Tue, 4 Aug 2020 21:24:43 +0200
Subject: [PATCH] Improve override components to match linter
---
src/components/Overrides/CustomAgenda.js | 105 +--
src/components/Overrides/CustomHTML.js | 79 +-
.../Overrides/CustomHeaderButton.js | 46 +-
src/components/Overrides/CustomIntroSlider.js | 752 +++++++++---------
src/components/Overrides/CustomModal.js | 49 +-
src/components/Overrides/CustomSlider.js | 85 +-
6 files changed, 573 insertions(+), 543 deletions(-)
diff --git a/src/components/Overrides/CustomAgenda.js b/src/components/Overrides/CustomAgenda.js
index b490fc7..eaf4f20 100644
--- a/src/components/Overrides/CustomAgenda.js
+++ b/src/components/Overrides/CustomAgenda.js
@@ -1,60 +1,63 @@
-import * as React from 'react';
-import {View} from "react-native";
-import {withTheme} from 'react-native-paper';
-import {Agenda} from "react-native-calendars";
+// @flow
-type Props = {
- theme: Object,
-}
+import * as React from 'react';
+import {View} from 'react-native';
+import {withTheme} from 'react-native-paper';
+import {Agenda} from 'react-native-calendars';
+import type {CustomTheme} from '../../managers/ThemeManager';
+
+type PropsType = {
+ theme: CustomTheme,
+ onRef: (ref: Agenda) => void,
+};
/**
* Abstraction layer for Agenda component, using custom configuration
*/
-class CustomAgenda extends React.Component {
+class CustomAgenda extends React.Component {
+ getAgenda(): React.Node {
+ const {props} = this;
+ return (
+
+ );
+ }
- getAgenda() {
- return ;
- }
-
- render() {
- // Completely recreate the component on theme change to force theme reload
- if (this.props.theme.dark)
- return (
-
- {this.getAgenda()}
-
- );
- else
- return this.getAgenda();
- }
+ render(): React.Node {
+ const {props} = this;
+ // Completely recreate the component on theme change to force theme reload
+ if (props.theme.dark)
+ return {this.getAgenda()};
+ return this.getAgenda();
+ }
}
export default withTheme(CustomAgenda);
diff --git a/src/components/Overrides/CustomHTML.js b/src/components/Overrides/CustomHTML.js
index 4e28948..d3f2d93 100644
--- a/src/components/Overrides/CustomHTML.js
+++ b/src/components/Overrides/CustomHTML.js
@@ -1,47 +1,58 @@
+/* eslint-disable flowtype/require-parameter-type */
+// @flow
+
import * as React from 'react';
import {Text, withTheme} from 'react-native-paper';
-import HTML from "react-native-render-html";
-import {Linking} from "react-native";
+import HTML from 'react-native-render-html';
+import {Linking} from 'react-native';
+import type {CustomTheme} from '../../managers/ThemeManager';
-type Props = {
- theme: Object,
- html: string,
-}
+type PropsType = {
+ theme: CustomTheme,
+ html: string,
+};
/**
* Abstraction layer for Agenda component, using custom configuration
*/
-class CustomHTML extends React.Component {
+class CustomHTML extends React.Component {
+ openWebLink = (event: {...}, link: string) => {
+ Linking.openURL(link);
+ };
- openWebLink = (event, link) => {
- Linking.openURL(link).catch((err) => console.error('Error opening link', err));
- };
+ getBasicText = (
+ htmlAttribs,
+ children,
+ convertedCSSStyles,
+ passProps,
+ ): React.Node => {
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ return {children};
+ };
- getBasicText = (htmlAttribs, children, convertedCSSStyles, passProps) => {
- return {children};
- };
+ getListBullet = (): React.Node => {
+ return - ;
+ };
- getListBullet = (htmlAttribs, children, convertedCSSStyles, passProps) => {
- return (
- -
- );
- };
-
- render() {
- // Surround description with p to allow text styling if the description is not html
- return " + this.props.html + "
"}
- renderers={{
- p: this.getBasicText,
- li: this.getBasicText,
- }}
- listsPrefixesRenderers={{
- ul: this.getListBullet
- }}
- ignoredTags={['img']}
- ignoredStyles={['color', 'background-color']}
- onLinkPress={this.openWebLink}/>;
- }
+ render(): React.Node {
+ const {props} = this;
+ // Surround description with p to allow text styling if the description is not html
+ return (
+ ${props.html}`}
+ renderers={{
+ p: this.getBasicText,
+ li: this.getBasicText,
+ }}
+ listsPrefixesRenderers={{
+ ul: this.getListBullet,
+ }}
+ ignoredTags={['img']}
+ ignoredStyles={['color', 'background-color']}
+ onLinkPress={this.openWebLink}
+ />
+ );
+ }
}
export default withTheme(CustomHTML);
diff --git a/src/components/Overrides/CustomHeaderButton.js b/src/components/Overrides/CustomHeaderButton.js
index add0138..47c0c1f 100644
--- a/src/components/Overrides/CustomHeaderButton.js
+++ b/src/components/Overrides/CustomHeaderButton.js
@@ -1,27 +1,39 @@
// @flow
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 {withTheme} from "react-native-paper";
+import {withTheme} from 'react-native-paper';
+import type {CustomTheme} from '../../managers/ThemeManager';
-const MaterialHeaderButton = (props: Object) =>
+const MaterialHeaderButton = (props: {
+ theme: CustomTheme,
+ color: string,
+}): React.Node => {
+ const {color, theme} = props;
+ return (
+ // $FlowFixMe
;
-
-const MaterialHeaderButtons = (props: Object) => {
- return (
-
- );
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ {...props}
+ IconComponent={MaterialCommunityIcons}
+ iconSize={26}
+ color={color != null ? color : theme.colors.text}
+ />
+ );
};
-export default withTheme(MaterialHeaderButtons);
+const MaterialHeaderButtons = (props: {...}): React.Node => {
+ return (
+ // $FlowFixMe
+
+ );
+};
+
+export default MaterialHeaderButtons;
export {Item} from 'react-navigation-header-buttons';
diff --git a/src/components/Overrides/CustomIntroSlider.js b/src/components/Overrides/CustomIntroSlider.js
index 371fe12..131700b 100644
--- a/src/components/Overrides/CustomIntroSlider.js
+++ b/src/components/Overrides/CustomIntroSlider.js
@@ -1,411 +1,403 @@
// @flow
import * as React from 'react';
-import {Platform, StatusBar, StyleSheet, View} from "react-native";
-import type {MaterialCommunityIconsGlyphs} from "react-native-vector-icons/MaterialCommunityIcons";
-import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
+import {Platform, StatusBar, StyleSheet, View} from 'react-native';
+import type {MaterialCommunityIconsGlyphs} from 'react-native-vector-icons/MaterialCommunityIcons';
+import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import i18n from 'i18n-js';
-import AppIntroSlider from "react-native-app-intro-slider";
-import Update from "../../constants/Update";
-import ThemeManager from "../../managers/ThemeManager";
+import AppIntroSlider from 'react-native-app-intro-slider';
import LinearGradient from 'react-native-linear-gradient';
-import Mascot, {MASCOT_STYLE} from "../Mascot/Mascot";
-import * as Animatable from "react-native-animatable";
-import {Card} from "react-native-paper";
+import * as Animatable from 'react-native-animatable';
+import {Card} from 'react-native-paper';
+import Update from '../../constants/Update';
+import ThemeManager from '../../managers/ThemeManager';
+import Mascot, {MASCOT_STYLE} from '../Mascot/Mascot';
-type Props = {
- onDone: Function,
- isUpdate: boolean,
- isAprilFools: boolean,
+type PropsType = {
+ onDone: () => void,
+ isUpdate: boolean,
+ isAprilFools: boolean,
};
-type State = {
- currentSlide: number,
-}
-
-type Slide = {
- key: string,
- title: string,
- text: string,
- view: () => React.Node,
- mascotStyle: number,
- colors: [string, string]
+type StateType = {
+ currentSlide: number,
};
+type IntroSlideType = {
+ key: string,
+ title: string,
+ text: string,
+ view: () => React.Node,
+ mascotStyle: number,
+ colors: [string, string],
+};
+
+const styles = StyleSheet.create({
+ mainContent: {
+ paddingBottom: 100,
+ },
+ text: {
+ color: 'rgba(255, 255, 255, 0.8)',
+ backgroundColor: 'transparent',
+ textAlign: 'center',
+ paddingHorizontal: 16,
+ },
+ title: {
+ fontSize: 22,
+ color: 'white',
+ backgroundColor: 'transparent',
+ textAlign: 'center',
+ marginBottom: 16,
+ },
+ center: {
+ marginTop: 'auto',
+ marginBottom: 'auto',
+ marginRight: 'auto',
+ marginLeft: 'auto',
+ },
+});
+
/**
* Class used to create intro slides
*/
-export default class CustomIntroSlider extends React.Component {
+export default class CustomIntroSlider extends React.Component<
+ PropsType,
+ StateType,
+> {
+ sliderRef: {current: null | AppIntroSlider};
- state = {
- currentSlide: 0,
- }
+ introSlides: Array;
- sliderRef: { current: null | AppIntroSlider };
+ updateSlides: Array;
- introSlides: Array;
- updateSlides: Array;
- aprilFoolsSlides: Array;
- currentSlides: Array;
+ aprilFoolsSlides: Array;
- /**
- * Generates intro slides
- */
- constructor() {
- super();
- this.sliderRef = React.createRef();
- this.introSlides = [
- {
- key: '0', // Mascot
- title: i18n.t('intro.slideMain.title'),
- text: i18n.t('intro.slideMain.text'),
- view: this.getWelcomeView,
- mascotStyle: MASCOT_STYLE.NORMAL,
- colors: ['#be1522', '#57080e'],
- },
- {
- key: '1',
- title: i18n.t('intro.slidePlanex.title'),
- text: i18n.t('intro.slidePlanex.text'),
- view: () => this.getIconView("calendar-clock"),
- mascotStyle: MASCOT_STYLE.INTELLO,
- colors: ['#be1522', '#57080e'],
- },
- {
- key: '2',
- title: i18n.t('intro.slideEvents.title'),
- text: i18n.t('intro.slideEvents.text'),
- view: () => this.getIconView("calendar-star",),
- mascotStyle: MASCOT_STYLE.HAPPY,
- colors: ['#be1522', '#57080e'],
- },
- {
- key: '3',
- title: i18n.t('intro.slideServices.title'),
- text: i18n.t('intro.slideServices.text'),
- view: () => this.getIconView("view-dashboard-variant",),
- mascotStyle: MASCOT_STYLE.CUTE,
- colors: ['#be1522', '#57080e'],
- },
- {
- key: '4',
- title: i18n.t('intro.slideDone.title'),
- text: i18n.t('intro.slideDone.text'),
- view: () => this.getEndView(),
- mascotStyle: MASCOT_STYLE.COOL,
- colors: ['#9c165b', '#3e042b'],
- },
- ];
- this.updateSlides = [];
- for (let i = 0; i < Update.slidesNumber; i++) {
- this.updateSlides.push(
- {
- key: i.toString(),
- title: Update.getInstance().titleList[i],
- text: Update.getInstance().descriptionList[i],
- icon: Update.iconList[i],
- colors: Update.colorsList[i],
- },
- );
- }
+ currentSlides: Array;
- this.aprilFoolsSlides = [
- {
- key: '1',
- title: i18n.t('intro.aprilFoolsSlide.title'),
- text: i18n.t('intro.aprilFoolsSlide.text'),
- view: () => ,
- mascotStyle: MASCOT_STYLE.NORMAL,
- colors: ['#e01928', '#be1522'],
- },
- ];
- }
-
- /**
- * Render item to be used for the intro introSlides
- *
- * @param item The item to be displayed
- * @param dimensions Dimensions of the item
- */
- getIntroRenderItem = ({item, dimensions}: { item: Slide, dimensions: { width: number, height: number } }) => {
- const index = parseInt(item.key);
- return (
-
- {this.state.currentSlide === index
- ?
-
- {item.view()}
-
-
- {index !== 0 && index !== this.introSlides.length - 1
- ?
- : null}
-
-
-
-
- {item.title}
-
-
- {item.text}
-
-
-
-
- : null}
-
- );
- }
-
- getEndView = () => {
- return (
-
-
-
- );
- }
-
- getWelcomeView = () => {
- return (
-
-
-
- PABLO
-
-
-
-
-
- )
- }
-
- getIconView(icon: MaterialCommunityIconsGlyphs) {
- return (
-
-
-
-
-
- )
- }
-
- setStatusBarColor(color: string) {
- if (Platform.OS === 'android')
- StatusBar.setBackgroundColor(color, true);
- }
-
- onSlideChange = (index: number, lastIndex: number) => {
- this.setStatusBarColor(this.currentSlides[index].colors[0]);
- this.setState({currentSlide: index});
+ /**
+ * Generates intro slides
+ */
+ constructor() {
+ super();
+ this.state = {
+ currentSlide: 0,
};
-
- onSkip = () => {
- this.setStatusBarColor(this.currentSlides[this.currentSlides.length - 1].colors[0]);
- if (this.sliderRef.current != null)
- this.sliderRef.current.goToSlide(this.currentSlides.length - 1);
+ this.sliderRef = React.createRef();
+ this.introSlides = [
+ {
+ key: '0', // Mascot
+ title: i18n.t('intro.slideMain.title'),
+ text: i18n.t('intro.slideMain.text'),
+ view: this.getWelcomeView,
+ mascotStyle: MASCOT_STYLE.NORMAL,
+ colors: ['#be1522', '#57080e'],
+ },
+ {
+ key: '1',
+ title: i18n.t('intro.slidePlanex.title'),
+ text: i18n.t('intro.slidePlanex.text'),
+ view: (): React.Node => CustomIntroSlider.getIconView('calendar-clock'),
+ mascotStyle: MASCOT_STYLE.INTELLO,
+ colors: ['#be1522', '#57080e'],
+ },
+ {
+ key: '2',
+ title: i18n.t('intro.slideEvents.title'),
+ text: i18n.t('intro.slideEvents.text'),
+ view: (): React.Node => CustomIntroSlider.getIconView('calendar-star'),
+ mascotStyle: MASCOT_STYLE.HAPPY,
+ colors: ['#be1522', '#57080e'],
+ },
+ {
+ key: '3',
+ title: i18n.t('intro.slideServices.title'),
+ text: i18n.t('intro.slideServices.text'),
+ view: (): React.Node =>
+ CustomIntroSlider.getIconView('view-dashboard-variant'),
+ mascotStyle: MASCOT_STYLE.CUTE,
+ colors: ['#be1522', '#57080e'],
+ },
+ {
+ key: '4',
+ title: i18n.t('intro.slideDone.title'),
+ text: i18n.t('intro.slideDone.text'),
+ view: (): React.Node => this.getEndView(),
+ mascotStyle: MASCOT_STYLE.COOL,
+ colors: ['#9c165b', '#3e042b'],
+ },
+ ];
+ // $FlowFixMe
+ this.updateSlides = [];
+ for (let i = 0; i < Update.slidesNumber; i += 1) {
+ this.updateSlides.push({
+ key: i.toString(),
+ title: Update.getInstance().titleList[i],
+ text: Update.getInstance().descriptionList[i],
+ icon: Update.iconList[i],
+ colors: Update.colorsList[i],
+ });
}
- onDone = () => {
- this.setStatusBarColor(ThemeManager.getCurrentTheme().colors.surface);
- this.props.onDone();
- }
-
- renderNextButton = () => {
- return (
- ,
+ mascotStyle: MASCOT_STYLE.NORMAL,
+ colors: ['#e01928', '#be1522'],
+ },
+ ];
+ }
+ /**
+ * Render item to be used for the intro introSlides
+ *
+ * @param item The item to be displayed
+ * @param dimensions Dimensions of the item
+ */
+ getIntroRenderItem = ({
+ item,
+ dimensions,
+ }: {
+ item: IntroSlideType,
+ dimensions: {width: number, height: number},
+ }): React.Node => {
+ const {state} = this;
+ const index = parseInt(item.key, 10);
+ return (
+
+ {state.currentSlide === index ? (
+
+ {item.view()}
+
+ {index !== 0 && index !== this.introSlides.length - 1 ? (
+
+ ) : null}
+
-
-
- )
- }
-
- renderDoneButton = () => {
- return (
-
+
-
+
+
+ {item.title}
+
+
+ {item.text}
+
+
+
- )
- }
+
+ ) : null}
+
+ );
+ };
- render() {
- this.currentSlides = this.introSlides;
- if (this.props.isUpdate)
- this.currentSlides = this.updateSlides;
- else if (this.props.isAprilFools)
- this.currentSlides = this.aprilFoolsSlides;
- this.setStatusBarColor(this.currentSlides[0].colors[0]);
- return (
- {
+ return (
+
+
+
+ );
+ };
- renderItem={this.getIntroRenderItem}
- renderNextButton={this.renderNextButton}
- renderDoneButton={this.renderDoneButton}
+ getWelcomeView = (): React.Node => {
+ return (
+
+
+
+ PABLO
+
+
+
+
+
+ );
+ };
- onDone={this.onDone}
- onSlideChange={this.onSlideChange}
- onSkip={this.onSkip}
- />
- );
- }
+ static getIconView(icon: MaterialCommunityIconsGlyphs): React.Node {
+ return (
+
+
+
+
+
+ );
+ }
+ static setStatusBarColor(color: string) {
+ if (Platform.OS === 'android') StatusBar.setBackgroundColor(color, true);
+ }
+
+ onSlideChange = (index: number) => {
+ CustomIntroSlider.setStatusBarColor(this.currentSlides[index].colors[0]);
+ this.setState({currentSlide: index});
+ };
+
+ onSkip = () => {
+ CustomIntroSlider.setStatusBarColor(
+ this.currentSlides[this.currentSlides.length - 1].colors[0],
+ );
+ if (this.sliderRef.current != null)
+ this.sliderRef.current.goToSlide(this.currentSlides.length - 1);
+ };
+
+ onDone = () => {
+ const {props} = this;
+ CustomIntroSlider.setStatusBarColor(
+ ThemeManager.getCurrentTheme().colors.surface,
+ );
+ props.onDone();
+ };
+
+ getRenderNextButton = (): React.Node => {
+ return (
+
+
+
+ );
+ };
+
+ getRenderDoneButton = (): React.Node => {
+ return (
+
+
+
+ );
+ };
+
+ render(): React.Node {
+ const {props, state} = this;
+ this.currentSlides = this.introSlides;
+ if (props.isUpdate) this.currentSlides = this.updateSlides;
+ else if (props.isAprilFools) this.currentSlides = this.aprilFoolsSlides;
+ CustomIntroSlider.setStatusBarColor(this.currentSlides[0].colors[0]);
+ return (
+
+ );
+ }
}
-
-
-const styles = StyleSheet.create({
- mainContent: {
- paddingBottom: 100,
- },
- text: {
- color: 'rgba(255, 255, 255, 0.8)',
- backgroundColor: 'transparent',
- textAlign: 'center',
- paddingHorizontal: 16,
- },
- title: {
- fontSize: 22,
- color: 'white',
- backgroundColor: 'transparent',
- textAlign: 'center',
- marginBottom: 16,
- },
- center: {
- marginTop: 'auto',
- marginBottom: 'auto',
- marginRight: 'auto',
- marginLeft: 'auto',
- },
-});
diff --git a/src/components/Overrides/CustomModal.js b/src/components/Overrides/CustomModal.js
index 598acc4..b11868a 100644
--- a/src/components/Overrides/CustomModal.js
+++ b/src/components/Overrides/CustomModal.js
@@ -2,9 +2,10 @@
import * as React from 'react';
import {withTheme} from 'react-native-paper';
-import {Modalize} from "react-native-modalize";
-import {View} from "react-native-animatable";
-import CustomTabBar from "../Tabbar/CustomTabBar";
+import {Modalize} from 'react-native-modalize';
+import {View} from 'react-native-animatable';
+import CustomTabBar from '../Tabbar/CustomTabBar';
+import type {CustomTheme} from '../../managers/ThemeManager';
/**
* Abstraction layer for Modalize component, using custom configuration
@@ -12,25 +13,29 @@ import CustomTabBar from "../Tabbar/CustomTabBar";
* @param props Props to pass to the element. Must specify an onRef prop to get an Modalize ref.
* @return {*}
*/
-function CustomModal(props) {
- const {colors} = props.theme;
- return (
-
-
- {props.children}
-
-
-
- );
+function CustomModal(props: {
+ theme: CustomTheme,
+ onRef: (re: Modalize) => void,
+ children?: React.Node,
+}): React.Node {
+ const {theme, onRef, children} = props;
+ return (
+
+
+ {children}
+
+
+ );
}
-export default withTheme(CustomModal);
+CustomModal.defaultProps = {children: null};
+export default withTheme(CustomModal);
diff --git a/src/components/Overrides/CustomSlider.js b/src/components/Overrides/CustomSlider.js
index 122ea4a..419ca02 100644
--- a/src/components/Overrides/CustomSlider.js
+++ b/src/components/Overrides/CustomSlider.js
@@ -2,19 +2,19 @@
import * as React from 'react';
import {Text, withTheme} from 'react-native-paper';
-import {View} from "react-native-animatable";
-import type {CustomTheme} from "../../managers/ThemeManager";
-import Slider, {SliderProps} from "@react-native-community/slider";
+import {View} from 'react-native-animatable';
+import Slider, {SliderProps} from '@react-native-community/slider';
+import type {CustomTheme} from '../../managers/ThemeManager';
-type Props = {
- theme: CustomTheme,
- valueSuffix: string,
- ...SliderProps
-}
+type PropsType = {
+ theme: CustomTheme,
+ valueSuffix?: string,
+ ...SliderProps,
+};
-type State = {
- currentValue: number,
-}
+type StateType = {
+ currentValue: number,
+};
/**
* Abstraction layer for Modalize component, using custom configuration
@@ -22,37 +22,44 @@ type State = {
* @param props Props to pass to the element. Must specify an onRef prop to get an Modalize ref.
* @return {*}
*/
-class CustomSlider extends React.Component {
+class CustomSlider extends React.Component {
+ static defaultProps = {
+ valueSuffix: '',
+ };
- static defaultProps = {
- valueSuffix: "",
- }
+ constructor(props: PropsType) {
+ super(props);
+ this.state = {
+ currentValue: props.value,
+ };
+ }
- state = {
- currentValue: this.props.value,
- }
-
- onValueChange = (value: number) => {
- this.setState({currentValue: value});
- if (this.props.onValueChange != null)
- this.props.onValueChange(value);
- }
-
- render() {
- return (
-
-
- {this.state.currentValue}min
-
-
-
- );
- }
+ onValueChange = (value: number) => {
+ const {props} = this;
+ this.setState({currentValue: value});
+ if (props.onValueChange != null) props.onValueChange(value);
+ };
+ render(): React.Node {
+ const {props, state} = this;
+ return (
+
+
+ {state.currentValue}min
+
+
+
+ );
+ }
}
export default withTheme(CustomSlider);
-