forked from vergnet/application-amicale
		
	Update Planex screens to use TypeScript
This commit is contained in:
		
							parent
							
								
									4d0df7a5b7
								
							
						
					
					
						commit
						742cb1802d
					
				
					 2 changed files with 77 additions and 62 deletions
				
			
		|  | @ -17,8 +17,6 @@ | ||||||
|  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
 |  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
 | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| // @flow
 |  | ||||||
| 
 |  | ||||||
| import * as React from 'react'; | import * as React from 'react'; | ||||||
| import {Platform} from 'react-native'; | import {Platform} from 'react-native'; | ||||||
| import i18n from 'i18n-js'; | import i18n from 'i18n-js'; | ||||||
|  | @ -32,31 +30,35 @@ import AsyncStorageManager from '../../managers/AsyncStorageManager'; | ||||||
| const LIST_ITEM_HEIGHT = 70; | const LIST_ITEM_HEIGHT = 70; | ||||||
| 
 | 
 | ||||||
| export type PlanexGroupType = { | export type PlanexGroupType = { | ||||||
|   name: string, |   name: string; | ||||||
|   id: number, |   id: number; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export type PlanexGroupCategoryType = { | export type PlanexGroupCategoryType = { | ||||||
|   name: string, |   name: string; | ||||||
|   id: number, |   id: number; | ||||||
|   content: Array<PlanexGroupType>, |   content: Array<PlanexGroupType>; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| type PropsType = { | type PropsType = { | ||||||
|   navigation: StackNavigationProp, |   navigation: StackNavigationProp<any>; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| type StateType = { | type StateType = { | ||||||
|   currentSearchString: string, |   currentSearchString: string; | ||||||
|   favoriteGroups: Array<PlanexGroupType>, |   favoriteGroups: Array<PlanexGroupType>; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| function sortName( | function sortName( | ||||||
|   a: PlanexGroupType | PlanexGroupCategoryType, |   a: PlanexGroupType | PlanexGroupCategoryType, | ||||||
|   b: PlanexGroupType | PlanexGroupCategoryType, |   b: PlanexGroupType | PlanexGroupCategoryType, | ||||||
| ): number { | ): number { | ||||||
|   if (a.name.toLowerCase() < b.name.toLowerCase()) return -1; |   if (a.name.toLowerCase() < b.name.toLowerCase()) { | ||||||
|   if (a.name.toLowerCase() > b.name.toLowerCase()) return 1; |     return -1; | ||||||
|  |   } | ||||||
|  |   if (a.name.toLowerCase() > b.name.toLowerCase()) { | ||||||
|  |     return 1; | ||||||
|  |   } | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -96,8 +98,9 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> { | ||||||
|    * |    * | ||||||
|    * @return {*} |    * @return {*} | ||||||
|    */ |    */ | ||||||
|   getSearchBar = (): React.Node => { |   getSearchBar = () => { | ||||||
|     return ( |     return ( | ||||||
|  |       // @ts-ignore
 | ||||||
|       <Searchbar |       <Searchbar | ||||||
|         placeholder={i18n.t('screens.proximo.search')} |         placeholder={i18n.t('screens.proximo.search')} | ||||||
|         onChangeText={this.onSearchStringChange} |         onChangeText={this.onSearchStringChange} | ||||||
|  | @ -111,7 +114,7 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> { | ||||||
|    * @param item The article to render |    * @param item The article to render | ||||||
|    * @return {*} |    * @return {*} | ||||||
|    */ |    */ | ||||||
|   getRenderItem = ({item}: {item: PlanexGroupCategoryType}): React.Node => { |   getRenderItem = ({item}: {item: PlanexGroupCategoryType}) => { | ||||||
|     const {currentSearchString, favoriteGroups} = this.state; |     const {currentSearchString, favoriteGroups} = this.state; | ||||||
|     if ( |     if ( | ||||||
|       this.shouldDisplayAccordion(item) || |       this.shouldDisplayAccordion(item) || | ||||||
|  | @ -138,8 +141,8 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> { | ||||||
|    * @return {*} |    * @return {*} | ||||||
|    * */ |    * */ | ||||||
|   createDataset = (fetchedData: { |   createDataset = (fetchedData: { | ||||||
|     [key: string]: PlanexGroupCategoryType, |     [key: string]: PlanexGroupCategoryType; | ||||||
|   }): Array<{title: string, data: Array<PlanexGroupCategoryType>}> => { |   }): Array<{title: string; data: Array<PlanexGroupCategoryType>}> => { | ||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         title: '', |         title: '', | ||||||
|  | @ -190,7 +193,9 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> { | ||||||
|     let isFav = false; |     let isFav = false; | ||||||
|     const {favoriteGroups} = this.state; |     const {favoriteGroups} = this.state; | ||||||
|     favoriteGroups.forEach((favGroup: PlanexGroupType) => { |     favoriteGroups.forEach((favGroup: PlanexGroupType) => { | ||||||
|       if (group.id === favGroup.id) isFav = true; |       if (group.id === favGroup.id) { | ||||||
|  |         isFav = true; | ||||||
|  |       } | ||||||
|     }); |     }); | ||||||
|     return isFav; |     return isFav; | ||||||
|   } |   } | ||||||
|  | @ -202,8 +207,11 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> { | ||||||
|    * @param group The group to add/remove to favorites |    * @param group The group to add/remove to favorites | ||||||
|    */ |    */ | ||||||
|   updateGroupFavorites(group: PlanexGroupType) { |   updateGroupFavorites(group: PlanexGroupType) { | ||||||
|     if (this.isGroupInFavorites(group)) this.removeGroupFromFavorites(group); |     if (this.isGroupInFavorites(group)) { | ||||||
|     else this.addGroupToFavorites(group); |       this.removeGroupFromFavorites(group); | ||||||
|  |     } else { | ||||||
|  |       this.addGroupToFavorites(group); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|  | @ -232,16 +240,13 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> { | ||||||
|    * @returns {[]} |    * @returns {[]} | ||||||
|    */ |    */ | ||||||
|   generateData(fetchedData: { |   generateData(fetchedData: { | ||||||
|     [key: string]: PlanexGroupCategoryType, |     [key: string]: PlanexGroupCategoryType; | ||||||
|   }): Array<PlanexGroupCategoryType> { |   }): Array<PlanexGroupCategoryType> { | ||||||
|     const {favoriteGroups} = this.state; |     const {favoriteGroups} = this.state; | ||||||
|     const data = []; |     const data: Array<PlanexGroupCategoryType> = []; | ||||||
|     // eslint-disable-next-line flowtype/no-weak-types
 |     Object.values(fetchedData).forEach((category: PlanexGroupCategoryType) => { | ||||||
|     (Object.values(fetchedData): Array<any>).forEach( |  | ||||||
|       (category: PlanexGroupCategoryType) => { |  | ||||||
|       data.push(category); |       data.push(category); | ||||||
|       }, |     }); | ||||||
|     ); |  | ||||||
|     data.sort(sortName); |     data.sort(sortName); | ||||||
|     data.unshift({ |     data.unshift({ | ||||||
|       name: i18n.t('screens.planex.favorites'), |       name: i18n.t('screens.planex.favorites'), | ||||||
|  | @ -258,7 +263,7 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> { | ||||||
|    */ |    */ | ||||||
|   removeGroupFromFavorites(group: PlanexGroupType) { |   removeGroupFromFavorites(group: PlanexGroupType) { | ||||||
|     this.setState((prevState: StateType): { |     this.setState((prevState: StateType): { | ||||||
|       favoriteGroups: Array<PlanexGroupType>, |       favoriteGroups: Array<PlanexGroupType>; | ||||||
|     } => { |     } => { | ||||||
|       const {favoriteGroups} = prevState; |       const {favoriteGroups} = prevState; | ||||||
|       for (let i = 0; i < favoriteGroups.length; i += 1) { |       for (let i = 0; i < favoriteGroups.length; i += 1) { | ||||||
|  | @ -282,7 +287,7 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> { | ||||||
|    */ |    */ | ||||||
|   addGroupToFavorites(group: PlanexGroupType) { |   addGroupToFavorites(group: PlanexGroupType) { | ||||||
|     this.setState((prevState: StateType): { |     this.setState((prevState: StateType): { | ||||||
|       favoriteGroups: Array<PlanexGroupType>, |       favoriteGroups: Array<PlanexGroupType>; | ||||||
|     } => { |     } => { | ||||||
|       const {favoriteGroups} = prevState; |       const {favoriteGroups} = prevState; | ||||||
|       favoriteGroups.push(group); |       favoriteGroups.push(group); | ||||||
|  | @ -295,7 +300,7 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> { | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   render(): React.Node { |   render() { | ||||||
|     const {props, state} = this; |     const {props, state} = this; | ||||||
|     return ( |     return ( | ||||||
|       <WebSectionList |       <WebSectionList | ||||||
|  | @ -22,11 +22,10 @@ | ||||||
| import * as React from 'react'; | import * as React from 'react'; | ||||||
| import {Title, withTheme} from 'react-native-paper'; | import {Title, withTheme} from 'react-native-paper'; | ||||||
| import i18n from 'i18n-js'; | import i18n from 'i18n-js'; | ||||||
| import {View} from 'react-native'; | import {NativeScrollEvent, NativeSyntheticEvent, 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 Autolink from 'react-native-autolink'; | import Autolink from 'react-native-autolink'; | ||||||
| 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'; | ||||||
|  | @ -40,16 +39,16 @@ import {MASCOT_STYLE} from '../../components/Mascot/Mascot'; | ||||||
| import MascotPopup from '../../components/Mascot/MascotPopup'; | import MascotPopup from '../../components/Mascot/MascotPopup'; | ||||||
| 
 | 
 | ||||||
| type PropsType = { | type PropsType = { | ||||||
|   navigation: StackNavigationProp, |   navigation: StackNavigationProp<any>; | ||||||
|   route: {params: {group: PlanexGroupType}}, |   route: {params: {group: PlanexGroupType}}; | ||||||
|   theme: CustomThemeType, |   theme: ReactNativePaper.Theme; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| type StateType = { | type StateType = { | ||||||
|   dialogVisible: boolean, |   dialogVisible: boolean; | ||||||
|   dialogTitle: string | React.Node, |   dialogTitle: string | React.ReactNode; | ||||||
|   dialogMessage: string, |   dialogMessage: string; | ||||||
|   currentGroup: PlanexGroupType, |   currentGroup: PlanexGroupType; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const PLANEX_URL = 'http://planex.insa-toulouse.fr/'; | const PLANEX_URL = 'http://planex.insa-toulouse.fr/'; | ||||||
|  | @ -154,14 +153,15 @@ class PlanexScreen extends React.Component<PropsType, StateType> { | ||||||
|     super(props); |     super(props); | ||||||
|     this.webScreenRef = React.createRef(); |     this.webScreenRef = React.createRef(); | ||||||
|     this.barRef = React.createRef(); |     this.barRef = React.createRef(); | ||||||
| 
 |     this.customInjectedJS = ''; | ||||||
|     let currentGroup = AsyncStorageManager.getString( |     let currentGroupString = AsyncStorageManager.getString( | ||||||
|       AsyncStorageManager.PREFERENCES.planexCurrentGroup.key, |       AsyncStorageManager.PREFERENCES.planexCurrentGroup.key, | ||||||
|     ); |     ); | ||||||
|     if (currentGroup === '') |     let currentGroup: PlanexGroupType; | ||||||
|       currentGroup = {name: 'SELECT GROUP', id: -1, isFav: false}; |     if (currentGroupString === '') { | ||||||
|     else { |       currentGroup = {name: 'SELECT GROUP', id: -1}; | ||||||
|       currentGroup = JSON.parse(currentGroup); |     } else { | ||||||
|  |       currentGroup = JSON.parse(currentGroupString); | ||||||
|       props.navigation.setOptions({title: currentGroup.name}); |       props.navigation.setOptions({title: currentGroup.name}); | ||||||
|     } |     } | ||||||
|     this.state = { |     this.state = { | ||||||
|  | @ -189,8 +189,9 @@ class PlanexScreen extends React.Component<PropsType, StateType> { | ||||||
|    */ |    */ | ||||||
|   shouldComponentUpdate(nextProps: PropsType): boolean { |   shouldComponentUpdate(nextProps: PropsType): boolean { | ||||||
|     const {props, state} = this; |     const {props, state} = this; | ||||||
|     if (nextProps.theme.dark !== props.theme.dark) |     if (nextProps.theme.dark !== props.theme.dark) { | ||||||
|       this.generateInjectedJS(state.currentGroup.id); |       this.generateInjectedJS(state.currentGroup.id); | ||||||
|  |     } | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -199,7 +200,7 @@ class PlanexScreen extends React.Component<PropsType, StateType> { | ||||||
|    * |    * | ||||||
|    * @returns {*} |    * @returns {*} | ||||||
|    */ |    */ | ||||||
|   getWebView(): React.Node { |   getWebView() { | ||||||
|     const {props, state} = this; |     const {props, state} = this; | ||||||
|     const showWebview = state.currentGroup.id !== -1; |     const showWebview = state.currentGroup.id !== -1; | ||||||
| 
 | 
 | ||||||
|  | @ -246,12 +247,16 @@ class PlanexScreen extends React.Component<PropsType, StateType> { | ||||||
|    * Or "setGroup" with the group id as data to set the selected group |    * Or "setGroup" with the group id as data to set the selected group | ||||||
|    * @param data Data to pass to the action |    * @param data Data to pass to the action | ||||||
|    */ |    */ | ||||||
|   sendMessage = (action: string, data: string) => { |   sendMessage = (action: string, data?: string) => { | ||||||
|     let command; |     let command; | ||||||
|     if (action === 'setGroup') command = `displayAde(${data})`; |     if (action === 'setGroup') { | ||||||
|     else command = `$('#calendar').fullCalendar('${action}', '${data}')`; |       command = `displayAde(${data})`; | ||||||
|     if (this.webScreenRef.current != null) |     } else { | ||||||
|       this.webScreenRef.current.injectJavaScript(`${command};true;`); // Injected javascript must end with true
 |       command = `$('#calendar').fullCalendar('${action}', '${data}')`; | ||||||
|  |     } | ||||||
|  |     if (this.webScreenRef.current != null) { | ||||||
|  |       this.webScreenRef.current.injectJavaScript(`${command};true;`); | ||||||
|  |     } // Injected javascript must end with true
 | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|  | @ -261,10 +266,10 @@ class PlanexScreen extends React.Component<PropsType, StateType> { | ||||||
|    */ |    */ | ||||||
|   onMessage = (event: {nativeEvent: {data: string}}) => { |   onMessage = (event: {nativeEvent: {data: string}}) => { | ||||||
|     const data: { |     const data: { | ||||||
|       start: string, |       start: string; | ||||||
|       end: string, |       end: string; | ||||||
|       title: string, |       title: string; | ||||||
|       color: string, |       color: string; | ||||||
|     } = JSON.parse(event.nativeEvent.data); |     } = JSON.parse(event.nativeEvent.data); | ||||||
|     const startDate = dateToString(new Date(data.start), true); |     const startDate = dateToString(new Date(data.start), true); | ||||||
|     const endDate = dateToString(new Date(data.end), true); |     const endDate = dateToString(new Date(data.end), true); | ||||||
|  | @ -272,8 +277,9 @@ class PlanexScreen extends React.Component<PropsType, StateType> { | ||||||
|     const endString = getTimeOnlyString(endDate); |     const endString = getTimeOnlyString(endDate); | ||||||
| 
 | 
 | ||||||
|     let msg = `${DateManager.getInstance().getTranslatedDate(startDate)}\n`; |     let msg = `${DateManager.getInstance().getTranslatedDate(startDate)}\n`; | ||||||
|     if (startString != null && endString != null) |     if (startString != null && endString != null) { | ||||||
|       msg += `${startString} - ${endString}`; |       msg += `${startString} - ${endString}`; | ||||||
|  |     } | ||||||
|     this.showDialog(data.title, msg); |     this.showDialog(data.title, msg); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  | @ -286,6 +292,7 @@ class PlanexScreen extends React.Component<PropsType, StateType> { | ||||||
|   showDialog = (title: string, message: string) => { |   showDialog = (title: string, message: string) => { | ||||||
|     this.setState({ |     this.setState({ | ||||||
|       dialogVisible: true, |       dialogVisible: true, | ||||||
|  |       // @ts-ignore
 | ||||||
|       dialogTitle: <Autolink text={title} component={Title} />, |       dialogTitle: <Autolink text={title} component={Title} />, | ||||||
|       dialogMessage: message, |       dialogMessage: message, | ||||||
|     }); |     }); | ||||||
|  | @ -305,8 +312,10 @@ class PlanexScreen extends React.Component<PropsType, StateType> { | ||||||
|    * |    * | ||||||
|    * @param event |    * @param event | ||||||
|    */ |    */ | ||||||
|   onScroll = (event: SyntheticEvent<EventTarget>) => { |   onScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => { | ||||||
|     if (this.barRef.current != null) this.barRef.current.onScroll(event); |     if (this.barRef.current != null) { | ||||||
|  |       this.barRef.current.onScroll(event); | ||||||
|  |     } | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|  | @ -354,13 +363,14 @@ class PlanexScreen extends React.Component<PropsType, StateType> { | ||||||
|       DateManager.isWeekend(new Date()) ? 'calendar.next()' : '' |       DateManager.isWeekend(new Date()) ? 'calendar.next()' : '' | ||||||
|     }${INJECT_STYLE}`;
 |     }${INJECT_STYLE}`;
 | ||||||
| 
 | 
 | ||||||
|     if (ThemeManager.getNightMode()) |     if (ThemeManager.getNightMode()) { | ||||||
|       this.customInjectedJS += `$('head').append('<style>${CUSTOM_CSS_DARK}</style>');`; |       this.customInjectedJS += `$('head').append('<style>${CUSTOM_CSS_DARK}</style>');`; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     this.customInjectedJS += 'removeAlpha();});true;'; // Prevents crash on ios
 |     this.customInjectedJS += 'removeAlpha();});true;'; // Prevents crash on ios
 | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   render(): React.Node { |   render() { | ||||||
|     const {props, state} = this; |     const {props, state} = this; | ||||||
|     return ( |     return ( | ||||||
|       <View style={{flex: 1}}> |       <View style={{flex: 1}}> | ||||||
		Loading…
	
		Reference in a new issue