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 * as React from 'react';
|
||||||
import {Linking, Platform, View} from 'react-native';
|
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 WebView from "react-native-webview";
|
||||||
import Touchable from "react-native-platform-touchable";
|
import Touchable from "react-native-platform-touchable";
|
||||||
import CustomMaterialIcon from "../components/CustomMaterialIcon";
|
import CustomMaterialIcon from "../components/CustomMaterialIcon";
|
||||||
|
@ -11,8 +11,12 @@ import BaseContainer from "../components/BaseContainer";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
navigation: Object,
|
navigation: Object,
|
||||||
url: string,
|
data: Array<{
|
||||||
customInjectedJS: string,
|
url: string,
|
||||||
|
icon: string,
|
||||||
|
name: string,
|
||||||
|
customJS: string
|
||||||
|
}>,
|
||||||
headerTitle: string,
|
headerTitle: string,
|
||||||
hasHeaderBackButton: boolean,
|
hasHeaderBackButton: boolean,
|
||||||
hasSideMenu: boolean,
|
hasSideMenu: boolean,
|
||||||
|
@ -25,16 +29,15 @@ type Props = {
|
||||||
export default class WebViewScreen extends React.Component<Props> {
|
export default class WebViewScreen extends React.Component<Props> {
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
customInjectedJS: '',
|
|
||||||
hasBackButton: false,
|
hasBackButton: false,
|
||||||
hasSideMenu: true,
|
hasSideMenu: true,
|
||||||
hasFooter: true,
|
hasFooter: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
webview: WebView;
|
webviewArray: Array<WebView> = [];
|
||||||
|
|
||||||
openWebLink() {
|
openWebLink(url: string) {
|
||||||
Linking.openURL(this.props.url).catch((err) => console.error('Error opening link', err));
|
Linking.openURL(url).catch((err) => console.error('Error opening link', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
getHeaderButton(clickAction: Function, icon: string) {
|
getHeaderButton(clickAction: Function, icon: string) {
|
||||||
|
@ -58,15 +61,73 @@ export default class WebViewScreen extends React.Component<Props> {
|
||||||
};
|
};
|
||||||
|
|
||||||
refreshWebview() {
|
refreshWebview() {
|
||||||
this.webview.reload();
|
for (let view of this.webviewArray) {
|
||||||
|
view.reload();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
goBackWebview() {
|
goBackWebview() {
|
||||||
this.webview.goBack();
|
for (let view of this.webviewArray) {
|
||||||
|
view.goBack();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
goForwardWebview() {
|
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() {
|
render() {
|
||||||
|
@ -78,38 +139,22 @@ export default class WebViewScreen extends React.Component<Props> {
|
||||||
headerRightButton={this.getRefreshButton()}
|
headerRightButton={this.getRefreshButton()}
|
||||||
hasBackButton={this.props.hasHeaderBackButton}
|
hasBackButton={this.props.hasHeaderBackButton}
|
||||||
hasSideMenu={this.props.hasSideMenu}>
|
hasSideMenu={this.props.hasSideMenu}>
|
||||||
<WebView
|
{this.props.data.length === 1 ?
|
||||||
ref={ref => (this.webview = ref)}
|
this.getWebview(this.props.data[0]) :
|
||||||
source={{uri: this.props.url}}
|
<Tabs
|
||||||
style={{
|
tabContainerStyle={{
|
||||||
width: '100%',
|
elevation: 0, // Fix for android shadow
|
||||||
height: '100%',
|
}}
|
||||||
}}
|
locked={true}
|
||||||
startInLoadingState={true}
|
>
|
||||||
injectedJavaScript={this.props.customInjectedJS}
|
{this.getTabbedWebview()}
|
||||||
javaScriptEnabled={true}
|
</Tabs>}
|
||||||
renderLoading={() =>
|
{this.props.hasFooter && this.props.data.length === 1 ?
|
||||||
<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 ?
|
|
||||||
<Footer>
|
<Footer>
|
||||||
<Left style={{
|
<Left style={{
|
||||||
paddingLeft: 6,
|
paddingLeft: 6,
|
||||||
}}>
|
}}>
|
||||||
{this.getHeaderButton(() => this.openWebLink(), 'open-in-new')}
|
{this.getHeaderButton(() => this.openWebLink(this.props.data[0]['url']), 'open-in-new')}
|
||||||
</Left>
|
</Left>
|
||||||
<Body/>
|
<Body/>
|
||||||
<Right style={{
|
<Right style={{
|
||||||
|
|
|
@ -22,7 +22,14 @@ export default class AmicaleScreen extends React.Component<Props> {
|
||||||
return (
|
return (
|
||||||
<WebViewScreen
|
<WebViewScreen
|
||||||
navigation={nav}
|
navigation={nav}
|
||||||
url={URL}
|
data={[
|
||||||
|
{
|
||||||
|
url: URL,
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
customJS: ''
|
||||||
|
},
|
||||||
|
]}
|
||||||
headerTitle={'Amicale'}
|
headerTitle={'Amicale'}
|
||||||
hasHeaderBackButton={true}
|
hasHeaderBackButton={true}
|
||||||
hasSideMenu={false}/>
|
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.
|
* 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> {
|
export default class AvailableRoomScreen extends React.Component<Props> {
|
||||||
|
|
||||||
customInjectedJS: string;
|
customInjectedJS: string;
|
||||||
|
customBibInjectedJS: string;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
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() {
|
render() {
|
||||||
|
@ -29,11 +43,31 @@ export default class AvailableRoomScreen extends React.Component<Props> {
|
||||||
return (
|
return (
|
||||||
<WebViewScreen
|
<WebViewScreen
|
||||||
navigation={nav}
|
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}
|
customInjectedJS={this.customInjectedJS}
|
||||||
headerTitle={i18n.t('screens.availableRooms')}
|
headerTitle={i18n.t('screens.availableRooms')}
|
||||||
hasHeaderBackButton={true}
|
hasHeaderBackButton={true}
|
||||||
hasSideMenu={false}/>
|
hasSideMenu={false}
|
||||||
|
hasFooter={false}/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,14 @@ export default class PlanexScreen extends React.Component<Props> {
|
||||||
return (
|
return (
|
||||||
<WebViewScreen
|
<WebViewScreen
|
||||||
navigation={nav}
|
navigation={nav}
|
||||||
url={PLANEX_URL}
|
data={[
|
||||||
|
{
|
||||||
|
url: PLANEX_URL,
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
customJS: this.customInjectedJS
|
||||||
|
},
|
||||||
|
]}
|
||||||
customInjectedJS={this.customInjectedJS}
|
customInjectedJS={this.customInjectedJS}
|
||||||
headerTitle={'Planex'}
|
headerTitle={'Planex'}
|
||||||
hasHeaderBackButton={false}
|
hasHeaderBackButton={false}
|
||||||
|
|
|
@ -22,7 +22,14 @@ export default class TutorInsaScreen extends React.Component<Props> {
|
||||||
return (
|
return (
|
||||||
<WebViewScreen
|
<WebViewScreen
|
||||||
navigation={nav}
|
navigation={nav}
|
||||||
url={URL}
|
data={[
|
||||||
|
{
|
||||||
|
url: URL,
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
customJS: ''
|
||||||
|
},
|
||||||
|
]}
|
||||||
headerTitle={'Tutor\'INSA'}
|
headerTitle={'Tutor\'INSA'}
|
||||||
hasHeaderBackButton={true}
|
hasHeaderBackButton={true}
|
||||||
hasSideMenu={false}/>
|
hasSideMenu={false}/>
|
||||||
|
|
|
@ -22,7 +22,14 @@ export default class WiketudScreen extends React.Component<Props> {
|
||||||
return (
|
return (
|
||||||
<WebViewScreen
|
<WebViewScreen
|
||||||
navigation={nav}
|
navigation={nav}
|
||||||
url={URL}
|
data={[
|
||||||
|
{
|
||||||
|
url: URL,
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
customJS: ''
|
||||||
|
},
|
||||||
|
]}
|
||||||
headerTitle={'Wiketud'}
|
headerTitle={'Wiketud'}
|
||||||
hasHeaderBackButton={true}
|
hasHeaderBackButton={true}
|
||||||
hasSideMenu={false}/>
|
hasSideMenu={false}/>
|
||||||
|
|
|
@ -182,6 +182,11 @@
|
||||||
"machineRunningBody": "The machine n°{{number}} is still running"
|
"machineRunningBody": "The machine n°{{number}} is still running"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"availableRoomScreen": {
|
||||||
|
"normalRoom": "Work",
|
||||||
|
"computerRoom": "Computer",
|
||||||
|
"bibRoom": "Bib'Box"
|
||||||
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"loading": "Loading...",
|
"loading": "Loading...",
|
||||||
"networkError": "Unable to contact servers. Make sure you are connected to Internet."
|
"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"
|
"machineRunningBody": "La machine n°{{number}} n'est pas encore terminée"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"availableRoomScreen": {
|
||||||
|
"normalRoom": "Travail",
|
||||||
|
"computerRoom": "Ordi",
|
||||||
|
"bibRoom": "Bib'Box"
|
||||||
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"loading": "Chargement...",
|
"loading": "Chargement...",
|
||||||
"networkError": "Impossible de contacter les serveurs. Assurez vous d'être connecté à internet."
|
"networkError": "Impossible de contacter les serveurs. Assurez vous d'être connecté à internet."
|
||||||
|
|
Loading…
Reference in a new issue