Compare commits

..

No commits in common. "bec015bce9fde3deeef197f7adf10b6508f522cf" and "6dfb8e0c38c018ba7716a2ef971408461144988f" have entirely different histories.

15 changed files with 78 additions and 281 deletions

4
App.js
View file

@ -72,7 +72,7 @@ export default class App extends React.Component<Props, State> {
showUpdate: false, showUpdate: false,
}); });
AsyncStorageManager.getInstance().savePref(AsyncStorageManager.getInstance().preferences.showIntro.key, '0'); AsyncStorageManager.getInstance().savePref(AsyncStorageManager.getInstance().preferences.showIntro.key, '0');
AsyncStorageManager.getInstance().savePref(AsyncStorageManager.getInstance().preferences.showUpdate4.key, '0'); AsyncStorageManager.getInstance().savePref(AsyncStorageManager.getInstance().preferences.showUpdate3.key, '0');
} }
async loadAssetsAsync() { async loadAssetsAsync() {
@ -95,7 +95,7 @@ export default class App extends React.Component<Props, State> {
isLoading: false, isLoading: false,
currentTheme: ThemeManager.getCurrentTheme(), currentTheme: ThemeManager.getCurrentTheme(),
showIntro: AsyncStorageManager.getInstance().preferences.showIntro.current === '1', showIntro: AsyncStorageManager.getInstance().preferences.showIntro.current === '1',
showUpdate: AsyncStorageManager.getInstance().preferences.showUpdate4.current === '1' showUpdate: AsyncStorageManager.getInstance().preferences.showUpdate3.current === '1'
// showIntro: true // showIntro: true
}); });
// Status bar goes dark if set too fast // Status bar goes dark if set too fast

View file

@ -10,7 +10,7 @@
"android", "android",
"web" "web"
], ],
"version": "1.3.0", "version": "1.2.0",
"orientation": "portrait", "orientation": "portrait",
"primaryColor": "#be1522", "primaryColor": "#be1522",
"icon": "./assets/android.icon.png", "icon": "./assets/android.icon.png",
@ -36,7 +36,7 @@
}, },
"android": { "android": {
"package": "fr.amicaleinsat.application", "package": "fr.amicaleinsat.application",
"versionCode": 10, "versionCode": 9,
"icon": "./assets/android.icon.png", "icon": "./assets/android.icon.png",
"adaptiveIcon": { "adaptiveIcon": {
"foregroundImage": "./assets/android.adaptive-icon.png", "foregroundImage": "./assets/android.adaptive-icon.png",

View file

@ -18,7 +18,6 @@ type Props = {
hasTabs: boolean, hasTabs: boolean,
hasBackButton: boolean, hasBackButton: boolean,
hasSideMenu: boolean, hasSideMenu: boolean,
isHeaderVisible: boolean
} }
type State = { type State = {
@ -35,7 +34,6 @@ export default class BaseContainer extends React.Component<Props, State> {
hasTabs: false, hasTabs: false,
hasBackButton: false, hasBackButton: false,
hasSideMenu: true, hasSideMenu: true,
isHeaderVisible: true,
}; };
@ -97,7 +95,6 @@ export default class BaseContainer extends React.Component<Props, State> {
render() { render() {
if (this.props.isHeaderVisible) {
return ( return (
<View style={{ <View style={{
backgroundColor: ThemeManager.getCurrentThemeVariables().sideMenuBgColor, backgroundColor: ThemeManager.getCurrentThemeVariables().sideMenuBgColor,
@ -113,17 +110,5 @@ export default class BaseContainer extends React.Component<Props, State> {
this.getMainContainer()} this.getMainContainer()}
</View> </View>
); );
} else {
return (
<View style={{
backgroundColor: ThemeManager.getCurrentThemeVariables().sideMenuBgColor,
width: '100%',
height: '100%'
}}>
{this.props.children}
</View>
);
}
} }
} }

View file

@ -105,7 +105,7 @@ export default class CustomIntroSlider extends React.Component<Props> {
key: '1', key: '1',
title: i18n.t('intro.updateSlide.title'), title: i18n.t('intro.updateSlide.title'),
text: i18n.t('intro.updateSlide.text'), text: i18n.t('intro.updateSlide.text'),
icon: 'school', icon: 'view-dashboard',
colors: ['#e01928', '#be1522'], colors: ['#e01928', '#be1522'],
}, },
] ]

View file

@ -2,93 +2,39 @@
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, Tab, TabHeading, Text, Tabs} from 'native-base'; import {Spinner, Footer, Right, Left, Body} 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";
import ThemeManager from "../utils/ThemeManager"; import ThemeManager from "../utils/ThemeManager";
import BaseContainer from "../components/BaseContainer"; import BaseContainer from "../components/BaseContainer";
import {ScreenOrientation} from 'expo';
import {NavigationActions} from 'react-navigation';
type Props = { type Props = {
navigation: Object, navigation: Object,
data: Array<{
url: string, url: string,
icon: string, customInjectedJS: string,
name: string,
customJS: string
}>,
headerTitle: string, headerTitle: string,
hasHeaderBackButton: boolean, hasHeaderBackButton: boolean,
hasSideMenu: boolean, hasSideMenu: boolean,
hasFooter: boolean, hasFooter: boolean,
} }
type State = {
isLandscape: boolean,
}
/** /**
* Class defining a webview screen. * Class defining a webview screen.
*/ */
export default class WebViewScreen extends React.Component<Props, State> { 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,
}; };
state = { webview: WebView;
isLandscape: false,
};
webviewArray: Array<WebView> = []; openWebLink() {
willFocusSubscription: function; Linking.openURL(this.props.url).catch((err) => console.error('Error opening link', err));
willBlurSubscription: function;
/**
* Register for blur event to close side menu on screen change
*/
componentDidMount() {
this.willFocusSubscription = this.props.navigation.addListener(
'willFocus',
payload => {
ScreenOrientation.unlockAsync();
ScreenOrientation.addOrientationChangeListener((OrientationChangeEvent) => {
let isLandscape = OrientationChangeEvent.orientationInfo.orientation === ScreenOrientation.Orientation.LANDSCAPE ||
OrientationChangeEvent.orientationInfo.orientation === ScreenOrientation.Orientation.LANDSCAPE_LEFT ||
OrientationChangeEvent.orientationInfo.orientation === ScreenOrientation.Orientation.LANDSCAPE_RIGHT;
this.setState({isLandscape: isLandscape});
const setParamsAction = NavigationActions.setParams({
params: {showTabBar: !isLandscape},
key: this.props.navigation.state.key,
});
this.props.navigation.dispatch(setParamsAction);
});
}
);
this.willBlurSubscription = this.props.navigation.addListener(
'willBlur',
payload => {
ScreenOrientation.lockAsync(ScreenOrientation.Orientation.PORTRAIT);
}
);
}
/**
* Unregister from event when un-mounting components
*/
componentWillUnmount() {
if (this.willBlurSubscription !== undefined)
this.willBlurSubscription.remove();
if (this.willFocusSubscription !== undefined)
this.willFocusSubscription.remove();
}
openWebLink(url: string) {
Linking.openURL(url).catch((err) => console.error('Error opening link', err));
} }
getHeaderButton(clickAction: Function, icon: string) { getHeaderButton(clickAction: Function, icon: string) {
@ -112,34 +58,35 @@ export default class WebViewScreen extends React.Component<Props, State> {
}; };
refreshWebview() { refreshWebview() {
for (let view of this.webviewArray) { this.webview.reload();
view.reload();
}
} }
goBackWebview() { goBackWebview() {
for (let view of this.webviewArray) { this.webview.goBack();
view.goBack();
}
} }
goForwardWebview() { goForwardWebview() {
for (let view of this.webviewArray) { this.webview.goForward();
view.goForward();
}
} }
getWebview(obj: Object) { render() {
const nav = this.props.navigation;
return ( return (
<BaseContainer
navigation={nav}
headerTitle={this.props.headerTitle}
headerRightButton={this.getRefreshButton()}
hasBackButton={this.props.hasHeaderBackButton}
hasSideMenu={this.props.hasSideMenu}>
<WebView <WebView
ref={ref => (this.webviewArray.push(ref))} ref={ref => (this.webview = ref)}
source={{uri: obj['url']}} source={{uri: this.props.url}}
style={{ style={{
width: '100%', width: '100%',
height: '100%', height: '100%',
}} }}
startInLoadingState={true} startInLoadingState={true}
injectedJavaScript={obj['customJS']} injectedJavaScript={this.props.customInjectedJS}
javaScriptEnabled={true} javaScriptEnabled={true}
renderLoading={() => renderLoading={() =>
<View style={{ <View style={{
@ -157,56 +104,12 @@ export default class WebViewScreen extends React.Component<Props, State> {
</View> </View>
} }
/> />
); {this.props.hasFooter ?
}
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() {
const nav = this.props.navigation;
return (
<BaseContainer
navigation={nav}
headerTitle={this.props.headerTitle}
headerRightButton={this.getRefreshButton()}
hasBackButton={this.props.hasHeaderBackButton}
hasSideMenu={this.props.hasSideMenu}
isHeaderVisible={!this.state.isLandscape}>
{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> <Footer>
<Left style={{ <Left style={{
paddingLeft: 6, paddingLeft: 6,
}}> }}>
{this.getHeaderButton(() => this.openWebLink(this.props.data[0]['url']), 'open-in-new')} {this.getHeaderButton(() => this.openWebLink(), 'open-in-new')}
</Left> </Left>
<Body/> <Body/>
<Right style={{ <Right style={{

View file

@ -24,22 +24,14 @@ function createMaterialBottomTabNavigatorWithInitialRoute(initialRoute: string)
Planning: {screen: PlanningScreen,}, Planning: {screen: PlanningScreen,},
Proxiwash: {screen: ProxiwashScreen,}, Proxiwash: {screen: ProxiwashScreen,},
Proximo: {screen: ProximoMainScreen,}, Proximo: {screen: ProximoMainScreen,},
Planex: { Planex: {screen: PlanexScreen},
screen: PlanexScreen,
navigationOptions: ({ navigation }) => {
const showTabBar = navigation.state && navigation.state.params ? navigation.state.params.showTabBar : true;
return {
tabBarVisible: showTabBar,
};
},},
}, { }, {
defaultNavigationOptions: ({navigation}) => ({ defaultNavigationOptions: ({navigation}) => ({
tabBarIcon: ({focused, horizontal, tintColor}) => { tabBarIcon: ({focused, horizontal, tintColor}) => {
let icon = TAB_ICONS[navigation.state.routeName]; let icon = TAB_ICONS[navigation.state.routeName];
return <CustomMaterialIcon icon={icon} color={tintColor}/>; return <CustomMaterialIcon icon={icon} color={tintColor}/>;
}, }
tabBarVisible: true,
}), }),
order: ['Proximo', 'Planning', 'Home', 'Proxiwash', 'Planex'], order: ['Proximo', 'Planning', 'Home', 'Proxiwash', 'Planex'],
initialRouteName: initialRoute, initialRouteName: initialRoute,

View file

@ -152,7 +152,7 @@ export default class AboutScreen extends React.Component<Props, State> {
onPressCallback: () => openWebLink(links.react), onPressCallback: () => openWebLink(links.react),
icon: 'react', icon: 'react',
text: i18n.t('aboutScreen.reactNative'), text: i18n.t('aboutScreen.reactNative'),
showChevron: true showChevron: false
}, },
{ {
onPressCallback: () => this.props.navigation.navigate('AboutDependenciesScreen', {data: packageJson.dependencies}), onPressCallback: () => this.props.navigation.navigate('AboutDependenciesScreen', {data: packageJson.dependencies}),

View file

@ -22,14 +22,7 @@ export default class AmicaleScreen extends React.Component<Props> {
return ( return (
<WebViewScreen <WebViewScreen
navigation={nav} navigation={nav}
data={[ url={URL}
{
url: URL,
icon: '',
name: '',
customJS: ''
},
]}
headerTitle={'Amicale'} headerTitle={'Amicale'}
hasHeaderBackButton={true} hasHeaderBackButton={true}
hasSideMenu={false}/> hasSideMenu={false}/>

View file

@ -9,11 +9,7 @@ type Props = {
} }
const ROOM_URL = 'http://planex.insa-toulouse.fr/salles.php'; const 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.
@ -22,20 +18,10 @@ const CUSTOM_CSS_Bib = 'https://srv-falcon.etud.insa-toulouse.fr/~amicale_app/cu
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>");true;' + // Fix for crash on ios
'$("thead").append(header);true;';
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() {
@ -43,31 +29,11 @@ export default class AvailableRoomScreen extends React.Component<Props> {
return ( return (
<WebViewScreen <WebViewScreen
navigation={nav} navigation={nav}
data={[ url={URL}
{
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}/>
); );
} }
} }

View file

@ -3,7 +3,6 @@
import * as React from 'react'; import * as React from 'react';
import ThemeManager from "../utils/ThemeManager"; import ThemeManager from "../utils/ThemeManager";
import WebViewScreen from "../components/WebViewScreen"; import WebViewScreen from "../components/WebViewScreen";
import i18n from "i18n-js";
type Props = { type Props = {
navigation: Object, navigation: Object,
@ -12,8 +11,8 @@ type Props = {
const PLANEX_URL = 'http://planex.insa-toulouse.fr/'; const PLANEX_URL = 'http://planex.insa-toulouse.fr/';
const CUSTOM_CSS_GENERAL = 'https://srv-falcon.etud.insa-toulouse.fr/~amicale_app/custom_css/planex/customMobile2.css'; const CUSTOM_CSS_GENERAL = 'https://srv-falcon.etud.insa-toulouse.fr/~amicale_app/custom_css/planex/customMobile.css';
const CUSTOM_CSS_NIGHTMODE = 'https://srv-falcon.etud.insa-toulouse.fr/~amicale_app/custom_css/planex/customDark2.css'; const CUSTOM_CSS_NIGHTMODE = 'https://srv-falcon.etud.insa-toulouse.fr/~amicale_app/custom_css/planex/customDark.css';
/** /**
* Class defining the app's planex screen. * Class defining the app's planex screen.
@ -27,9 +26,7 @@ export default class PlanexScreen extends React.Component<Props> {
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 += \'<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"/>\';' + 'document.querySelector(\'head\').innerHTML += \'<link rel="stylesheet" href="' + CUSTOM_CSS_GENERAL + '" type="text/css"/>\';';
'$(".fc-toolbar .fc-center").append(\'<p id="rotateToLandscape">' + i18n.t("planexScreen.rotateToLandscape") + '</p>\');' +
'$(".fc-toolbar .fc-center").append(\'<p id="rotateToPortrait">' + i18n.t("planexScreen.rotateToPortrait") + '</p>\');';
if (ThemeManager.getNightMode()) if (ThemeManager.getNightMode())
this.customInjectedJS += 'document.querySelector(\'head\').innerHTML += \'<link rel="stylesheet" href="' + CUSTOM_CSS_NIGHTMODE + '" type="text/css"/>\';'; this.customInjectedJS += 'document.querySelector(\'head\').innerHTML += \'<link rel="stylesheet" href="' + CUSTOM_CSS_NIGHTMODE + '" type="text/css"/>\';';
} }
@ -39,14 +36,7 @@ export default class PlanexScreen extends React.Component<Props> {
return ( return (
<WebViewScreen <WebViewScreen
navigation={nav} navigation={nav}
data={[ url={PLANEX_URL}
{
url: PLANEX_URL,
icon: '',
name: '',
customJS: this.customInjectedJS
},
]}
customInjectedJS={this.customInjectedJS} customInjectedJS={this.customInjectedJS}
headerTitle={'Planex'} headerTitle={'Planex'}
hasHeaderBackButton={false} hasHeaderBackButton={false}

View file

@ -22,14 +22,7 @@ export default class TutorInsaScreen extends React.Component<Props> {
return ( return (
<WebViewScreen <WebViewScreen
navigation={nav} navigation={nav}
data={[ url={URL}
{
url: URL,
icon: '',
name: '',
customJS: ''
},
]}
headerTitle={'Tutor\'INSA'} headerTitle={'Tutor\'INSA'}
hasHeaderBackButton={true} hasHeaderBackButton={true}
hasSideMenu={false}/> hasSideMenu={false}/>

View file

@ -22,14 +22,7 @@ export default class WiketudScreen extends React.Component<Props> {
return ( return (
<WebViewScreen <WebViewScreen
navigation={nav} navigation={nav}
data={[ url={URL}
{
url: URL,
icon: '',
name: '',
customJS: ''
},
]}
headerTitle={'Wiketud'} headerTitle={'Wiketud'}
hasHeaderBackButton={true} hasHeaderBackButton={true}
hasSideMenu={false}/> hasSideMenu={false}/>

View file

@ -41,7 +41,7 @@
}, },
"updateSlide": { "updateSlide": {
"title": "New in this update!", "title": "New in this update!",
"text": "Get ready for your exams with Tutor'INSA! Book a Bib'Box or find an empty room to study, available in the side menu." "text": "Say hello to the brand new dashboard!\nGet a quick look at the most important information right from the home screen!"
}, },
"buttons": { "buttons": {
"next": "Next", "next": "Next",
@ -182,15 +182,6 @@
"machineRunningBody": "The machine n°{{number}} is still running" "machineRunningBody": "The machine n°{{number}} is still running"
} }
}, },
"planexScreen": {
"rotateToLandscape": "Turn your screen to see the whole week",
"rotateToPortrait": "Turn your screen to see only 2 days"
},
"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."

View file

@ -41,7 +41,7 @@
}, },
"updateSlide": { "updateSlide": {
"title": "Nouveau dans cette mise à jour !", "title": "Nouveau dans cette mise à jour !",
"text": "Préparez vos exams avec Tutor'INSA! Réservez une Bib'Box ou trouvez une salle libre pour travailler, disponible dans le menu à gauche. " "text": "Dites bonjour à la toute nouvelle Dashboard !\nAccédez rapidement aux informations les plus importantes depuis l'écran d'accueil !"
}, },
"buttons": { "buttons": {
"next": "Suivant", "next": "Suivant",
@ -184,15 +184,6 @@
"machineRunningBody": "La machine n°{{number}} n'est pas encore terminée" "machineRunningBody": "La machine n°{{number}} n'est pas encore terminée"
} }
}, },
"planexScreen": {
"rotateToLandscape": "Tournez votre téléphone pour voir la semaine entière",
"rotateToPortrait": "Tournez votre téléphone pour voir seulement 2 jours"
},
"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."

View file

@ -29,8 +29,8 @@ export default class AsyncStorageManager {
default: '1', default: '1',
current: '', current: '',
}, },
showUpdate4: { showUpdate3: {
key: 'showUpdate4', key: 'showUpdate3',
default: '1', default: '1',
current: '', current: '',
}, },