forked from vergnet/application-amicale
		
	Update about screens to use TypeScript
This commit is contained in:
		
							parent
							
								
									172b7e8187
								
							
						
					
					
						commit
						f7e767748a
					
				
					 3 changed files with 100 additions and 88 deletions
				
			
		|  | @ -17,8 +17,6 @@ | |||
|  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| // @flow
 | ||||
| 
 | ||||
| import * as React from 'react'; | ||||
| import {List} from 'react-native-paper'; | ||||
| import {View} from 'react-native-animatable'; | ||||
|  | @ -26,8 +24,8 @@ import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatLis | |||
| import packageJson from '../../../package.json'; | ||||
| 
 | ||||
| type ListItemType = { | ||||
|   name: string, | ||||
|   version: string, | ||||
|   name: string; | ||||
|   version: string; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  | @ -37,9 +35,9 @@ type ListItemType = { | |||
|  * @return {Array<ListItemType>} | ||||
|  */ | ||||
| function generateListFromObject(object: { | ||||
|   [key: string]: string, | ||||
|   [key: string]: string; | ||||
| }): Array<ListItemType> { | ||||
|   const list = []; | ||||
|   const list: Array<ListItemType> = []; | ||||
|   const keys = Object.keys(object); | ||||
|   keys.forEach((key: string) => { | ||||
|     list.push({name: key, version: object[key]}); | ||||
|  | @ -56,13 +54,13 @@ export default class AboutDependenciesScreen extends React.Component<null> { | |||
|   data: Array<ListItemType>; | ||||
| 
 | ||||
|   constructor() { | ||||
|     super(); | ||||
|     super(null); | ||||
|     this.data = generateListFromObject(packageJson.dependencies); | ||||
|   } | ||||
| 
 | ||||
|   keyExtractor = (item: ListItemType): string => item.name; | ||||
| 
 | ||||
|   getRenderItem = ({item}: {item: ListItemType}): React.Node => ( | ||||
|   getRenderItem = ({item}: {item: ListItemType}) => ( | ||||
|     <List.Item | ||||
|       title={item.name} | ||||
|       description={item.version.replace('^', '').replace('~', '')} | ||||
|  | @ -71,15 +69,15 @@ export default class AboutDependenciesScreen extends React.Component<null> { | |||
|   ); | ||||
| 
 | ||||
|   getItemLayout = ( | ||||
|     data: ListItemType, | ||||
|     data: Array<ListItemType> | null | undefined, | ||||
|     index: number, | ||||
|   ): {length: number, offset: number, index: number} => ({ | ||||
|   ): {length: number; offset: number; index: number} => ({ | ||||
|     length: LIST_ITEM_HEIGHT, | ||||
|     offset: LIST_ITEM_HEIGHT * index, | ||||
|     index, | ||||
|   }); | ||||
| 
 | ||||
|   render(): React.Node { | ||||
|   render() { | ||||
|     return ( | ||||
|       <View> | ||||
|         <CollapsibleFlatList | ||||
|  | @ -17,37 +17,32 @@ | |||
|  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| // @flow
 | ||||
| 
 | ||||
| import * as React from 'react'; | ||||
| import {FlatList, Linking, Platform, Image, View} from 'react-native'; | ||||
| import i18n from 'i18n-js'; | ||||
| import {Avatar, Card, List, withTheme} from 'react-native-paper'; | ||||
| import {Avatar, Card, List} from 'react-native-paper'; | ||||
| import {StackNavigationProp} from '@react-navigation/stack'; | ||||
| import packageJson from '../../../package.json'; | ||||
| import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList'; | ||||
| import APP_LOGO from '../../../assets/android.icon.round.png'; | ||||
| import type { | ||||
|   CardTitleIconPropsType, | ||||
|   ListIconPropsType, | ||||
| } from '../../constants/PaperStyles'; | ||||
| import OptionsDialog from '../../components/Dialogs/OptionsDialog'; | ||||
| import type {OptionsDialogButtonType} from '../../components/Dialogs/OptionsDialog'; | ||||
| 
 | ||||
| const APP_LOGO = require('../../../assets/android.icon.round.png'); | ||||
| 
 | ||||
| type ListItemType = { | ||||
|   onPressCallback: () => void, | ||||
|   icon: string, | ||||
|   text: string, | ||||
|   showChevron: boolean, | ||||
|   onPressCallback: () => void; | ||||
|   icon: string; | ||||
|   text: string; | ||||
|   showChevron: boolean; | ||||
| }; | ||||
| 
 | ||||
| type MemberItemType = { | ||||
|   name: string, | ||||
|   message: string, | ||||
|   icon: string, | ||||
|   trollLink?: string, | ||||
|   linkedin?: string, | ||||
|   mail?: string, | ||||
|   name: string; | ||||
|   message: string; | ||||
|   icon: string; | ||||
|   trollLink?: string; | ||||
|   linkedin?: string; | ||||
|   mail?: string; | ||||
| }; | ||||
| 
 | ||||
| const links = { | ||||
|  | @ -64,14 +59,14 @@ const links = { | |||
| }; | ||||
| 
 | ||||
| type PropsType = { | ||||
|   navigation: StackNavigationProp, | ||||
|   navigation: StackNavigationProp<any>; | ||||
| }; | ||||
| 
 | ||||
| type StateType = { | ||||
|   dialogVisible: boolean, | ||||
|   dialogTitle: string, | ||||
|   dialogMessage: string, | ||||
|   dialogButtons: Array<OptionsDialogButtonType>, | ||||
|   dialogVisible: boolean; | ||||
|   dialogTitle: string; | ||||
|   dialogMessage: string; | ||||
|   dialogButtons: Array<OptionsDialogButtonType>; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  | @ -86,7 +81,6 @@ function openWebLink(link: string) { | |||
|  * Class defining an about screen. This screen shows the user information about the app and it's author. | ||||
|  */ | ||||
| class AboutScreen extends React.Component<PropsType, StateType> { | ||||
| 
 | ||||
|   /** | ||||
|    * Object containing data relative to major contributors | ||||
|    */ | ||||
|  | @ -109,7 +103,8 @@ class AboutScreen extends React.Component<PropsType, StateType> { | |||
|       message: i18n.t('screens.about.user.yohan'), | ||||
|       icon: 'xml', | ||||
|       linkedin: 'https://www.linkedin.com/in/yohan-simard', | ||||
|       mail: 'mailto:ysimard@etud.insa-toulouse.fr?' + | ||||
|       mail: | ||||
|         'mailto:ysimard@etud.insa-toulouse.fr?' + | ||||
|         'subject=' + | ||||
|         'Application Amicale INSA Toulouse' + | ||||
|         '&body=' + | ||||
|  | @ -333,7 +328,7 @@ class AboutScreen extends React.Component<PropsType, StateType> { | |||
|    * @param user The member to show information for | ||||
|    */ | ||||
|   onContributorListItemPress(user: MemberItemType) { | ||||
|     const dialogBtn = [ | ||||
|     const dialogBtn: Array<OptionsDialogButtonType> = [ | ||||
|       { | ||||
|         title: 'OK', | ||||
|         onPress: this.onDialogDismiss, | ||||
|  | @ -379,15 +374,14 @@ class AboutScreen extends React.Component<PropsType, StateType> { | |||
|    * | ||||
|    * @return {*} | ||||
|    */ | ||||
|   getAppCard(): React.Node { | ||||
|   getAppCard() { | ||||
|     return ( | ||||
|       <Card style={{marginBottom: 10}}> | ||||
|         <Card.Title | ||||
|           title="Campus" | ||||
|           subtitle={packageJson.version} | ||||
|           left={(iconProps: CardTitleIconPropsType): React.Node => ( | ||||
|           left={(iconProps) => ( | ||||
|             <Image | ||||
|               size={iconProps.size} | ||||
|               source={APP_LOGO} | ||||
|               style={{width: iconProps.size, height: iconProps.size}} | ||||
|             /> | ||||
|  | @ -409,12 +403,12 @@ class AboutScreen extends React.Component<PropsType, StateType> { | |||
|    * | ||||
|    * @return {*} | ||||
|    */ | ||||
|   getTeamCard(): React.Node { | ||||
|   getTeamCard() { | ||||
|     return ( | ||||
|       <Card style={{marginBottom: 10}}> | ||||
|         <Card.Title | ||||
|           title={i18n.t('screens.about.team')} | ||||
|           left={(iconProps: CardTitleIconPropsType): React.Node => ( | ||||
|           left={(iconProps) => ( | ||||
|             <Avatar.Icon size={iconProps.size} icon="account-multiple" /> | ||||
|           )} | ||||
|         /> | ||||
|  | @ -434,12 +428,12 @@ class AboutScreen extends React.Component<PropsType, StateType> { | |||
|    * | ||||
|    * @return {*} | ||||
|    */ | ||||
|   getThanksCard(): React.Node { | ||||
|   getThanksCard() { | ||||
|     return ( | ||||
|       <Card style={{marginBottom: 10}}> | ||||
|         <Card.Title | ||||
|           title={i18n.t('screens.about.thanks')} | ||||
|           left={(iconProps: CardTitleIconPropsType): React.Node => ( | ||||
|           left={(iconProps) => ( | ||||
|             <Avatar.Icon size={iconProps.size} icon="hand-heart" /> | ||||
|           )} | ||||
|         /> | ||||
|  | @ -459,12 +453,12 @@ class AboutScreen extends React.Component<PropsType, StateType> { | |||
|    * | ||||
|    * @return {*} | ||||
|    */ | ||||
|   getTechnoCard(): React.Node { | ||||
|   getTechnoCard() { | ||||
|     return ( | ||||
|       <Card style={{marginBottom: 10}}> | ||||
|         <Card.Title | ||||
|           title={i18n.t('screens.about.technologies')} | ||||
|           left={(iconProps: CardTitleIconPropsType): React.Node => ( | ||||
|           left={(iconProps) => ( | ||||
|             <Avatar.Icon size={iconProps.size} icon="wrench" /> | ||||
|           )} | ||||
|         /> | ||||
|  | @ -485,7 +479,13 @@ class AboutScreen extends React.Component<PropsType, StateType> { | |||
|    * @param props | ||||
|    * @return {*} | ||||
|    */ | ||||
|   static getChevronIcon(props: ListIconPropsType): React.Node { | ||||
|   static getChevronIcon(props: { | ||||
|     color: string; | ||||
|     style?: { | ||||
|       marginRight: number; | ||||
|       marginVertical?: number; | ||||
|     }; | ||||
|   }) { | ||||
|     return ( | ||||
|       <List.Icon color={props.color} style={props.style} icon="chevron-right" /> | ||||
|     ); | ||||
|  | @ -498,7 +498,16 @@ class AboutScreen extends React.Component<PropsType, StateType> { | |||
|    * @param props | ||||
|    * @return {*} | ||||
|    */ | ||||
|   static getItemIcon(item: ListItemType, props: ListIconPropsType): React.Node { | ||||
|   static getItemIcon( | ||||
|     item: ListItemType, | ||||
|     props: { | ||||
|       color: string; | ||||
|       style?: { | ||||
|         marginRight: number; | ||||
|         marginVertical?: number; | ||||
|       }; | ||||
|     }, | ||||
|   ) { | ||||
|     return ( | ||||
|       <List.Icon color={props.color} style={props.style} icon={item.icon} /> | ||||
|     ); | ||||
|  | @ -509,9 +518,14 @@ class AboutScreen extends React.Component<PropsType, StateType> { | |||
|    * | ||||
|    * @returns {*} | ||||
|    */ | ||||
|   getCardItem = ({item}: {item: ListItemType}): React.Node => { | ||||
|     const getItemIcon = (props: ListIconPropsType): React.Node => | ||||
|       AboutScreen.getItemIcon(item, props); | ||||
|   getCardItem = ({item}: {item: ListItemType}) => { | ||||
|     const getItemIcon = (props: { | ||||
|       color: string; | ||||
|       style?: { | ||||
|         marginRight: number; | ||||
|         marginVertical?: number; | ||||
|       }; | ||||
|     }) => AboutScreen.getItemIcon(item, props); | ||||
|     if (item.showChevron) { | ||||
|       return ( | ||||
|         <List.Item | ||||
|  | @ -537,7 +551,7 @@ class AboutScreen extends React.Component<PropsType, StateType> { | |||
|    * @param item The item to show | ||||
|    * @return {*} | ||||
|    */ | ||||
|   getMainCard = ({item}: {item: {id: string}}): React.Node => { | ||||
|   getMainCard = ({item}: {item: {id: string}}) => { | ||||
|     switch (item.id) { | ||||
|       case 'app': | ||||
|         return this.getAppCard(); | ||||
|  | @ -564,7 +578,7 @@ class AboutScreen extends React.Component<PropsType, StateType> { | |||
|    */ | ||||
|   keyExtractor = (item: ListItemType): string => item.icon; | ||||
| 
 | ||||
|   render(): React.Node { | ||||
|   render() { | ||||
|     const {state} = this; | ||||
|     return ( | ||||
|       <View | ||||
|  | @ -588,4 +602,4 @@ class AboutScreen extends React.Component<PropsType, StateType> { | |||
|   } | ||||
| } | ||||
| 
 | ||||
| export default withTheme(AboutScreen); | ||||
| export default AboutScreen; | ||||
|  | @ -17,8 +17,6 @@ | |||
|  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| // @flow
 | ||||
| 
 | ||||
| import * as React from 'react'; | ||||
| import {View} from 'react-native'; | ||||
| import { | ||||
|  | @ -32,22 +30,21 @@ import { | |||
| 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 PreferenceItemType = { | ||||
|   key: string, | ||||
|   default: string, | ||||
|   current: string, | ||||
|   key: string; | ||||
|   default: string; | ||||
|   current: string; | ||||
| }; | ||||
| 
 | ||||
| type PropsType = { | ||||
|   theme: CustomThemeType, | ||||
|   theme: ReactNativePaper.Theme; | ||||
| }; | ||||
| 
 | ||||
| type StateType = { | ||||
|   modalCurrentDisplayItem: PreferenceItemType, | ||||
|   currentPreferences: Array<PreferenceItemType>, | ||||
|   modalCurrentDisplayItem: PreferenceItemType | null; | ||||
|   currentPreferences: Array<PreferenceItemType>; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  | @ -55,7 +52,7 @@ type StateType = { | |||
|  * This screen allows the user to get and modify information on the app/device. | ||||
|  */ | ||||
| class DebugScreen extends React.Component<PropsType, StateType> { | ||||
|   modalRef: Modalize; | ||||
|   modalRef: Modalize | null; | ||||
| 
 | ||||
|   modalInputValue: string; | ||||
| 
 | ||||
|  | @ -66,16 +63,16 @@ class DebugScreen extends React.Component<PropsType, StateType> { | |||
|    */ | ||||
|   constructor(props: PropsType) { | ||||
|     super(props); | ||||
|     this.modalRef = null; | ||||
|     this.modalInputValue = ''; | ||||
|     const currentPreferences: Array<PreferenceItemType> = []; | ||||
|     // eslint-disable-next-line flowtype/no-weak-types
 | ||||
|     Object.values(AsyncStorageManager.PREFERENCES).forEach((object: any) => { | ||||
|       const newObject: PreferenceItemType = {...object}; | ||||
|       newObject.current = AsyncStorageManager.getString(newObject.key); | ||||
|       currentPreferences.push(newObject); | ||||
|     }); | ||||
|     this.state = { | ||||
|       modalCurrentDisplayItem: {}, | ||||
|       modalCurrentDisplayItem: null, | ||||
|       currentPreferences, | ||||
|     }; | ||||
|   } | ||||
|  | @ -85,21 +82,27 @@ class DebugScreen extends React.Component<PropsType, StateType> { | |||
|    * | ||||
|    * @return {*} | ||||
|    */ | ||||
|   getModalContent(): React.Node { | ||||
|   getModalContent() { | ||||
|     const {props, state} = this; | ||||
|     let key = ''; | ||||
|     let defaultValue = ''; | ||||
|     let current = ''; | ||||
|     if (state.modalCurrentDisplayItem) { | ||||
|       key = state.modalCurrentDisplayItem.key; | ||||
|       defaultValue = state.modalCurrentDisplayItem.default; | ||||
|       defaultValue = state.modalCurrentDisplayItem.default; | ||||
|       current = state.modalCurrentDisplayItem.current; | ||||
|     } | ||||
| 
 | ||||
|     return ( | ||||
|       <View | ||||
|         style={{ | ||||
|           flex: 1, | ||||
|           padding: 20, | ||||
|         }}> | ||||
|         <Title>{state.modalCurrentDisplayItem.key}</Title> | ||||
|         <Subheading> | ||||
|           Default: {state.modalCurrentDisplayItem.default} | ||||
|         </Subheading> | ||||
|         <Subheading> | ||||
|           Current: {state.modalCurrentDisplayItem.current} | ||||
|         </Subheading> | ||||
|         <Title>{key}</Title> | ||||
|         <Subheading>Default: {defaultValue}</Subheading> | ||||
|         <Subheading>Current: {current}</Subheading> | ||||
|         <TextInput | ||||
|           label="New Value" | ||||
|           onChangeText={(text: string) => { | ||||
|  | @ -116,10 +119,7 @@ class DebugScreen extends React.Component<PropsType, StateType> { | |||
|             dark | ||||
|             color={props.theme.colors.success} | ||||
|             onPress={() => { | ||||
|               this.saveNewPrefs( | ||||
|                 state.modalCurrentDisplayItem.key, | ||||
|                 this.modalInputValue, | ||||
|               ); | ||||
|               this.saveNewPrefs(key, this.modalInputValue); | ||||
|             }}> | ||||
|             Save new value | ||||
|           </Button> | ||||
|  | @ -128,10 +128,7 @@ class DebugScreen extends React.Component<PropsType, StateType> { | |||
|             dark | ||||
|             color={props.theme.colors.danger} | ||||
|             onPress={() => { | ||||
|               this.saveNewPrefs( | ||||
|                 state.modalCurrentDisplayItem.key, | ||||
|                 state.modalCurrentDisplayItem.default, | ||||
|               ); | ||||
|               this.saveNewPrefs(key, defaultValue); | ||||
|             }}> | ||||
|             Reset to default | ||||
|           </Button> | ||||
|  | @ -140,7 +137,7 @@ class DebugScreen extends React.Component<PropsType, StateType> { | |||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   getRenderItem = ({item}: {item: PreferenceItemType}): React.Node => { | ||||
|   getRenderItem = ({item}: {item: PreferenceItemType}) => { | ||||
|     return ( | ||||
|       <List.Item | ||||
|         title={item.key} | ||||
|  | @ -170,7 +167,9 @@ class DebugScreen extends React.Component<PropsType, StateType> { | |||
|     this.setState({ | ||||
|       modalCurrentDisplayItem: item, | ||||
|     }); | ||||
|     if (this.modalRef) this.modalRef.open(); | ||||
|     if (this.modalRef) { | ||||
|       this.modalRef.open(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -199,24 +198,25 @@ class DebugScreen extends React.Component<PropsType, StateType> { | |||
|    */ | ||||
|   saveNewPrefs(key: string, value: string) { | ||||
|     this.setState((prevState: StateType): { | ||||
|       currentPreferences: Array<PreferenceItemType>, | ||||
|       currentPreferences: Array<PreferenceItemType>; | ||||
|     } => { | ||||
|       const currentPreferences = [...prevState.currentPreferences]; | ||||
|       currentPreferences[this.findIndexOfKey(key)].current = value; | ||||
|       return {currentPreferences}; | ||||
|     }); | ||||
|     AsyncStorageManager.set(key, value); | ||||
|     this.modalRef.close(); | ||||
|     if (this.modalRef) { | ||||
|       this.modalRef.close(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   render(): React.Node { | ||||
|   render() { | ||||
|     const {state} = this; | ||||
|     return ( | ||||
|       <View> | ||||
|         <CustomModal onRef={this.onModalRef}> | ||||
|           {this.getModalContent()} | ||||
|         </CustomModal> | ||||
|         {/* $FlowFixMe */} | ||||
|         <CollapsibleFlatList | ||||
|           data={state.currentPreferences} | ||||
|           extraData={state.currentPreferences} | ||||
		Loading…
	
		Reference in a new issue