Improve about components to match linter

This commit is contained in:
Arnaud Vergnet 2020-08-05 00:37:51 +02:00
parent 3e4f2f4ac1
commit 483970c9a8
3 changed files with 601 additions and 532 deletions

View file

@ -1,73 +1,75 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import packageJson from '../../../package';
import {List} from 'react-native-paper'; import {List} from 'react-native-paper';
import {StackNavigationProp} from "@react-navigation/stack"; import {View} from 'react-native-animatable';
import CollapsibleFlatList from "../../components/Collapsible/CollapsibleFlatList"; import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList';
import {View} from "react-native-animatable"; import packageJson from '../../../package.json';
type listItem = { type ListItemType = {
name: string, name: string,
version: string version: string,
}; };
/** /**
* Generates the dependencies list from the raw json * Generates the dependencies list from the raw json
* *
* @param object The raw json * @param object The raw json
* @return {Array<listItem>} * @return {Array<ListItemType>}
*/ */
function generateListFromObject(object: { [key: string]: string }): Array<listItem> { function generateListFromObject(object: {
let list = []; [key: string]: string,
let keys = Object.keys(object); }): Array<ListItemType> {
let values = Object.values(object); const list = [];
for (let i = 0; i < keys.length; i++) { const keys = Object.keys(object);
list.push({name: keys[i], version: values[i]}); keys.forEach((key: string) => {
} list.push({name: key, version: object[key]});
//$FlowFixMe });
return list; return list;
} }
type Props = {
navigation: StackNavigationProp,
}
const LIST_ITEM_HEIGHT = 64; const LIST_ITEM_HEIGHT = 64;
/** /**
* Class defining a screen showing the list of libraries used by the app, taken from package.json * Class defining a screen showing the list of libraries used by the app, taken from package.json
*/ */
export default class AboutDependenciesScreen extends React.Component<Props> { export default class AboutDependenciesScreen extends React.Component<null> {
data: Array<ListItemType>;
data: Array<listItem>;
constructor() { constructor() {
super(); super();
this.data = generateListFromObject(packageJson.dependencies); this.data = generateListFromObject(packageJson.dependencies);
} }
keyExtractor = (item: listItem) => item.name; keyExtractor = (item: ListItemType): string => item.name;
renderItem = ({item}: { item: listItem }) => getRenderItem = ({item}: {item: ListItemType}): React.Node => (
<List.Item <List.Item
title={item.name} title={item.name}
description={item.version.replace('^', '').replace('~', '')} description={item.version.replace('^', '').replace('~', '')}
style={{height: LIST_ITEM_HEIGHT}} style={{height: LIST_ITEM_HEIGHT}}
/>; />
);
itemLayout = (data: any, index: number) => ({length: LIST_ITEM_HEIGHT, offset: LIST_ITEM_HEIGHT * index, index}); getItemLayout = (
data: ListItemType,
index: number,
): {length: number, offset: number, index: number} => ({
length: LIST_ITEM_HEIGHT,
offset: LIST_ITEM_HEIGHT * index,
index,
});
render() { render(): React.Node {
return ( return (
<View> <View>
<CollapsibleFlatList <CollapsibleFlatList
data={this.data} data={this.data}
keyExtractor={this.keyExtractor} keyExtractor={this.keyExtractor}
renderItem={this.renderItem} renderItem={this.getRenderItem}
// Performance props, see https://reactnative.dev/docs/optimizing-flatlist-configuration // Performance props, see https://reactnative.dev/docs/optimizing-flatlist-configuration
removeClippedSubviews={true} removeClippedSubviews
getItemLayout={this.itemLayout} getItemLayout={this.getItemLayout}
/> />
</View> </View>
); );

View file

@ -1,43 +1,50 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import {FlatList, Linking, Platform, View} from 'react-native'; import {FlatList, Linking, Platform} from 'react-native';
import i18n from "i18n-js"; import i18n from 'i18n-js';
import {Avatar, Card, List, Title, withTheme} from 'react-native-paper'; import {Avatar, Card, List, Title, withTheme} from 'react-native-paper';
import packageJson from "../../../package.json"; import {StackNavigationProp} from '@react-navigation/stack';
import {StackNavigationProp} from "@react-navigation/stack"; import packageJson from '../../../package.json';
import CollapsibleFlatList from "../../components/Collapsible/CollapsibleFlatList"; import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList';
import APP_LOGO from '../../../assets/android.icon.png';
type ListItem = { type ListItemType = {
onPressCallback: () => void, onPressCallback: () => void,
icon: string, icon: string,
text: string, text: string,
showChevron: boolean showChevron: boolean,
}; };
const links = { const links = {
appstore: 'https://apps.apple.com/us/app/campus-amicale-insat/id1477722148', appstore: 'https://apps.apple.com/us/app/campus-amicale-insat/id1477722148',
playstore: 'https://play.google.com/store/apps/details?id=fr.amicaleinsat.application', playstore:
git: 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/src/branch/master/README.md', 'https://play.google.com/store/apps/details?id=fr.amicaleinsat.application',
changelog: 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/src/branch/master/Changelog.md', git:
license: 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/src/branch/master/LICENSE', 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/src/branch/master/README.md',
authorMail: "mailto:vergnet@etud.insa-toulouse.fr?" + changelog:
"subject=" + 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/src/branch/master/Changelog.md',
"Application Amicale INSA Toulouse" + license:
"&body=" + 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/src/branch/master/LICENSE',
"Coucou !\n\n", authorMail:
'mailto:vergnet@etud.insa-toulouse.fr?' +
'subject=' +
'Application Amicale INSA Toulouse' +
'&body=' +
'Coucou !\n\n',
authorLinkedin: 'https://www.linkedin.com/in/arnaud-vergnet-434ba5179/', authorLinkedin: 'https://www.linkedin.com/in/arnaud-vergnet-434ba5179/',
yohanMail: "mailto:ysimard@etud.insa-toulouse.fr?" + yohanMail:
"subject=" + 'mailto:ysimard@etud.insa-toulouse.fr?' +
"Application Amicale INSA Toulouse" + 'subject=' +
"&body=" + 'Application Amicale INSA Toulouse' +
"Coucou !\n\n", '&body=' +
'Coucou !\n\n',
yohanLinkedin: 'https://www.linkedin.com/in/yohan-simard', yohanLinkedin: 'https://www.linkedin.com/in/yohan-simard',
react: 'https://facebook.github.io/react-native/', react: 'https://facebook.github.io/react-native/',
meme: "https://www.youtube.com/watch?v=dQw4w9WgXcQ" meme: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
}; };
type Props = { type PropsType = {
navigation: StackNavigationProp, navigation: StackNavigationProp,
}; };
@ -45,113 +52,147 @@ type Props = {
* Opens a link in the device's browser * Opens a link in the device's browser
* @param link The link to open * @param link The link to open
*/ */
function openWebLink(link) { function openWebLink(link: string) {
Linking.openURL(link).catch((err) => console.error('Error opening link', err)); Linking.openURL(link);
} }
/** /**
* Class defining an about screen. This screen shows the user information about the app and it's author. * Class defining an about screen. This screen shows the user information about the app and it's author.
*/ */
class AboutScreen extends React.Component<Props> { class AboutScreen extends React.Component<PropsType> {
/** /**
* Data to be displayed in the app card * Data to be displayed in the app card
*/ */
appData = [ appData = [
{ {
onPressCallback: () => openWebLink(Platform.OS === "ios" ? links.appstore : links.playstore), onPressCallback: () => {
icon: Platform.OS === "ios" ? 'apple' : 'google-play', openWebLink(Platform.OS === 'ios' ? links.appstore : links.playstore);
text: Platform.OS === "ios" ? i18n.t('screens.about.appstore') : i18n.t('screens.about.playstore'), },
showChevron: true icon: Platform.OS === 'ios' ? 'apple' : 'google-play',
text:
Platform.OS === 'ios'
? i18n.t('screens.about.appstore')
: i18n.t('screens.about.playstore'),
showChevron: true,
}, },
{ {
onPressCallback: () => this.props.navigation.navigate("feedback"), onPressCallback: () => {
const {navigation} = this.props;
navigation.navigate('feedback');
},
icon: 'bug', icon: 'bug',
text: i18n.t("screens.feedback.homeButtonTitle"), text: i18n.t('screens.feedback.homeButtonTitle'),
showChevron: true showChevron: true,
}, },
{ {
onPressCallback: () => openWebLink(links.git), onPressCallback: () => {
openWebLink(links.git);
},
icon: 'git', icon: 'git',
text: 'Git', text: 'Git',
showChevron: true showChevron: true,
}, },
{ {
onPressCallback: () => openWebLink(links.changelog), onPressCallback: () => {
openWebLink(links.changelog);
},
icon: 'refresh', icon: 'refresh',
text: i18n.t('screens.about.changelog'), text: i18n.t('screens.about.changelog'),
showChevron: true showChevron: true,
}, },
{ {
onPressCallback: () => openWebLink(links.license), onPressCallback: () => {
openWebLink(links.license);
},
icon: 'file-document', icon: 'file-document',
text: i18n.t('screens.about.license'), text: i18n.t('screens.about.license'),
showChevron: true showChevron: true,
}, },
]; ];
/** /**
* Data to be displayed in the author card * Data to be displayed in the author card
*/ */
authorData = [ authorData = [
{ {
onPressCallback: () => openWebLink(links.meme), onPressCallback: () => {
openWebLink(links.meme);
},
icon: 'account-circle', icon: 'account-circle',
text: 'Arnaud VERGNET', text: 'Arnaud VERGNET',
showChevron: false showChevron: false,
}, },
{ {
onPressCallback: () => openWebLink(links.authorMail), onPressCallback: () => {
openWebLink(links.authorMail);
},
icon: 'email', icon: 'email',
text: i18n.t('screens.about.authorMail'), text: i18n.t('screens.about.authorMail'),
showChevron: true showChevron: true,
}, },
{ {
onPressCallback: () => openWebLink(links.authorLinkedin), onPressCallback: () => {
openWebLink(links.authorLinkedin);
},
icon: 'linkedin', icon: 'linkedin',
text: 'Linkedin', text: 'Linkedin',
showChevron: true showChevron: true,
}, },
]; ];
/** /**
* Data to be displayed in the additional developer card * Data to be displayed in the additional developer card
*/ */
additionalDevData = [ additionalDevData = [
{ {
onPressCallback: () => console.log('Meme this'), onPressCallback: () => {
console.log('Meme this');
},
icon: 'account', icon: 'account',
text: 'Yohan SIMARD', text: 'Yohan SIMARD',
showChevron: false showChevron: false,
}, },
{ {
onPressCallback: () => openWebLink(links.yohanMail), onPressCallback: () => {
openWebLink(links.yohanMail);
},
icon: 'email', icon: 'email',
text: i18n.t('screens.about.authorMail'), text: i18n.t('screens.about.authorMail'),
showChevron: true showChevron: true,
}, },
{ {
onPressCallback: () => openWebLink(links.yohanLinkedin), onPressCallback: () => {
openWebLink(links.yohanLinkedin);
},
icon: 'linkedin', icon: 'linkedin',
text: 'Linkedin', text: 'Linkedin',
showChevron: true showChevron: true,
}, },
]; ];
/** /**
* Data to be displayed in the technologies card * Data to be displayed in the technologies card
*/ */
technoData = [ technoData = [
{ {
onPressCallback: () => openWebLink(links.react), onPressCallback: () => {
openWebLink(links.react);
},
icon: 'react', icon: 'react',
text: i18n.t('screens.about.reactNative'), text: i18n.t('screens.about.reactNative'),
showChevron: true showChevron: true,
}, },
{ {
onPressCallback: () => this.props.navigation.navigate('dependencies'), onPressCallback: () => {
const {navigation} = this.props;
navigation.navigate('dependencies');
},
icon: 'developer-board', icon: 'developer-board',
text: i18n.t('screens.about.libs'), text: i18n.t('screens.about.libs'),
showChevron: true showChevron: true,
}, },
]; ];
/** /**
* Order of information cards * Order of information cards
*/ */
@ -167,44 +208,25 @@ class AboutScreen extends React.Component<Props> {
}, },
]; ];
/**
* Gets the app icon
*
* @param props
* @return {*}
*/
getAppIcon(props) {
return (
<Avatar.Image
{...props}
source={require('../../../assets/android.icon.png')}
style={{backgroundColor: 'transparent'}}
/>
);
}
/**
* Extracts a key from the given item
*
* @param item The item to extract the key from
* @return {string} The extracted key
*/
keyExtractor(item: ListItem): string {
return item.icon;
}
/** /**
* Gets the app card showing information and links about the app. * Gets the app card showing information and links about the app.
* *
* @return {*} * @return {*}
*/ */
getAppCard() { getAppCard(): React.Node {
return ( return (
<Card style={{marginBottom: 10}}> <Card style={{marginBottom: 10}}>
<Card.Title <Card.Title
title={"Campus"} title="Campus"
subtitle={packageJson.version} subtitle={packageJson.version}
left={this.getAppIcon}/> left={({size}: {size: number}): React.Node => (
<Avatar.Image
size={size}
source={APP_LOGO}
style={{backgroundColor: 'transparent'}}
/>
)}
/>
<Card.Content> <Card.Content>
<FlatList <FlatList
data={this.appData} data={this.appData}
@ -221,25 +243,28 @@ class AboutScreen extends React.Component<Props> {
* *
* @return {*} * @return {*}
*/ */
getTeamCard() { getTeamCard(): React.Node {
return ( return (
<Card style={{marginBottom: 10}}> <Card style={{marginBottom: 10}}>
<Card.Title <Card.Title
title={i18n.t('screens.about.team')} title={i18n.t('screens.about.team')}
left={(props) => <Avatar.Icon {...props} icon={'account-multiple'}/>}/> left={({size, color}: {size: number, color: string}): React.Node => (
<Avatar.Icon size={size} color={color} icon="account-multiple" />
)}
/>
<Card.Content> <Card.Content>
<Title>{i18n.t('screens.about.author')}</Title> <Title>{i18n.t('screens.about.author')}</Title>
<FlatList <FlatList
data={this.authorData} data={this.authorData}
keyExtractor={this.keyExtractor} keyExtractor={this.keyExtractor}
listKey={"1"} listKey="1"
renderItem={this.getCardItem} renderItem={this.getCardItem}
/> />
<Title>{i18n.t('screens.about.additionalDev')}</Title> <Title>{i18n.t('screens.about.additionalDev')}</Title>
<FlatList <FlatList
data={this.additionalDevData} data={this.additionalDevData}
keyExtractor={this.keyExtractor} keyExtractor={this.keyExtractor}
listKey={"2"} listKey="2"
renderItem={this.getCardItem} renderItem={this.getCardItem}
/> />
</Card.Content> </Card.Content>
@ -252,7 +277,7 @@ class AboutScreen extends React.Component<Props> {
* *
* @return {*} * @return {*}
*/ */
getTechnoCard() { getTechnoCard(): React.Node {
return ( return (
<Card style={{marginBottom: 10}}> <Card style={{marginBottom: 10}}>
<Card.Content> <Card.Content>
@ -273,10 +298,14 @@ class AboutScreen extends React.Component<Props> {
* @param props * @param props
* @return {*} * @return {*}
*/ */
getChevronIcon(props) { static getChevronIcon({
return ( size,
<List.Icon {...props} icon={'chevron-right'}/> color,
); }: {
size: number,
color: string,
}): React.Node {
return <List.Icon size={size} color={color} icon="chevron-right" />;
} }
/** /**
@ -286,10 +315,11 @@ class AboutScreen extends React.Component<Props> {
* @param props * @param props
* @return {*} * @return {*}
*/ */
getItemIcon(item: ListItem, props) { static getItemIcon(
return ( item: ListItemType,
<List.Icon {...props} icon={item.icon}/> {size, color}: {size: number, color: string},
); ): React.Node {
return <List.Icon size={size} color={color} icon={item.icon} />;
} }
/** /**
@ -297,18 +327,19 @@ class AboutScreen extends React.Component<Props> {
* *
* @returns {*} * @returns {*}
*/ */
getCardItem = ({item}: { item: ListItem }) => { getCardItem = ({item}: {item: ListItemType}): React.Node => {
const getItemIcon = this.getItemIcon.bind(this, item); const getItemIcon = (props: {size: number, color: string}): React.Node =>
AboutScreen.getItemIcon(item, props);
if (item.showChevron) { if (item.showChevron) {
return ( return (
<List.Item <List.Item
title={item.text} title={item.text}
left={getItemIcon} left={getItemIcon}
right={this.getChevronIcon} right={AboutScreen.getChevronIcon}
onPress={item.onPressCallback} onPress={item.onPressCallback}
/> />
); );
} else { }
return ( return (
<List.Item <List.Item
title={item.text} title={item.text}
@ -316,7 +347,6 @@ class AboutScreen extends React.Component<Props> {
onPress={item.onPressCallback} onPress={item.onPressCallback}
/> />
); );
}
}; };
/** /**
@ -325,7 +355,7 @@ class AboutScreen extends React.Component<Props> {
* @param item The item to show * @param item The item to show
* @return {*} * @return {*}
*/ */
getMainCard = ({item}: { item: { id: string } }) => { getMainCard = ({item}: {item: {id: string}}): React.Node => {
switch (item.id) { switch (item.id) {
case 'app': case 'app':
return this.getAppCard(); return this.getAppCard();
@ -333,11 +363,20 @@ class AboutScreen extends React.Component<Props> {
return this.getTeamCard(); return this.getTeamCard();
case 'techno': case 'techno':
return this.getTechnoCard(); return this.getTechnoCard();
default:
return null;
} }
return <View/>;
}; };
render() { /**
* Extracts a key from the given item
*
* @param item The item to extract the key from
* @return {string} The extracted key
*/
keyExtractor = (item: ListItemType): string => item.icon;
render(): React.Node {
return ( return (
<CollapsibleFlatList <CollapsibleFlatList
style={{padding: 5}} style={{padding: 5}}

View file

@ -1,38 +1,43 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import {View} from "react-native"; import {View} from 'react-native';
import AsyncStorageManager from "../../managers/AsyncStorageManager"; import {
import CustomModal from "../../components/Overrides/CustomModal"; Button,
import {Button, List, Subheading, TextInput, Title, withTheme} from 'react-native-paper'; List,
import {StackNavigationProp} from "@react-navigation/stack"; Subheading,
import {Modalize} from "react-native-modalize"; TextInput,
import type {CustomTheme} from "../../managers/ThemeManager"; Title,
import CollapsibleFlatList from "../../components/Collapsible/CollapsibleFlatList"; withTheme,
} from 'react-native-paper';
import {Modalize} from 'react-native-modalize';
import CustomModal from '../../components/Overrides/CustomModal';
import AsyncStorageManager from '../../managers/AsyncStorageManager';
import type {CustomThemeType} from '../../managers/ThemeManager';
import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList';
type PreferenceItem = { type PreferenceItemType = {
key: string, key: string,
default: string, default: string,
current: string, current: string,
}
type Props = {
navigation: StackNavigationProp,
theme: CustomTheme
}; };
type State = { type PropsType = {
modalCurrentDisplayItem: PreferenceItem, theme: CustomThemeType,
currentPreferences: Array<PreferenceItem>, };
}
type StateType = {
modalCurrentDisplayItem: PreferenceItemType,
currentPreferences: Array<PreferenceItemType>,
};
/** /**
* Class defining the Debug screen. * Class defining the Debug screen.
* This screen allows the user to get and modify information on the app/device. * This screen allows the user to get and modify information on the app/device.
*/ */
class DebugScreen extends React.Component<Props, State> { class DebugScreen extends React.Component<PropsType, StateType> {
modalRef: Modalize; modalRef: Modalize;
modalInputValue: string; modalInputValue: string;
/** /**
@ -40,87 +45,126 @@ class DebugScreen extends React.Component<Props, State> {
* *
* @param props * @param props
*/ */
constructor(props) { constructor(props: PropsType) {
super(props); super(props);
this.modalInputValue = ""; this.modalInputValue = '';
let currentPreferences : Array<PreferenceItem> = []; const currentPreferences: Array<PreferenceItemType> = [];
Object.values(AsyncStorageManager.PREFERENCES).map((object: any) => { // eslint-disable-next-line flowtype/no-weak-types
let newObject: PreferenceItem = {...object}; Object.values(AsyncStorageManager.PREFERENCES).forEach((object: any) => {
const newObject: PreferenceItemType = {...object};
newObject.current = AsyncStorageManager.getString(newObject.key); newObject.current = AsyncStorageManager.getString(newObject.key);
currentPreferences.push(newObject); currentPreferences.push(newObject);
}); });
this.state = { this.state = {
modalCurrentDisplayItem: {}, modalCurrentDisplayItem: {},
currentPreferences: currentPreferences currentPreferences,
}; };
} }
/**
* Shows the edit modal
*
* @param item
*/
showEditModal(item: PreferenceItem) {
this.setState({
modalCurrentDisplayItem: item
});
if (this.modalRef) {
this.modalRef.open();
}
}
/** /**
* Gets the edit modal content * Gets the edit modal content
* *
* @return {*} * @return {*}
*/ */
getModalContent() { getModalContent(): React.Node {
const {props, state} = this;
return ( return (
<View style={{ <View
style={{
flex: 1, flex: 1,
padding: 20 padding: 20,
}}> }}>
<Title>{this.state.modalCurrentDisplayItem.key}</Title> <Title>{state.modalCurrentDisplayItem.key}</Title>
<Subheading>Default: {this.state.modalCurrentDisplayItem.default}</Subheading> <Subheading>
<Subheading>Current: {this.state.modalCurrentDisplayItem.current}</Subheading> Default: {state.modalCurrentDisplayItem.default}
</Subheading>
<Subheading>
Current: {state.modalCurrentDisplayItem.current}
</Subheading>
<TextInput <TextInput
label='New Value' label="New Value"
onChangeText={(text) => this.modalInputValue = text} onChangeText={(text: string) => {
this.modalInputValue = text;
}}
/> />
<View style={{ <View
style={{
flexDirection: 'row', flexDirection: 'row',
marginTop: 10, marginTop: 10,
}}> }}>
<Button <Button
mode="contained" mode="contained"
dark={true} dark
color={this.props.theme.colors.success} color={props.theme.colors.success}
onPress={() => this.saveNewPrefs(this.state.modalCurrentDisplayItem.key, this.modalInputValue)}> onPress={() => {
this.saveNewPrefs(
state.modalCurrentDisplayItem.key,
this.modalInputValue,
);
}}>
Save new value Save new value
</Button> </Button>
<Button <Button
mode="contained" mode="contained"
dark={true} dark
color={this.props.theme.colors.danger} color={props.theme.colors.danger}
onPress={() => this.saveNewPrefs(this.state.modalCurrentDisplayItem.key, this.state.modalCurrentDisplayItem.default)}> onPress={() => {
this.saveNewPrefs(
state.modalCurrentDisplayItem.key,
state.modalCurrentDisplayItem.default,
);
}}>
Reset to default Reset to default
</Button> </Button>
</View> </View>
</View> </View>
); );
} }
getRenderItem = ({item}: {item: PreferenceItemType}): React.Node => {
return (
<List.Item
title={item.key}
description="Click to edit"
onPress={() => {
this.showEditModal(item);
}}
/>
);
};
/**
* Callback used when receiving the modal ref
*
* @param ref
*/
onModalRef = (ref: Modalize) => {
this.modalRef = ref;
};
/**
* Shows the edit modal
*
* @param item
*/
showEditModal(item: PreferenceItemType) {
this.setState({
modalCurrentDisplayItem: item,
});
if (this.modalRef) this.modalRef.open();
}
/** /**
* Finds the index of the given key in the preferences array * Finds the index of the given key in the preferences array
* *
* @param key THe key to find the index of * @param key THe key to find the index of
* @returns {number} * @returns {number}
*/ */
findIndexOfKey(key: string) { findIndexOfKey(key: string): number {
const {currentPreferences} = this.state;
let index = -1; let index = -1;
for (let i = 0; i < this.state.currentPreferences.length; i++) { for (let i = 0; i < currentPreferences.length; i += 1) {
if (this.state.currentPreferences[i].key === key) { if (currentPreferences[i].key === key) {
index = i; index = i;
break; break;
} }
@ -135,8 +179,10 @@ class DebugScreen extends React.Component<Props, State> {
* @param value The pref value * @param value The pref value
*/ */
saveNewPrefs(key: string, value: string) { saveNewPrefs(key: string, value: string) {
this.setState((prevState) => { this.setState((prevState: StateType): {
let currentPreferences = [...prevState.currentPreferences]; currentPreferences: Array<PreferenceItemType>,
} => {
const currentPreferences = [...prevState.currentPreferences];
currentPreferences[this.findIndexOfKey(key)].current = value; currentPreferences[this.findIndexOfKey(key)].current = value;
return {currentPreferences}; return {currentPreferences};
}); });
@ -144,36 +190,18 @@ class DebugScreen extends React.Component<Props, State> {
this.modalRef.close(); this.modalRef.close();
} }
/** render(): React.Node {
* Callback used when receiving the modal ref const {state} = this;
*
* @param ref
*/
onModalRef = (ref: Modalize) => {
this.modalRef = ref;
}
renderItem = ({item}: {item: PreferenceItem}) => {
return (
<List.Item
title={item.key}
description={'Click to edit'}
onPress={() => this.showEditModal(item)}
/>
);
};
render() {
return ( return (
<View> <View>
<CustomModal onRef={this.onModalRef}> <CustomModal onRef={this.onModalRef}>
{this.getModalContent()} {this.getModalContent()}
</CustomModal> </CustomModal>
{/*$FlowFixMe*/} {/* $FlowFixMe */}
<CollapsibleFlatList <CollapsibleFlatList
data={this.state.currentPreferences} data={state.currentPreferences}
extraData={this.state.currentPreferences} extraData={state.currentPreferences}
renderItem={this.renderItem} renderItem={this.getRenderItem}
/> />
</View> </View>
); );