forked from vergnet/application-amicale
		
	Added tabbed webview for available rooms
This commit is contained in:
		
							parent
							
								
									8b132ccc91
								
							
						
					
					
						commit
						1da41c1fd1
					
				
					 8 changed files with 163 additions and 46 deletions
				
			
		|  | @ -2,7 +2,7 @@ | |||
| 
 | ||||
| import * as React from 'react'; | ||||
| import {Linking, Platform, View} from 'react-native'; | ||||
| import {Spinner, Footer, Right, Left, Body} from 'native-base'; | ||||
| import {Spinner, Footer, Right, Left, Body, Tab, TabHeading, Text, Tabs} from 'native-base'; | ||||
| import WebView from "react-native-webview"; | ||||
| import Touchable from "react-native-platform-touchable"; | ||||
| import CustomMaterialIcon from "../components/CustomMaterialIcon"; | ||||
|  | @ -11,8 +11,12 @@ import BaseContainer from "../components/BaseContainer"; | |||
| 
 | ||||
| type Props = { | ||||
|     navigation: Object, | ||||
|     url: string, | ||||
|     customInjectedJS: string, | ||||
|     data: Array<{ | ||||
|         url: string, | ||||
|         icon: string, | ||||
|         name: string, | ||||
|         customJS: string | ||||
|     }>, | ||||
|     headerTitle: string, | ||||
|     hasHeaderBackButton: boolean, | ||||
|     hasSideMenu: boolean, | ||||
|  | @ -25,16 +29,15 @@ type Props = { | |||
| export default class WebViewScreen extends React.Component<Props> { | ||||
| 
 | ||||
|     static defaultProps = { | ||||
|         customInjectedJS: '', | ||||
|         hasBackButton: false, | ||||
|         hasSideMenu: true, | ||||
|         hasFooter: true, | ||||
|     }; | ||||
| 
 | ||||
|     webview: WebView; | ||||
|     webviewArray: Array<WebView> = []; | ||||
| 
 | ||||
|     openWebLink() { | ||||
|         Linking.openURL(this.props.url).catch((err) => console.error('Error opening link', err)); | ||||
|     openWebLink(url: string) { | ||||
|         Linking.openURL(url).catch((err) => console.error('Error opening link', err)); | ||||
|     } | ||||
| 
 | ||||
|     getHeaderButton(clickAction: Function, icon: string) { | ||||
|  | @ -58,15 +61,73 @@ export default class WebViewScreen extends React.Component<Props> { | |||
|     }; | ||||
| 
 | ||||
|     refreshWebview() { | ||||
|         this.webview.reload(); | ||||
|         for (let view of this.webviewArray) { | ||||
|             view.reload(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     goBackWebview() { | ||||
|         this.webview.goBack(); | ||||
|         for (let view of this.webviewArray) { | ||||
|             view.goBack(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     goForwardWebview() { | ||||
|         this.webview.goForward(); | ||||
|         for (let view of this.webviewArray) { | ||||
|             view.goForward(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     getWebview(obj: Object) { | ||||
|         return ( | ||||
|             <WebView | ||||
|                 ref={ref => (this.webviewArray.push(ref))} | ||||
|                 source={{uri: obj['url']}} | ||||
|                 style={{ | ||||
|                     width: '100%', | ||||
|                     height: '100%', | ||||
|                 }} | ||||
|                 startInLoadingState={true} | ||||
|                 injectedJavaScript={obj['customJS']} | ||||
|                 javaScriptEnabled={true} | ||||
|                 renderLoading={() => | ||||
|                     <View style={{ | ||||
|                         backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor, | ||||
|                         position: 'absolute', | ||||
|                         top: 0, | ||||
|                         right: 0, | ||||
|                         width: '100%', | ||||
|                         height: '100%', | ||||
|                         flex: 1, | ||||
|                         alignItems: 'center', | ||||
|                         justifyContent: 'center' | ||||
|                     }}> | ||||
|                         <Spinner/> | ||||
|                     </View> | ||||
|                 } | ||||
|             /> | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     getTabbedWebview() { | ||||
|         let tabbedView = []; | ||||
|         for (let i = 0; i < this.props.data.length; i++) { | ||||
|             tabbedView.push( | ||||
|                 <Tab heading={ | ||||
|                     <TabHeading> | ||||
|                         <CustomMaterialIcon | ||||
|                             icon={this.props.data[i]['icon']} | ||||
|                             color={ThemeManager.getCurrentThemeVariables().tabIconColor} | ||||
|                             fontSize={20} | ||||
|                         /> | ||||
|                         <Text>{this.props.data[i]['name']}</Text> | ||||
|                     </TabHeading>} | ||||
|                      key={this.props.data[i]['url']} | ||||
|                      style={{backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor}}> | ||||
|                     {this.getWebview(this.props.data[i])} | ||||
|                 </Tab>); | ||||
|         } | ||||
|         return tabbedView; | ||||
|     } | ||||
| 
 | ||||
|     render() { | ||||
|  | @ -78,38 +139,22 @@ export default class WebViewScreen extends React.Component<Props> { | |||
|                 headerRightButton={this.getRefreshButton()} | ||||
|                 hasBackButton={this.props.hasHeaderBackButton} | ||||
|                 hasSideMenu={this.props.hasSideMenu}> | ||||
|                 <WebView | ||||
|                     ref={ref => (this.webview = ref)} | ||||
|                     source={{uri: this.props.url}} | ||||
|                     style={{ | ||||
|                         width: '100%', | ||||
|                         height: '100%', | ||||
|                     }} | ||||
|                     startInLoadingState={true} | ||||
|                     injectedJavaScript={this.props.customInjectedJS} | ||||
|                     javaScriptEnabled={true} | ||||
|                     renderLoading={() => | ||||
|                         <View style={{ | ||||
|                             backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor, | ||||
|                             position: 'absolute', | ||||
|                             top: 0, | ||||
|                             right: 0, | ||||
|                             width: '100%', | ||||
|                             height: '100%', | ||||
|                             flex: 1, | ||||
|                             alignItems: 'center', | ||||
|                             justifyContent: 'center' | ||||
|                         }}> | ||||
|                             <Spinner/> | ||||
|                         </View> | ||||
|                     } | ||||
|                 /> | ||||
|                 {this.props.hasFooter ? | ||||
|                 {this.props.data.length === 1 ? | ||||
|                     this.getWebview(this.props.data[0]) : | ||||
|                     <Tabs | ||||
|                         tabContainerStyle={{ | ||||
|                             elevation: 0, // Fix for android shadow
 | ||||
|                         }} | ||||
|                         locked={true} | ||||
|                     > | ||||
|                         {this.getTabbedWebview()} | ||||
|                     </Tabs>} | ||||
|                 {this.props.hasFooter && this.props.data.length === 1 ? | ||||
|                     <Footer> | ||||
|                         <Left style={{ | ||||
|                             paddingLeft: 6, | ||||
|                         }}> | ||||
|                             {this.getHeaderButton(() => this.openWebLink(), 'open-in-new')} | ||||
|                             {this.getHeaderButton(() => this.openWebLink(this.props.data[0]['url']), 'open-in-new')} | ||||
|                         </Left> | ||||
|                         <Body/> | ||||
|                         <Right style={{ | ||||
|  |  | |||
|  | @ -22,7 +22,14 @@ export default class AmicaleScreen extends React.Component<Props> { | |||
|         return ( | ||||
|             <WebViewScreen | ||||
|                 navigation={nav} | ||||
|                 url={URL} | ||||
|                 data={[ | ||||
|                     { | ||||
|                         url: URL, | ||||
|                         icon: '', | ||||
|                         name: '', | ||||
|                         customJS: '' | ||||
|                     }, | ||||
|                 ]} | ||||
|                 headerTitle={'Amicale'} | ||||
|                 hasHeaderBackButton={true} | ||||
|                 hasSideMenu={false}/> | ||||
|  |  | |||
|  | @ -9,7 +9,11 @@ type Props = { | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| const URL = 'http://planex.insa-toulouse.fr/salles.php'; | ||||
| const ROOM_URL = 'http://planex.insa-toulouse.fr/salles.php'; | ||||
| const PC_URL = 'http://planex.insa-toulouse.fr/sallesInfo.php'; | ||||
| const BIB_URL = 'https://bibbox.insa-toulouse.fr/'; | ||||
| const CUSTOM_CSS_GENERAL = 'https://srv-falcon.etud.insa-toulouse.fr/~amicale_app/custom_css/rooms/customMobile.css'; | ||||
| const CUSTOM_CSS_Bib = 'https://srv-falcon.etud.insa-toulouse.fr/~amicale_app/custom_css/rooms/customBibMobile.css'; | ||||
| 
 | ||||
| /** | ||||
|  * Class defining the app's planex screen. | ||||
|  | @ -18,10 +22,20 @@ const URL = 'http://planex.insa-toulouse.fr/salles.php'; | |||
| export default class AvailableRoomScreen extends React.Component<Props> { | ||||
| 
 | ||||
|     customInjectedJS: string; | ||||
|     customBibInjectedJS: string; | ||||
| 
 | ||||
|     constructor() { | ||||
|         super(); | ||||
|         this.customInjectedJS = ''; | ||||
|         this.customInjectedJS = | ||||
|             'document.querySelector(\'head\').innerHTML += \'<meta name="viewport" content="width=device-width, initial-scale=1.0">\';' + | ||||
|             'document.querySelector(\'head\').innerHTML += \'<link rel="stylesheet" href="' + CUSTOM_CSS_GENERAL + '" type="text/css"/>\';' + | ||||
|             'let header = $(".table tbody tr:first");' + | ||||
|             '$("table").prepend("<thead></thead>");' + | ||||
|             '$("thead").append(header);'; | ||||
| 
 | ||||
|         this.customBibInjectedJS = | ||||
|             'document.querySelector(\'head\').innerHTML += \'<meta name="viewport" content="width=device-width, initial-scale=1.0">\';' + | ||||
|             'document.querySelector(\'head\').innerHTML += \'<link rel="stylesheet" href="' + CUSTOM_CSS_Bib + '" type="text/css"/>\';'; | ||||
|     } | ||||
| 
 | ||||
|     render() { | ||||
|  | @ -29,11 +43,31 @@ export default class AvailableRoomScreen extends React.Component<Props> { | |||
|         return ( | ||||
|             <WebViewScreen | ||||
|                 navigation={nav} | ||||
|                 url={URL} | ||||
|                 data={[ | ||||
|                     { | ||||
|                         url: ROOM_URL, | ||||
|                         icon: 'file-document-outline', | ||||
|                         name: i18n.t('availableRoomScreen.normalRoom'), | ||||
|                         customJS: this.customInjectedJS | ||||
|                     }, | ||||
|                     { | ||||
|                         url: PC_URL, | ||||
|                         icon: 'monitor', | ||||
|                         name: i18n.t('availableRoomScreen.computerRoom'), | ||||
|                         customJS: this.customInjectedJS | ||||
|                     }, | ||||
|                     { | ||||
|                         url: BIB_URL, | ||||
|                         icon: 'book', | ||||
|                         name: i18n.t('availableRoomScreen.bibRoom'), | ||||
|                         customJS: this.customBibInjectedJS | ||||
|                     }, | ||||
|                 ]} | ||||
|                 customInjectedJS={this.customInjectedJS} | ||||
|                 headerTitle={i18n.t('screens.availableRooms')} | ||||
|                 hasHeaderBackButton={true} | ||||
|                 hasSideMenu={false}/> | ||||
|                 hasSideMenu={false} | ||||
|                 hasFooter={false}/> | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -36,7 +36,14 @@ export default class PlanexScreen extends React.Component<Props> { | |||
|         return ( | ||||
|             <WebViewScreen | ||||
|                 navigation={nav} | ||||
|                 url={PLANEX_URL} | ||||
|                 data={[ | ||||
|                     { | ||||
|                         url: PLANEX_URL, | ||||
|                         icon: '', | ||||
|                         name: '', | ||||
|                         customJS: this.customInjectedJS | ||||
|                     }, | ||||
|                 ]} | ||||
|                 customInjectedJS={this.customInjectedJS} | ||||
|                 headerTitle={'Planex'} | ||||
|                 hasHeaderBackButton={false} | ||||
|  |  | |||
|  | @ -22,7 +22,14 @@ export default class TutorInsaScreen extends React.Component<Props> { | |||
|         return ( | ||||
|             <WebViewScreen | ||||
|                 navigation={nav} | ||||
|                 url={URL} | ||||
|                 data={[ | ||||
|                     { | ||||
|                         url: URL, | ||||
|                         icon: '', | ||||
|                         name: '', | ||||
|                         customJS: '' | ||||
|                     }, | ||||
|                 ]} | ||||
|                 headerTitle={'Tutor\'INSA'} | ||||
|                 hasHeaderBackButton={true} | ||||
|                 hasSideMenu={false}/> | ||||
|  |  | |||
|  | @ -22,7 +22,14 @@ export default class WiketudScreen extends React.Component<Props> { | |||
|         return ( | ||||
|             <WebViewScreen | ||||
|                 navigation={nav} | ||||
|                 url={URL} | ||||
|                 data={[ | ||||
|                     { | ||||
|                         url: URL, | ||||
|                         icon: '', | ||||
|                         name: '', | ||||
|                         customJS: '' | ||||
|                     }, | ||||
|                 ]} | ||||
|                 headerTitle={'Wiketud'} | ||||
|                 hasHeaderBackButton={true} | ||||
|                 hasSideMenu={false}/> | ||||
|  |  | |||
|  | @ -182,6 +182,11 @@ | |||
|       "machineRunningBody": "The machine n°{{number}} is still running" | ||||
|     } | ||||
|   }, | ||||
|   "availableRoomScreen": { | ||||
|     "normalRoom": "Work", | ||||
|     "computerRoom": "Computer", | ||||
|     "bibRoom": "Bib'Box" | ||||
|   }, | ||||
|   "general": { | ||||
|     "loading": "Loading...", | ||||
|     "networkError": "Unable to contact servers. Make sure you are connected to Internet." | ||||
|  |  | |||
|  | @ -184,6 +184,11 @@ | |||
|       "machineRunningBody": "La machine n°{{number}} n'est pas encore terminée" | ||||
|     } | ||||
|   }, | ||||
|   "availableRoomScreen": { | ||||
|     "normalRoom": "Travail", | ||||
|     "computerRoom": "Ordi", | ||||
|     "bibRoom": "Bib'Box" | ||||
|   }, | ||||
|   "general": { | ||||
|     "loading": "Chargement...", | ||||
|     "networkError": "Impossible de contacter les serveurs. Assurez vous d'être connecté à internet." | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue