Use React navigation header

This commit is contained in:
keplyx 2020-03-06 09:12:56 +01:00
parent 14960794bc
commit 79eaefab88
21 changed files with 659 additions and 732 deletions

View file

@ -1,83 +0,0 @@
// @flow
import * as React from 'react';
import {Container} from "native-base";
import CustomHeader from "./CustomHeader";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import {Platform, View} from "react-native";
import ThemeManager from "../utils/ThemeManager";
import Touchable from "react-native-platform-touchable";
type Props = {
navigation: Object,
headerTitle: string,
headerSubtitle: string,
headerRightButton: React.Node,
children: React.Node,
hasTabs: boolean,
hasBackButton: boolean,
hasSideMenu: boolean,
enableRotation: boolean,
hideHeaderOnLandscape: boolean,
}
type State = {
isHeaderVisible: boolean
}
export default class BaseContainer extends React.Component<Props, State> {
static defaultProps = {
headerRightButton: <View/>,
hasTabs: false,
hasBackButton: false,
hasSideMenu: true,
enableRotation: false,
hideHeaderOnLandscape: false,
headerSubtitle: '',
};
state = {
isHeaderVisible: true,
};
onDrawerPress: Function;
constructor() {
super();
this.onDrawerPress = this.onDrawerPress.bind(this);
}
onDrawerPress() {
this.props.navigation.toggleDrawer();
}
render() {
// console.log("rendering BaseContainer");
return (
<Container>
{this.state.isHeaderVisible ?
<CustomHeader
navigation={this.props.navigation}
title={this.props.headerTitle}
subtitle={this.props.headerSubtitle}
leftButton={
<Touchable
style={{padding: 6}}
onPress={this.onDrawerPress}>
<MaterialCommunityIcons
color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
size={26}
name="menu"/>
</Touchable>
}
rightButton={this.props.headerRightButton}
hasTabs={this.props.hasTabs}
hasBackButton={this.props.hasBackButton}/>
: <View/>}
{this.props.children}
</Container>
);
}
}

View file

@ -1,150 +0,0 @@
// @flow
import * as React from "react";
import {Body, Header, Input, Item, Left, Right, Subtitle, Title} from "native-base";
import {Platform, StyleSheet, View} from "react-native";
import {getStatusBarHeight} from "react-native-status-bar-height";
import Touchable from 'react-native-platform-touchable';
import ThemeManager from "../utils/ThemeManager";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import i18n from "i18n-js";
type Props = {
hasBackButton: boolean,
hasSearchField: boolean,
searchCallback: Function,
shouldFocusSearchBar: boolean,
leftButton: React.Node,
rightButton: React.Node,
title: string,
subtitle: string,
navigation: Object,
hasTabs: boolean,
};
/**
* Custom component defining a header using native base
*
* @prop hasBackButton {boolean} Whether to show a back button or a burger menu. Use burger if unspecified
* @prop rightMenu {React.Node} Element to place at the right of the header. Use nothing if unspecified
* @prop title {string} This header title
* @prop navigation {Object} The navigation object from react navigation
*/
export default class CustomHeader extends React.Component<Props> {
static defaultProps = {
hasBackButton: false,
hasSearchField: false,
searchCallback: null,
shouldFocusSearchBar: false,
title: '',
subtitle: '',
leftButton: <View/>,
rightButton: <View/>,
hasTabs: false,
};
onPressBack: Function;
constructor() {
super();
this.onPressBack = this.onPressBack.bind(this);
}
shouldComponentUpdate(nextProps: Props): boolean {
return nextProps.title !== this.props.title ||
nextProps.subtitle !== this.props.subtitle ||
nextProps.hasBackButton !== this.props.hasBackButton ||
nextProps.hasSearchField !== this.props.hasSearchField ||
nextProps.shouldFocusSearchBar !== this.props.shouldFocusSearchBar ||
nextProps.hasTabs !== this.props.hasTabs ||
nextProps.rightButton !== this.props.rightButton ||
nextProps.leftButton !== this.props.leftButton;
}
componentDidMount() {
if (this.refs.searchInput !== undefined && this.refs.searchInput._root !== undefined && this.props.shouldFocusSearchBar) {
// does not work if called too early for some reason...
setTimeout(this.refs.searchInput._root.focus, 500);
}
}
getSearchBar() {
return (
<Body>
<Item
style={{
width: '100%',
marginBottom: 7
}}>
<MaterialCommunityIcons
name={'magnify'}
size={26}
color={ThemeManager.getCurrentThemeVariables().toolbarBtnColor}/>
<Input
ref="searchInput"
placeholder={i18n.t('proximoScreen.search')}
placeholderTextColor={ThemeManager.getCurrentThemeVariables().toolbarPlaceholderColor}
onChangeText={this.props.searchCallback}/>
</Item>
</Body>
);
}
getHeaderTitle() {
return (
<Body>
<Title style={{
color: ThemeManager.getCurrentThemeVariables().toolbarTextColor
}}>
{this.props.title}
</Title>
{this.props.subtitle !== '' ? <Subtitle>{this.props.subtitle}</Subtitle> : null}
</Body>
);
}
onPressBack() {
this.props.navigation.goBack();
}
render() {
// console.log("rendering CustomHeader");
let button;
// Does the app have a back button or a burger menu ?
if (this.props.hasBackButton)
button =
<Touchable
style={{padding: 6}}
onPress={this.onPressBack}>
<MaterialCommunityIcons
color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
name={Platform.OS === 'ios' ? 'chevron-left' : "arrow-left"}
size={26}/>
</Touchable>;
else
button = this.props.leftButton;
return (
<Header style={styles.header}
hasTabs={this.props.hasTabs}>
<Left style={{flex: 0}}>
{button}
</Left>
{this.props.hasSearchField ?
this.getSearchBar() :
this.getHeaderTitle()}
<Right style={{flex: this.props.hasSearchField ? 0 : 1}}>
{this.props.rightButton}
</Right>
</Header>);
}
};
// Fix header in status bar on Android
const styles = StyleSheet.create({
header: {
paddingTop: getStatusBarHeight(),
height: 54 + getStatusBarHeight(),
},
});

View file

@ -40,6 +40,42 @@ export default class SideBar extends React.Component<Props, State> {
super(props); super(props);
// Dataset used to render the drawer // Dataset used to render the drawer
this.dataSet = [ this.dataSet = [
{
name: "Home",
route: "Main",
icon: "home",
},
{
name: i18n.t('sidenav.divider2'),
route: "Divider2"
},
{
name: i18n.t('screens.menuSelf'),
route: "SelfMenuScreen",
icon: "silverware-fork-knife",
},
{
name: i18n.t('screens.availableRooms'),
route: "AvailableRoomScreen",
icon: "calendar-check",
},
{
name: 'Bib',
route: "BibScreen",
icon: "book",
},
{
name: i18n.t('screens.bluemind'),
route: "BlueMindScreen",
link: "https://etud-mel.insa-toulouse.fr/webmail/",
icon: "email",
},
{
name: i18n.t('screens.ent'),
route: "EntScreen",
link: "https://ent.insa-toulouse.fr/",
icon: "notebook",
},
{ {
name: i18n.t('sidenav.divider1'), name: i18n.t('sidenav.divider1'),
route: "Divider1" route: "Divider1"
@ -68,32 +104,6 @@ export default class SideBar extends React.Component<Props, State> {
link: "https://www.etud.insa-toulouse.fr/~tutorinsa/", link: "https://www.etud.insa-toulouse.fr/~tutorinsa/",
icon: "school", icon: "school",
}, },
{
name: i18n.t('sidenav.divider2'),
route: "Divider2"
},
{
name: i18n.t('screens.bluemind'),
route: "BlueMindScreen",
link: "https://etud-mel.insa-toulouse.fr/webmail/",
icon: "email",
},
{
name: i18n.t('screens.ent'),
route: "EntScreen",
link: "https://ent.insa-toulouse.fr/",
icon: "notebook",
},
{
name: i18n.t('screens.availableRooms'),
route: "AvailableRoomScreen",
icon: "calendar-check",
},
{
name: i18n.t('screens.menuSelf'),
route: "SelfMenuScreen",
icon: "silverware-fork-knife",
},
{ {
name: i18n.t('sidenav.divider3'), name: i18n.t('sidenav.divider3'),
route: "Divider3" route: "Divider3"

View file

@ -1,13 +1,12 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import {Linking, Platform, View} from 'react-native'; import {Platform, View} from 'react-native';
import {Body, Footer, Left, Right, Spinner, Tab, TabHeading, Tabs, Text} from 'native-base'; import {Container, Spinner, Tab, TabHeading, Tabs, Text} 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 {MaterialCommunityIcons} from "@expo/vector-icons"; import {MaterialCommunityIcons} from "@expo/vector-icons";
import ThemeManager from "../utils/ThemeManager"; import ThemeManager from "../utils/ThemeManager";
import BaseContainer from "../components/BaseContainer";
type Props = { type Props = {
navigation: Object, navigation: Object,
@ -50,8 +49,11 @@ export default class WebViewScreen extends React.Component<Props> {
this.onOpenWebLink = this.onOpenWebLink.bind(this); this.onOpenWebLink = this.onOpenWebLink.bind(this);
} }
openWebLink(url: string) { componentDidMount() {
Linking.openURL(url).catch((err) => console.error('Error opening link', err)); const rightButton = this.getRefreshButton.bind(this);
this.props.navigation.setOptions({
headerRight: rightButton,
});
} }
getHeaderButton(clickAction: Function, icon: string) { getHeaderButton(clickAction: Function, icon: string) {
@ -69,7 +71,10 @@ export default class WebViewScreen extends React.Component<Props> {
getRefreshButton() { getRefreshButton() {
return ( return (
<View style={{flexDirection: 'row'}}> <View style={{
flexDirection: 'row',
marginRight: 10
}}>
{this.getHeaderButton(this.onRefreshClicked, 'refresh')} {this.getHeaderButton(this.onRefreshClicked, 'refresh')}
</View> </View>
); );
@ -165,15 +170,7 @@ export default class WebViewScreen extends React.Component<Props> {
const nav = this.props.navigation; const nav = this.props.navigation;
this.webviewArray = []; this.webviewArray = [];
return ( return (
<BaseContainer <Container>
navigation={nav}
headerTitle={this.props.headerTitle}
headerRightButton={this.getRefreshButton()}
hasBackButton={this.props.hasHeaderBackButton}
hasSideMenu={this.props.hasSideMenu}
enableRotation={true}
hideHeaderOnLandscape={true}
hasTabs={this.props.data.length > 1}>
{this.props.data.length === 1 ? {this.props.data.length === 1 ?
this.getWebview(this.props.data[0]) : this.getWebview(this.props.data[0]) :
<Tabs <Tabs
@ -190,30 +187,7 @@ export default class WebViewScreen extends React.Component<Props> {
> >
{this.getTabbedWebview()} {this.getTabbedWebview()}
</Tabs>} </Tabs>}
{this.props.hasFooter && this.props.data.length === 1 ? </Container>
<Footer>
<Left style={{
paddingLeft: 6,
}}>
{this.getHeaderButton(this.onOpenWebLink, 'open-in-new')}
</Left>
<Body/>
<Right style={{
flexDirection: 'row',
alignItems: 'flex-end',
paddingRight: 6
}}>
<View style={{
flexDirection: 'row',
marginRight: 0,
marginLeft: 'auto'
}}>
{this.getHeaderButton(this.onGoBackWebview, 'chevron-left')}
{this.getHeaderButton(this.onGoForwardWebview, 'chevron-right')}
</View>
</Right>
</Footer> : <View/>}
</BaseContainer>
); );
} }
} }

View file

@ -8,10 +8,52 @@ import AboutScreen from '../screens/About/AboutScreen';
import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen'; import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
import SelfMenuScreen from '../screens/SelfMenuScreen'; import SelfMenuScreen from '../screens/SelfMenuScreen';
import AvailableRoomScreen from "../screens/Websites/AvailableRoomScreen"; import AvailableRoomScreen from "../screens/Websites/AvailableRoomScreen";
import BibScreen from "../screens/Websites/BibScreen";
import DebugScreen from '../screens/DebugScreen'; import DebugScreen from '../screens/DebugScreen';
import Sidebar from "../components/Sidebar"; import Sidebar from "../components/Sidebar";
import {createStackNavigator, TransitionPresets} from "@react-navigation/stack"; import {createStackNavigator, TransitionPresets} from "@react-navigation/stack";
import PerfHomeScreen from '../screens/PerfHomeScreen'; import PerfHomeScreen from '../screens/PerfHomeScreen';
import {Platform, StyleSheet, View} from "react-native";
import ThemeManager from "../utils/ThemeManager";
import Touchable from "react-native-platform-touchable";
import {MaterialCommunityIcons} from "@expo/vector-icons";
const styles = StyleSheet.create({
header: {
backgroundColor: ThemeManager.getCurrentThemeVariables().brandPrimary,
},
headerTitle: {
color: "#ffffff",
},
});
const defaultScreenOptions = {
headerTintColor: 'white',
headerStyle: styles.header,
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.SlideFromRightIOS,
};
function getDrawerButton(navigation: Object) {
return (
<View
style={{
flexDirection: 'row',
marginLeft: 10
}}>
<Touchable
style={{padding: 6}}
onPress={navigation.openDrawer}>
<MaterialCommunityIcons
name="menu"
size={26}
color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}/>
</Touchable>
</View>
);
}
const AboutStack = createStackNavigator(); const AboutStack = createStackNavigator();
@ -19,30 +61,134 @@ function AboutStackComponent() {
return ( return (
<AboutStack.Navigator <AboutStack.Navigator
initialRouteName="AboutScreen" initialRouteName="AboutScreen"
mode='card' headerMode="float"
headerMode="none" screenOptions={defaultScreenOptions}
screenOptions={{
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.SlideFromRightIOS,
}}
> >
<AboutStack.Screen <AboutStack.Screen
name="AboutScreen" name="AboutScreen"
component={AboutScreen} component={AboutScreen}
options={({navigation}) => {
const openDrawer = getDrawerButton.bind(this, navigation);
return {
title: 'About',
headerLeft: openDrawer
};
}}
/> />
<AboutStack.Screen <AboutStack.Screen
name="AboutDependenciesScreen" name="AboutDependenciesScreen"
component={AboutDependenciesScreen} component={AboutDependenciesScreen}
options={{
title: 'Dependencies'
}}
/> />
<AboutStack.Screen <AboutStack.Screen
name="DebugScreen" name="DebugScreen"
component={DebugScreen} component={DebugScreen}
options={{
title: 'Debug'
}}
/> />
</AboutStack.Navigator> </AboutStack.Navigator>
); );
} }
const SettingsStack = createStackNavigator();
function SettingsStackComponent() {
return (
<SettingsStack.Navigator
initialRouteName="SettingsScreen"
headerMode="float"
screenOptions={defaultScreenOptions}
>
<SettingsStack.Screen
name="SettingsScreen"
component={SettingsScreen}
options={({navigation}) => {
const openDrawer = getDrawerButton.bind(this, navigation);
return {
title: 'Settings',
headerLeft: openDrawer
};
}}
/>
</SettingsStack.Navigator>
);
}
const SelfMenuStack = createStackNavigator();
function SelfMenuStackComponent() {
return (
<SelfMenuStack.Navigator
initialRouteName="SelfMenuScreen"
headerMode="float"
screenOptions={defaultScreenOptions}
>
<SelfMenuStack.Screen
name="SelfMenuScreen"
component={SelfMenuScreen}
options={({navigation}) => {
const openDrawer = getDrawerButton.bind(this, navigation);
return {
title: 'Menu RU',
headerLeft: openDrawer
};
}}
/>
</SelfMenuStack.Navigator>
);
}
const AvailableRoomStack = createStackNavigator();
function AvailableRoomStackComponent() {
return (
<AvailableRoomStack.Navigator
initialRouteName="AvailableRoomScreen"
headerMode="float"
screenOptions={defaultScreenOptions}
>
<AvailableRoomStack.Screen
name="AvailableRoomScreen"
component={AvailableRoomScreen}
options={({navigation}) => {
const openDrawer = getDrawerButton.bind(this, navigation);
return {
title: 'Available Rooms',
headerLeft: openDrawer
};
}}
/>
</AvailableRoomStack.Navigator>
);
}
const BibStack = createStackNavigator();
function BibStackComponent() {
return (
<BibStack.Navigator
initialRouteName="BibScreen"
headerMode="float"
screenOptions={defaultScreenOptions}
>
<BibStack.Screen
name="BibScreen"
component={BibScreen}
options={({navigation}) => {
const openDrawer = getDrawerButton.bind(this, navigation);
return {
title: 'Bib',
headerLeft: openDrawer
};
}}
/>
</BibStack.Navigator>
);
}
const Drawer = createDrawerNavigator(); const Drawer = createDrawerNavigator();
function getDrawerContent(nav) { function getDrawerContent(nav) {
@ -53,13 +199,11 @@ export default function DrawerNavigator() {
return ( return (
<Drawer.Navigator <Drawer.Navigator
initialRouteName={'Main'} initialRouteName={'Main'}
mode='card' headerMode={'float'}
backBehavior={'initialRoute'}
drawerType={'back'}
drawerContent={props => getDrawerContent(props.navigation)} drawerContent={props => getDrawerContent(props.navigation)}
screenOptions={{ screenOptions={defaultScreenOptions}
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.SlideFromRightIOS,
}}
> >
<Drawer.Screen <Drawer.Screen
name="Main" name="Main"
@ -68,7 +212,7 @@ export default function DrawerNavigator() {
</Drawer.Screen> </Drawer.Screen>
<Drawer.Screen <Drawer.Screen
name="SettingsScreen" name="SettingsScreen"
component={SettingsScreen} component={SettingsStackComponent}
/> />
<Drawer.Screen <Drawer.Screen
name="AboutScreen" name="AboutScreen"
@ -76,33 +220,16 @@ export default function DrawerNavigator() {
/> />
<Drawer.Screen <Drawer.Screen
name="SelfMenuScreen" name="SelfMenuScreen"
component={SelfMenuScreen} component={SelfMenuStackComponent}
/> />
<Drawer.Screen <Drawer.Screen
name="AvailableRoomScreen" name="AvailableRoomScreen"
component={AvailableRoomScreen} component={AvailableRoomStackComponent}
/>
<Drawer.Screen
name="BibScreen"
component={BibStackComponent}
/> />
</Drawer.Navigator> </Drawer.Navigator>
); );
} }
const basicStack = createStackNavigator();
function DrawerNavigator1() {
return (
<basicStack.Navigator
initialRouteName={'Main'}
mode='card'
screenOptions={{
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.SlideFromRightIOS,
}}
>
<basicStack.Screen
name="Main"
component={TabNavigator}
/>
</basicStack.Navigator>
);
}

View file

@ -14,7 +14,7 @@ import PlanexScreen from '../screens/Websites/PlanexScreen';
import {MaterialCommunityIcons} from "@expo/vector-icons"; import {MaterialCommunityIcons} from "@expo/vector-icons";
import ThemeManager from "../utils/ThemeManager"; import ThemeManager from "../utils/ThemeManager";
import AsyncStorageManager from "../utils/AsyncStorageManager"; import AsyncStorageManager from "../utils/AsyncStorageManager";
import {StyleSheet, View} from "react-native"; import {Platform, StyleSheet, View} from "react-native";
import Touchable from "react-native-platform-touchable"; import Touchable from "react-native-platform-touchable";
const TAB_ICONS = { const TAB_ICONS = {
@ -25,8 +25,6 @@ const TAB_ICONS = {
Planex: 'timetable', Planex: 'timetable',
}; };
const ProximoStack = createStackNavigator();
const styles = StyleSheet.create({ const styles = StyleSheet.create({
header: { header: {
backgroundColor: ThemeManager.getCurrentThemeVariables().brandPrimary, backgroundColor: ThemeManager.getCurrentThemeVariables().brandPrimary,
@ -36,24 +34,50 @@ const styles = StyleSheet.create({
}, },
}); });
const defaultScreenOptions = {
headerTintColor: 'white',
headerStyle: styles.header,
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.SlideFromRightIOS,
};
function getDrawerButton(navigation: Object) {
return (
<View
style={{
flexDirection: 'row',
marginLeft: 10
}}>
<Touchable
style={{padding: 6}}
onPress={navigation.openDrawer}>
<MaterialCommunityIcons
name="menu"
size={26}
color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}/>
</Touchable>
</View>
);
}
const ProximoStack = createStackNavigator();
function ProximoStackComponent() { function ProximoStackComponent() {
return ( return (
<ProximoStack.Navigator <ProximoStack.Navigator
initialRouteName="ProximoMainScreen" initialRouteName="ProximoMainScreen"
headerMode="float" headerMode="float"
screenOptions={{ screenOptions={defaultScreenOptions}
headerTintColor: 'white',
headerStyle: styles.header,
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.SlideFromRightIOS,
}}
> >
<ProximoStack.Screen <ProximoStack.Screen
name="ProximoMainScreen" name="ProximoMainScreen"
options={{ options={({navigation}) => {
title: 'Proximo', const openDrawer = getDrawerButton.bind(this, navigation);
return {
title: 'Proximo',
headerLeft: openDrawer
};
}} }}
component={ProximoMainScreen} component={ProximoMainScreen}
/> />
@ -82,21 +106,27 @@ function ProxiwashStackComponent() {
return ( return (
<ProxiwashStack.Navigator <ProxiwashStack.Navigator
initialRouteName="ProxiwashScreen" initialRouteName="ProxiwashScreen"
mode='card' headerMode='float'
headerMode="none" screenOptions={defaultScreenOptions}
screenOptions={{
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.ModalSlideFromBottomIOS,
}}
> >
<ProxiwashStack.Screen <ProxiwashStack.Screen
name="ProxiwashScreen" name="ProxiwashScreen"
component={ProxiwashScreen} component={ProxiwashScreen}
options={({navigation}) => {
const openDrawer = getDrawerButton.bind(this, navigation);
return {
title: 'Proxiwash',
headerLeft: openDrawer
};
}}
/> />
<ProxiwashStack.Screen <ProxiwashStack.Screen
name="ProxiwashAboutScreen" name="ProxiwashAboutScreen"
component={ProxiwashAboutScreen} component={ProxiwashAboutScreen}
options={{
title: 'Proxiwash',
...TransitionPresets.ModalSlideFromBottomIOS,
}}
/> />
</ProxiwashStack.Navigator> </ProxiwashStack.Navigator>
); );
@ -108,21 +138,27 @@ function PlanningStackComponent() {
return ( return (
<PlanningStack.Navigator <PlanningStack.Navigator
initialRouteName="PlanningScreen" initialRouteName="PlanningScreen"
mode='card' headerMode='float'
headerMode="none" screenOptions={defaultScreenOptions}
screenOptions={{
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.ModalSlideFromBottomIOS,
}}
> >
<PlanningStack.Screen <PlanningStack.Screen
name="PlanningScreen" name="PlanningScreen"
component={PlanningScreen} component={PlanningScreen}
options={({navigation}) => {
const openDrawer = getDrawerButton.bind(this, navigation);
return {
title: 'Planning',
headerLeft: openDrawer
};
}}
/> />
<PlanningStack.Screen <PlanningStack.Screen
name="PlanningDisplayScreen" name="PlanningDisplayScreen"
component={PlanningDisplayScreen} component={PlanningDisplayScreen}
options={{
title: 'Details',
...TransitionPresets.ModalSlideFromBottomIOS,
}}
/> />
</PlanningStack.Navigator> </PlanningStack.Navigator>
); );
@ -134,26 +170,56 @@ function HomeStackComponent() {
return ( return (
<HomeStack.Navigator <HomeStack.Navigator
initialRouteName="HomeScreen" initialRouteName="HomeScreen"
mode='card'
headerMode="float" headerMode="float"
screenOptions={{ screenOptions={defaultScreenOptions}
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.ModalSlideFromBottomIOS,
}}
> >
<HomeStack.Screen <HomeStack.Screen
name="HomeScreen" name="HomeScreen"
component={HomeScreen} component={HomeScreen}
options={({navigation}) => {
const openDrawer = getDrawerButton.bind(this, navigation);
return {
title: 'Home',
headerLeft: openDrawer
};
}}
/> />
<HomeStack.Screen <HomeStack.Screen
name="PlanningDisplayScreen" name="PlanningDisplayScreen"
component={PlanningDisplayScreen} component={PlanningDisplayScreen}
options={{
title: 'Details',
...TransitionPresets.ModalSlideFromBottomIOS,
}}
/> />
</HomeStack.Navigator> </HomeStack.Navigator>
); );
} }
const PlanexStack = createStackNavigator();
function PlanexStackComponent() {
return (
<PlanexStack.Navigator
initialRouteName="HomeScreen"
headerMode="float"
screenOptions={defaultScreenOptions}
>
<PlanexStack.Screen
name="PlanexScreen"
component={PlanexScreen}
options={({navigation}) => {
const openDrawer = getDrawerButton.bind(this, navigation);
return {
title: 'Planex',
headerLeft: openDrawer
};
}}
/>
</PlanexStack.Navigator>
);
}
const Tab = createMaterialBottomTabNavigator(); const Tab = createMaterialBottomTabNavigator();
export default function TabNavigator() { export default function TabNavigator() {
@ -188,7 +254,7 @@ export default function TabNavigator() {
/> />
<Tab.Screen <Tab.Screen
name="Planex" name="Planex"
component={PlanexScreen} component={PlanexStackComponent}
/> />
</Tab.Navigator> </Tab.Navigator>
); );

View file

@ -1,10 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import {Body, Container, ListItem, Text} from 'native-base'; import {Body, ListItem, Text} from 'native-base';
import CustomHeader from "../../components/CustomHeader";
import {FlatList} from "react-native"; import {FlatList} from "react-native";
import i18n from "i18n-js"; import packageJson from '../../package';
function generateListFromObject(object) { function generateListFromObject(object) {
let list = []; let list = [];
@ -17,7 +16,8 @@ function generateListFromObject(object) {
} }
type Props = { type Props = {
navigation: Object navigation: Object,
route: Object
} }
/** /**
@ -26,28 +26,24 @@ type Props = {
export default class AboutDependenciesScreen extends React.Component<Props> { export default class AboutDependenciesScreen extends React.Component<Props> {
render() { render() {
const nav = this.props.navigation; const data = generateListFromObject(packageJson.dependencies);
const data = generateListFromObject(nav.getParam('data', {}));
return ( return (
<Container> <FlatList
<CustomHeader hasBackButton={true} navigation={nav} title={i18n.t('aboutScreen.libs')}/> data={data}
<FlatList keyExtractor={(item) => item.name}
data={data} style={{minHeight: 300, width: '100%'}}
keyExtractor={(item) => item.name} renderItem={({item}) =>
style={{minHeight: 300, width: '100%'}} <ListItem>
renderItem={({item}) => <Body>
<ListItem> <Text>
<Body> {item.name}
<Text> </Text>
{item.name} <Text note>
</Text> {item.version.replace('^', '')}
<Text note> </Text>
{item.version.replace('^', '')} </Body>
</Text> </ListItem>}
</Body> />
</ListItem>}
/>
</Container>
); );
} }
} }

View file

@ -2,11 +2,9 @@
import * as React from 'react'; import * as React from 'react';
import {FlatList, Linking, Platform, View} from 'react-native'; import {FlatList, Linking, Platform, View} from 'react-native';
import {Body, Button, Card, CardItem, Container, H1, Left, Right, Text, Thumbnail} from 'native-base'; import {Body, Button, Card, CardItem, Content, H1, Left, Right, Text, Thumbnail} from 'native-base';
import CustomHeader from "../../components/CustomHeader";
import i18n from "i18n-js"; import i18n from "i18n-js";
import appJson from '../../app'; import appJson from '../../app';
import packageJson from '../../package';
import {MaterialCommunityIcons} from "@expo/vector-icons"; import {MaterialCommunityIcons} from "@expo/vector-icons";
import AsyncStorageManager from "../../utils/AsyncStorageManager"; import AsyncStorageManager from "../../utils/AsyncStorageManager";
import {Modalize} from "react-native-modalize"; import {Modalize} from "react-native-modalize";
@ -169,7 +167,7 @@ export default class AboutScreen extends React.Component<Props, State> {
showChevron: true showChevron: true
}, },
{ {
onPressCallback: () => this.props.navigation.navigate('AboutDependenciesScreen', {data: packageJson.dependencies}), onPressCallback: () => this.props.navigation.navigate('AboutDependenciesScreen'),
icon: 'developer-board', icon: 'developer-board',
text: i18n.t('aboutScreen.libs'), text: i18n.t('aboutScreen.libs'),
showChevron: true showChevron: true
@ -391,11 +389,9 @@ export default class AboutScreen extends React.Component<Props, State> {
} }
render() { render() {
const nav = this.props.navigation;
return ( return (
<Container> <Content padder>
{this.getBugReportModal()} {this.getBugReportModal()}
<CustomHeader navigation={nav} title={i18n.t('screens.about')} hasBackButton={true}/>
<FlatList <FlatList
style={{padding: 5}} style={{padding: 5}}
data={this.dataOrder} data={this.dataOrder}
@ -403,7 +399,7 @@ export default class AboutScreen extends React.Component<Props, State> {
keyExtractor={(item) => item.id} keyExtractor={(item) => item.id}
renderItem={this.getMainCard} renderItem={this.getMainCard}
/> />
</Container> </Content>
); );
} }
} }

View file

@ -20,9 +20,7 @@ import {
Right, Right,
Text Text
} from "native-base"; } from "native-base";
import CustomHeader from "../components/CustomHeader";
import ThemeManager from '../utils/ThemeManager'; import ThemeManager from '../utils/ThemeManager';
import i18n from "i18n-js";
import {MaterialCommunityIcons} from "@expo/vector-icons"; import {MaterialCommunityIcons} from "@expo/vector-icons";
import {Alert, Clipboard, View} from "react-native"; import {Alert, Clipboard, View} from "react-native";
import AsyncStorageManager from "../utils/AsyncStorageManager"; import AsyncStorageManager from "../utils/AsyncStorageManager";
@ -150,7 +148,6 @@ export default class DebugScreen extends React.Component<Props, State> {
} }
render() { render() {
const nav = this.props.navigation;
return ( return (
<Container> <Container>
<Modalize <Modalize
@ -159,7 +156,6 @@ export default class DebugScreen extends React.Component<Props, State> {
modalStyle={{backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor}}> modalStyle={{backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor}}>
{this.getModalContent()} {this.getModalContent()}
</Modalize> </Modalize>
<CustomHeader navigation={nav} title={i18n.t('screens.debug')} hasBackButton={true}/>
<Content padder> <Content padder>
<Card> <Card>
<CardItem header> <CardItem header>

View file

@ -9,7 +9,6 @@ import Autolink from 'react-native-autolink';
import ThemeManager from "../utils/ThemeManager"; import ThemeManager from "../utils/ThemeManager";
import DashboardItem from "../components/DashboardItem"; import DashboardItem from "../components/DashboardItem";
import * as WebBrowser from 'expo-web-browser'; import * as WebBrowser from 'expo-web-browser';
import BaseContainer from "../components/BaseContainer";
import WebSectionList from "../components/WebSectionList"; import WebSectionList from "../components/WebSectionList";
// import DATA from "../dashboard_data.json"; // import DATA from "../dashboard_data.json";
@ -571,17 +570,13 @@ export default class HomeScreen extends React.Component<Props> {
render() { render() {
const nav = this.props.navigation; const nav = this.props.navigation;
return ( return (
<BaseContainer <WebSectionList
createDataset={this.createDataset}
navigation={nav} navigation={nav}
headerTitle={i18n.t('screens.home')}> refreshTime={REFRESH_TIME}
<WebSectionList fetchUrl={DATA_URL}
createDataset={this.createDataset} renderItem={this.getRenderItem}
navigation={nav} updateErrorText={i18n.t("homeScreen.listUpdateFail")}/>
refreshTime={REFRESH_TIME}
fetchUrl={DATA_URL}
renderItem={this.getRenderItem}
updateErrorText={i18n.t("homeScreen.listUpdateFail")}/>
</BaseContainer>
); );
} }
} }

View file

@ -3,7 +3,6 @@
import * as React from 'react'; import * as React from 'react';
import {Image} from 'react-native'; import {Image} from 'react-native';
import {Container, Content, H1, H3, View} from 'native-base'; import {Container, Content, H1, H3, View} from 'native-base';
import CustomHeader from "../components/CustomHeader";
import ThemeManager from "../utils/ThemeManager"; import ThemeManager from "../utils/ThemeManager";
import HTML from "react-native-render-html"; import HTML from "react-native-render-html";
import {Linking} from "expo"; import {Linking} from "expo";
@ -11,6 +10,7 @@ import PlanningEventManager from '../utils/PlanningEventManager';
type Props = { type Props = {
navigation: Object, navigation: Object,
route: Object
}; };
function openWebLink(event, link) { function openWebLink(event, link) {
@ -21,37 +21,33 @@ function openWebLink(event, link) {
* Class defining an about screen. This screen shows the user information about the app and it's author. * Class defining an about screen. This screen shows the user information about the app and it's author.
*/ */
export default class PlanningDisplayScreen extends React.Component<Props> { export default class PlanningDisplayScreen extends React.Component<Props> {
displayData = this.props.route.params['data'];
render() { render() {
// console.log("rendering planningDisplayScreen"); // console.log("rendering planningDisplayScreen");
const nav = this.props.navigation;
const displayData = nav.getParam('data', []);
return ( return (
<Container> <Container>
<CustomHeader
navigation={nav}
title={displayData.title}
subtitle={PlanningEventManager.getFormattedTime(displayData)}
hasBackButton={true}/>
<Content padder> <Content padder>
<H1> <H1>
{displayData.title} {this.displayData.title}
</H1> </H1>
<H3 style={{ <H3 style={{
marginTop: 10, marginTop: 10,
color: ThemeManager.getCurrentThemeVariables().listNoteColor color: ThemeManager.getCurrentThemeVariables().listNoteColor
}}> }}>
{PlanningEventManager.getFormattedTime(displayData)} {PlanningEventManager.getFormattedTime(this.displayData)}
</H3> </H3>
{displayData.logo !== null ? {this.displayData.logo !== null ?
<View style={{width: '100%', height: 300, marginTop: 20, marginBottom: 20}}> <View style={{width: '100%', height: 300, marginTop: 20, marginBottom: 20}}>
<Image style={{flex: 1, resizeMode: "contain"}} <Image style={{flex: 1, resizeMode: "contain"}}
source={{uri: displayData.logo}}/> source={{uri: this.displayData.logo}}/>
</View> </View>
: <View/>} : <View/>}
{displayData.description !== null ? {this.displayData.description !== null ?
// Surround description with div to allow text styling if the description is not html // Surround description with div to allow text styling if the description is not html
<HTML html={"<div>" + displayData.description + "</div>"} <HTML html={"<div>" + this.displayData.description + "</div>"}
tagsStyles={{ tagsStyles={{
p: { p: {
color: ThemeManager.getCurrentThemeVariables().textColor, color: ThemeManager.getCurrentThemeVariables().textColor,

View file

@ -5,7 +5,6 @@ import {BackHandler, Image} from 'react-native';
import {H3, Text, View} from 'native-base'; import {H3, Text, View} from 'native-base';
import i18n from "i18n-js"; import i18n from "i18n-js";
import ThemeManager from "../utils/ThemeManager"; import ThemeManager from "../utils/ThemeManager";
import BaseContainer from "../components/BaseContainer";
import {Agenda, LocaleConfig} from 'react-native-calendars'; import {Agenda, LocaleConfig} from 'react-native-calendars';
import Touchable from 'react-native-platform-touchable'; import Touchable from 'react-native-platform-touchable';
import WebDataManager from "../utils/WebDataManager"; import WebDataManager from "../utils/WebDataManager";
@ -61,6 +60,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
onAgendaRef: Function; onAgendaRef: Function;
onCalendarToggled: Function; onCalendarToggled: Function;
onBackButtonPressAndroid: Function; onBackButtonPressAndroid: Function;
currentDate = this.getCurrentDate();
constructor(props: any) { constructor(props: any) {
super(props); super(props);
@ -271,66 +271,62 @@ export default class PlanningScreen extends React.Component<Props, State> {
this.setState({calendarShowing: isCalendarOpened}); this.setState({calendarShowing: isCalendarOpened});
} }
currentDate = this.getCurrentDate();
render() { render() {
// console.log("rendering PlanningScreen"); // console.log("rendering PlanningScreen");
return ( return (
<BaseContainer navigation={this.props.navigation} headerTitle={i18n.t('screens.planning')}> <Agenda
<Agenda // the list of items that have to be displayed in agenda. If you want to render item as empty date
// the list of items that have to be displayed in agenda. If you want to render item as empty date // the value of date key kas to be an empty array []. If there exists no value for date key it is
// the value of date key kas to be an empty array []. If there exists no value for date key it is // considered that the date in question is not yet loaded
// considered that the date in question is not yet loaded items={this.state.agendaItems}
items={this.state.agendaItems} // initially selected day
// initially selected day selected={this.currentDate}
selected={this.currentDate} // Minimum date that can be selected, dates before minDate will be grayed out. Default = undefined
// Minimum date that can be selected, dates before minDate will be grayed out. Default = undefined minDate={this.currentDate}
minDate={this.currentDate} // Max amount of months allowed to scroll to the past. Default = 50
// Max amount of months allowed to scroll to the past. Default = 50 pastScrollRange={1}
pastScrollRange={1} // Max amount of months allowed to scroll to the future. Default = 50
// Max amount of months allowed to scroll to the future. Default = 50 futureScrollRange={AGENDA_MONTH_SPAN}
futureScrollRange={AGENDA_MONTH_SPAN} // If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the refreshing prop correctly.
// If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the refreshing prop correctly. onRefresh={this.onRefresh}
onRefresh={this.onRefresh} // callback that fires when the calendar is opened or closed
// callback that fires when the calendar is opened or closed onCalendarToggled={this.onCalendarToggled}
onCalendarToggled={this.onCalendarToggled} // Set this true while waiting for new data from a refresh
// Set this true while waiting for new data from a refresh refreshing={this.state.refreshing}
refreshing={this.state.refreshing} renderItem={this.getRenderItem}
renderItem={this.getRenderItem} renderEmptyDate={this.getRenderEmptyDate}
renderEmptyDate={this.getRenderEmptyDate} rowHasChanged={this.rowHasChanged}
rowHasChanged={this.rowHasChanged} // If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday.
// If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday. firstDay={1}
firstDay={1} // ref to this agenda in order to handle back button event
// ref to this agenda in order to handle back button event ref={this.onAgendaRef}
ref={this.onAgendaRef} // agenda theme
// agenda theme theme={{
theme={{ backgroundColor: ThemeManager.getCurrentThemeVariables().agendaBackgroundColor,
backgroundColor: ThemeManager.getCurrentThemeVariables().agendaBackgroundColor, calendarBackground: ThemeManager.getCurrentThemeVariables().containerBgColor,
calendarBackground: ThemeManager.getCurrentThemeVariables().containerBgColor, textSectionTitleColor: ThemeManager.getCurrentThemeVariables().listNoteColor,
textSectionTitleColor: ThemeManager.getCurrentThemeVariables().listNoteColor, selectedDayBackgroundColor: ThemeManager.getCurrentThemeVariables().brandPrimary,
selectedDayBackgroundColor: ThemeManager.getCurrentThemeVariables().brandPrimary, selectedDayTextColor: '#ffffff',
selectedDayTextColor: '#ffffff', todayTextColor: ThemeManager.getCurrentThemeVariables().brandPrimary,
todayTextColor: ThemeManager.getCurrentThemeVariables().brandPrimary, dayTextColor: ThemeManager.getCurrentThemeVariables().textColor,
dayTextColor: ThemeManager.getCurrentThemeVariables().textColor, textDisabledColor: ThemeManager.getCurrentThemeVariables().textDisabledColor,
textDisabledColor: ThemeManager.getCurrentThemeVariables().textDisabledColor, dotColor: ThemeManager.getCurrentThemeVariables().brandPrimary,
dotColor: ThemeManager.getCurrentThemeVariables().brandPrimary, selectedDotColor: '#ffffff',
selectedDotColor: '#ffffff', arrowColor: 'orange',
arrowColor: 'orange', monthTextColor: ThemeManager.getCurrentThemeVariables().brandPrimary,
monthTextColor: ThemeManager.getCurrentThemeVariables().brandPrimary, indicatorColor: ThemeManager.getCurrentThemeVariables().brandPrimary,
indicatorColor: ThemeManager.getCurrentThemeVariables().brandPrimary, textDayFontWeight: '300',
textDayFontWeight: '300', textMonthFontWeight: 'bold',
textMonthFontWeight: 'bold', textDayHeaderFontWeight: '300',
textDayHeaderFontWeight: '300', textDayFontSize: 16,
textDayFontSize: 16, textMonthFontSize: 16,
textMonthFontSize: 16, textDayHeaderFontSize: 16,
textDayHeaderFontSize: 16, agendaDayTextColor: ThemeManager.getCurrentThemeVariables().listNoteColor,
agendaDayTextColor: ThemeManager.getCurrentThemeVariables().listNoteColor, agendaDayNumColor: ThemeManager.getCurrentThemeVariables().listNoteColor,
agendaDayNumColor: ThemeManager.getCurrentThemeVariables().listNoteColor, agendaTodayColor: ThemeManager.getCurrentThemeVariables().brandPrimary,
agendaTodayColor: ThemeManager.getCurrentThemeVariables().brandPrimary, agendaKnobColor: ThemeManager.getCurrentThemeVariables().brandPrimary,
agendaKnobColor: ThemeManager.getCurrentThemeVariables().brandPrimary, }}
}} />
/>
</BaseContainer>
); );
} }
} }

View file

@ -3,7 +3,6 @@
import * as React from 'react'; import * as React from 'react';
import {Image, View} from 'react-native'; import {Image, View} from 'react-native';
import {Card, CardItem, Container, Content, H2, Left, Text} from 'native-base'; import {Card, CardItem, Container, Content, H2, Left, Text} from 'native-base';
import CustomHeader from "../../components/CustomHeader";
import i18n from "i18n-js"; import i18n from "i18n-js";
import {MaterialCommunityIcons} from "@expo/vector-icons"; import {MaterialCommunityIcons} from "@expo/vector-icons";

View file

@ -1,8 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import {Body, Container, Content, H1, H3, Input, Item, Left, ListItem, Right, Text, Thumbnail} from 'native-base'; import {Body, Content, H1, H3, Input, Item, Left, ListItem, Right, Text, Thumbnail} from 'native-base';
import CustomHeader from "../../components/CustomHeader";
import {FlatList, Image, Platform, View} from "react-native"; import {FlatList, Image, Platform, View} from "react-native";
import Touchable from 'react-native-platform-touchable'; import Touchable from 'react-native-platform-touchable';
import Menu, {MenuItem} from 'react-native-material-menu'; import Menu, {MenuItem} from 'react-native-material-menu';
@ -387,7 +386,7 @@ export default class ProximoListScreen extends React.Component<Props, State> {
// console.log("rendering ProximoListScreen"); // console.log("rendering ProximoListScreen");
const nav = this.props.navigation; const nav = this.props.navigation;
return ( return (
<Container> <View>
<Modalize ref={this.modalRef} <Modalize ref={this.modalRef}
adjustToContentHeight adjustToContentHeight
modalStyle={{backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor}}> modalStyle={{backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor}}>
@ -400,7 +399,7 @@ export default class ProximoListScreen extends React.Component<Props, State> {
style={{minHeight: 300, width: '100%'}} style={{minHeight: 300, width: '100%'}}
renderItem={this.renderItem} renderItem={this.renderItem}
/> />
</Container> </View>
); );
} }
} }

View file

@ -2,7 +2,7 @@
import * as React from 'react'; import * as React from 'react';
import {Platform, View} from 'react-native' import {Platform, View} from 'react-native'
import {Body, Left, ListItem, Right, Text, Container} from 'native-base'; import {Body, Left, ListItem, Right, Text} from 'native-base';
import i18n from "i18n-js"; import i18n from "i18n-js";
import {MaterialCommunityIcons} from "@expo/vector-icons"; import {MaterialCommunityIcons} from "@expo/vector-icons";
import ThemeManager from "../../utils/ThemeManager"; import ThemeManager from "../../utils/ThemeManager";
@ -40,14 +40,6 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
this.createDataset = this.createDataset.bind(this); this.createDataset = this.createDataset.bind(this);
} }
componentDidMount() {
const button = this.getRightButton.bind(this);
this.props.navigation.setOptions({
headerRight: button
,
});
}
static sortFinalData(a: Object, b: Object) { static sortFinalData(a: Object, b: Object) {
let str1 = a.type.name.toLowerCase(); let str1 = a.type.name.toLowerCase();
let str2 = b.type.name.toLowerCase(); let str2 = b.type.name.toLowerCase();
@ -66,6 +58,13 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
return 0; return 0;
} }
componentDidMount() {
const rightButton = this.getRightButton.bind(this);
this.props.navigation.setOptions({
headerRight: rightButton,
});
}
getKeyExtractor(item: Object) { getKeyExtractor(item: Object) {
return item !== undefined ? item.type['id'] : undefined; return item !== undefined ? item.type['id'] : undefined;
} }
@ -180,6 +179,7 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
); );
} }
getRenderItem({item}: Object) { getRenderItem({item}: Object) {
let dataToSend = { let dataToSend = {
shouldFocusSearchBar: false, shouldFocusSearchBar: false,
@ -223,15 +223,13 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
render() { render() {
const nav = this.props.navigation; const nav = this.props.navigation;
return ( return (
<Container> <WebSectionList
<WebSectionList createDataset={this.createDataset}
createDataset={this.createDataset} navigation={nav}
navigation={nav} refreshTime={0}
refreshTime={0} fetchUrl={DATA_URL}
fetchUrl={DATA_URL} renderItem={this.getRenderItem}
renderItem={this.getRenderItem} updateErrorText={i18n.t("homeScreen.listUpdateFail")}/>
updateErrorText={i18n.t("homeScreen.listUpdateFail")}/>
</Container>
); );
} }
} }

View file

@ -2,8 +2,7 @@
import * as React from 'react'; import * as React from 'react';
import {Image, View} from 'react-native'; import {Image, View} from 'react-native';
import {Body, Card, CardItem, Container, Content, H2, H3, Left, Tab, TabHeading, Tabs, Text} from 'native-base'; import {Body, Card, CardItem, Content, H2, H3, Left, Tab, TabHeading, Tabs, Text} from 'native-base';
import CustomHeader from "../../components/CustomHeader";
import i18n from "i18n-js"; import i18n from "i18n-js";
import {MaterialCommunityIcons} from "@expo/vector-icons"; import {MaterialCommunityIcons} from "@expo/vector-icons";
import ThemeManager from "../../utils/ThemeManager"; import ThemeManager from "../../utils/ThemeManager";
@ -18,140 +17,130 @@ type Props = {
export default class ProxiwashAboutScreen extends React.Component<Props> { export default class ProxiwashAboutScreen extends React.Component<Props> {
render() { render() {
const nav = this.props.navigation;
return ( return (
<Container> <Tabs>
<CustomHeader <Tab
navigation={nav} title={i18n.t('screens.proxiwash')} heading={
hasBackButton={true} <TabHeading>
hasTabs={true}/> <MaterialCommunityIcons
<Tabs name={'information'}
tabContainerStyle={{ color={ThemeManager.getCurrentThemeVariables().tabIconColor}
elevation: 0, // Fix for android shadow size={20}
}}> />
<Tab <Text>{i18n.t('proxiwashScreen.informationTab')}</Text>
heading={ </TabHeading>
<TabHeading> }
<MaterialCommunityIcons key={1}
name={'information'} style={{backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor}}>
color={ThemeManager.getCurrentThemeVariables().tabIconColor} <Content padder>
size={20} <View style={{
/> width: '100%',
<Text>{i18n.t('proxiwashScreen.informationTab')}</Text> height: 100,
</TabHeading> marginTop: 20,
} marginBottom: 20,
key={1} justifyContent: 'center',
style={{backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor}}> alignItems: 'center'
<Content padder> }}>
<View style={{ <Image
width: '100%', source={require('../../assets/proxiwash-logo.png')}
height: 100, style={{flex: 1, resizeMode: "contain"}}
marginTop: 20, resizeMode="contain"/>
marginBottom: 20, </View>
justifyContent: 'center', <Text>{i18n.t('proxiwashScreen.description')}</Text>
alignItems: 'center' <Card>
}}> <CardItem>
<Image <Left>
source={require('../../assets/proxiwash-logo.png')} <MaterialCommunityIcons
style={{flex: 1, resizeMode: "contain"}} name={'tumble-dryer'}
resizeMode="contain"/> size={26}/>
</View> <H2>{i18n.t('proxiwashScreen.dryer')}</H2>
<Text>{i18n.t('proxiwashScreen.description')}</Text> </Left>
<Card> </CardItem>
<CardItem> <CardItem>
<Left> <Body>
<MaterialCommunityIcons <H3>{i18n.t('proxiwashScreen.procedure')}</H3>
name={'tumble-dryer'} <Text>{i18n.t('proxiwashScreen.dryerProcedure')}</Text>
size={26}/> </Body>
<H2>{i18n.t('proxiwashScreen.dryer')}</H2> </CardItem>
</Left> <CardItem>
</CardItem> <Body>
<CardItem> <H3>{i18n.t('proxiwashScreen.tips')}</H3>
<Body> <Text>{i18n.t('proxiwashScreen.dryerTips')}</Text>
<H3>{i18n.t('proxiwashScreen.procedure')}</H3> </Body>
<Text>{i18n.t('proxiwashScreen.dryerProcedure')}</Text> </CardItem>
</Body> </Card>
</CardItem> <Card>
<CardItem> <CardItem>
<Body> <Left>
<H3>{i18n.t('proxiwashScreen.tips')}</H3> <MaterialCommunityIcons
<Text>{i18n.t('proxiwashScreen.dryerTips')}</Text> name={'washing-machine'}
</Body> size={26}/>
</CardItem> <H2>{i18n.t('proxiwashScreen.washer')}</H2>
</Card> </Left>
<Card> </CardItem>
<CardItem> <CardItem>
<Left> <Body>
<MaterialCommunityIcons <H3>{i18n.t('proxiwashScreen.procedure')}</H3>
name={'washing-machine'} <Text>{i18n.t('proxiwashScreen.washerProcedure')}</Text>
size={26}/> </Body>
<H2>{i18n.t('proxiwashScreen.washer')}</H2> </CardItem>
</Left> <CardItem>
</CardItem> <Body>
<CardItem> <H3>{i18n.t('proxiwashScreen.tips')}</H3>
<Body> <Text>{i18n.t('proxiwashScreen.washerTips')}</Text>
<H3>{i18n.t('proxiwashScreen.procedure')}</H3> </Body>
<Text>{i18n.t('proxiwashScreen.washerProcedure')}</Text> </CardItem>
</Body> </Card>
</CardItem> </Content>
<CardItem> </Tab>
<Body> <Tab
<H3>{i18n.t('proxiwashScreen.tips')}</H3> heading={
<Text>{i18n.t('proxiwashScreen.washerTips')}</Text> <TabHeading>
</Body> <MaterialCommunityIcons
</CardItem> name={'cash'}
</Card> color={ThemeManager.getCurrentThemeVariables().tabIconColor}
</Content> size={20}
</Tab> />
<Tab <Text>{i18n.t('proxiwashScreen.paymentTab')}</Text>
heading={ </TabHeading>
<TabHeading> }
<MaterialCommunityIcons key={2}
name={'cash'} style={{backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor}}>
color={ThemeManager.getCurrentThemeVariables().tabIconColor} <Content padder>
size={20} <Card>
/> <CardItem>
<Text>{i18n.t('proxiwashScreen.paymentTab')}</Text> <Left>
</TabHeading> <MaterialCommunityIcons
} name={'coins'}
key={2} size={26}/>
style={{backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor}}> <H2>{i18n.t('proxiwashScreen.tariffs')}</H2>
<Content padder> </Left>
<Card> </CardItem>
<CardItem> <CardItem>
<Left> <Body>
<MaterialCommunityIcons <Text>{i18n.t('proxiwashScreen.washersTariff')}</Text>
name={'coins'} <Text>{i18n.t('proxiwashScreen.dryersTariff')}</Text>
size={26}/> </Body>
<H2>{i18n.t('proxiwashScreen.tariffs')}</H2> </CardItem>
</Left> </Card>
</CardItem> <Card>
<CardItem> <CardItem>
<Body> <Left>
<Text>{i18n.t('proxiwashScreen.washersTariff')}</Text> <MaterialCommunityIcons
<Text>{i18n.t('proxiwashScreen.dryersTariff')}</Text> name={'cash'}
</Body> size={26}/>
</CardItem> <H2>{i18n.t('proxiwashScreen.paymentMethods')}</H2>
</Card> </Left>
<Card> </CardItem>
<CardItem> <CardItem>
<Left> <Body>
<MaterialCommunityIcons <Text>{i18n.t('proxiwashScreen.paymentMethodsDescription')}</Text>
name={'cash'} </Body>
size={26}/> </CardItem>
<H2>{i18n.t('proxiwashScreen.paymentMethods')}</H2> </Card>
</Left> </Content>
</CardItem> </Tab>
<CardItem> </Tabs>
<Body>
<Text>{i18n.t('proxiwashScreen.paymentMethodsDescription')}</Text>
</Body>
</CardItem>
</Card>
</Content>
</Tab>
</Tabs>
</Container>
); );
} }
} }

View file

@ -12,7 +12,6 @@ import PlatformTouchable from "react-native-platform-touchable";
import Touchable from "react-native-platform-touchable"; import Touchable from "react-native-platform-touchable";
import AsyncStorageManager from "../../utils/AsyncStorageManager"; import AsyncStorageManager from "../../utils/AsyncStorageManager";
import * as Expo from "expo"; import * as Expo from "expo";
import BaseContainer from "../../components/BaseContainer";
const DATA_URL = "https://etud.insa-toulouse.fr/~amicale_app/washinsa/washinsa.json"; const DATA_URL = "https://etud.insa-toulouse.fr/~amicale_app/washinsa/washinsa.json";
@ -102,6 +101,10 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
* Setup notification channel for android and add listeners to detect notifications fired * Setup notification channel for android and add listeners to detect notifications fired
*/ */
componentDidMount() { componentDidMount() {
const rightButton = this.getRightButton.bind(this);
this.props.navigation.setOptions({
headerRight: rightButton,
});
if (AsyncStorageManager.getInstance().preferences.expoToken.current !== '') { if (AsyncStorageManager.getInstance().preferences.expoToken.current !== '') {
// Get latest watchlist from server // Get latest watchlist from server
NotificationsManager.getMachineNotificationWatchlist((fetchedList) => { NotificationsManager.getMachineNotificationWatchlist((fetchedList) => {
@ -283,10 +286,13 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
this.props.navigation.navigate('ProxiwashAboutScreen'); this.props.navigation.navigate('ProxiwashAboutScreen');
} }
getRightButton(): * { getRightButton() {
return ( return (
<Touchable <Touchable
style={{padding: 6}} style={{
padding: 6,
marginRight: 10
}}
onPress={this.onAboutPress}> onPress={this.onAboutPress}>
<MaterialCommunityIcons <MaterialCommunityIcons
color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"} color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
@ -299,18 +305,13 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
render() { render() {
const nav = this.props.navigation; const nav = this.props.navigation;
return ( return (
<BaseContainer <WebSectionList
createDataset={this.createDataset}
navigation={nav} navigation={nav}
headerTitle={i18n.t('screens.proxiwash')} refreshTime={REFRESH_TIME}
headerRightButton={this.getRightButton()}> fetchUrl={DATA_URL}
<WebSectionList renderItem={this.getRenderItem}
createDataset={this.createDataset} updateErrorText={i18n.t("proxiwashScreen.listUpdateFail")}/>
navigation={nav}
refreshTime={REFRESH_TIME}
fetchUrl={DATA_URL}
renderItem={this.getRenderItem}
updateErrorText={i18n.t("proxiwashScreen.listUpdateFail")}/>
</BaseContainer>
); );
} }

View file

@ -5,7 +5,6 @@ import {View} from 'react-native';
import {Card, CardItem, H2, H3, Text} from 'native-base'; import {Card, CardItem, H2, H3, Text} from 'native-base';
import ThemeManager from "../utils/ThemeManager"; import ThemeManager from "../utils/ThemeManager";
import i18n from "i18n-js"; import i18n from "i18n-js";
import BaseContainer from "../components/BaseContainer";
import WebSectionList from "../components/WebSectionList"; import WebSectionList from "../components/WebSectionList";
const DATA_URL = "https://etud.insa-toulouse.fr/~amicale_app/menu/menu_data.json"; const DATA_URL = "https://etud.insa-toulouse.fr/~amicale_app/menu/menu_data.json";
@ -95,7 +94,6 @@ export default class SelfMenuScreen extends React.Component<Props> {
} }
getRenderSectionHeader({section}: Object) { getRenderSectionHeader({section}: Object) {
let title = "";
return ( return (
<Card style={{ <Card style={{
marginLeft: 10, marginLeft: 10,
@ -164,20 +162,15 @@ export default class SelfMenuScreen extends React.Component<Props> {
render() { render() {
const nav = this.props.navigation; const nav = this.props.navigation;
return ( return (
<BaseContainer <WebSectionList
createDataset={this.createDataset}
navigation={nav} navigation={nav}
headerTitle={i18n.t('screens.menuSelf')} refreshTime={0}
hasBackButton={true}> fetchUrl={DATA_URL}
<WebSectionList renderItem={this.getRenderItem}
createDataset={this.createDataset} renderSectionHeader={this.getRenderSectionHeader}
navigation={nav} updateErrorText={i18n.t("homeScreen.listUpdateFail")}
refreshTime={0} stickyHeader={true}/>
fetchUrl={DATA_URL}
renderItem={this.getRenderItem}
renderSectionHeader={this.getRenderSectionHeader}
updateErrorText={i18n.t("homeScreen.listUpdateFail")}
stickyHeader={true}/>
</BaseContainer>
); );
} }
} }

View file

@ -1,21 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import { import {Body, Card, CardItem, CheckBox, Content, Left, List, ListItem, Picker, Right, Text,} from "native-base";
Body,
Card,
CardItem,
CheckBox,
Container,
Content,
Left,
List,
ListItem,
Picker,
Right,
Text,
} from "native-base";
import CustomHeader from "../components/CustomHeader";
import ThemeManager from '../utils/ThemeManager'; import ThemeManager from '../utils/ThemeManager';
import i18n from "i18n-js"; import i18n from "i18n-js";
import {NavigationActions, StackActions} from "@react-navigation/native"; import {NavigationActions, StackActions} from "@react-navigation/native";
@ -228,30 +214,26 @@ export default class SettingsScreen extends React.Component<Props, State> {
} }
render() { render() {
const nav = this.props.navigation;
return ( return (
<Container> <Content padder>
<CustomHeader navigation={nav} title={i18n.t('screens.settings')} hasBackButton={true}/> <Card>
<Content padder> <CardItem header>
<Card> <Text>{i18n.t('settingsScreen.generalCard')}</Text>
<CardItem header> </CardItem>
<Text>{i18n.t('settingsScreen.generalCard')}</Text> <List>
</CardItem> {this.getToggleItem(this.onToggleNightMode, 'theme-light-dark', i18n.t('settingsScreen.nightMode'), i18n.t('settingsScreen.nightModeSub'))}
<List> {SettingsScreen.getGeneralItem(this.getStartScreenPicker(), 'power', i18n.t('settingsScreen.startScreen'), i18n.t('settingsScreen.startScreenSub'))}
{this.getToggleItem(this.onToggleNightMode, 'theme-light-dark', i18n.t('settingsScreen.nightMode'), i18n.t('settingsScreen.nightModeSub'))} </List>
{SettingsScreen.getGeneralItem(this.getStartScreenPicker(), 'power', i18n.t('settingsScreen.startScreen'), i18n.t('settingsScreen.startScreenSub'))} </Card>
</List> <Card>
</Card> <CardItem header>
<Card> <Text>Proxiwash</Text>
<CardItem header> </CardItem>
<Text>Proxiwash</Text> <List>
</CardItem> {SettingsScreen.getGeneralItem(this.getProxiwashNotifPicker(), 'washing-machine', i18n.t('settingsScreen.proxiwashNotifReminder'), i18n.t('settingsScreen.proxiwashNotifReminderSub'))}
<List> </List>
{SettingsScreen.getGeneralItem(this.getProxiwashNotifPicker(), 'washing-machine', i18n.t('settingsScreen.proxiwashNotifReminder'), i18n.t('settingsScreen.proxiwashNotifReminderSub'))} </Card>
</List> </Content>
</Card>
</Content>
</Container>
); );
} }

View file

@ -11,9 +11,7 @@ type Props = {
const ROOM_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 PC_URL = 'http://planex.insa-toulouse.fr/sallesInfo.php';
const BIB_URL = 'https://bibbox.insa-toulouse.fr/';
const CUSTOM_CSS_GENERAL = 'https://etud.insa-toulouse.fr/~amicale_app/custom_css/rooms/customMobile.css'; const CUSTOM_CSS_GENERAL = 'https://etud.insa-toulouse.fr/~amicale_app/custom_css/rooms/customMobile.css';
const CUSTOM_CSS_Bib = 'https://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.
@ -32,17 +30,6 @@ export default class AvailableRoomScreen extends React.Component<Props> {
'let header = $(".table tbody tr:first");' + 'let header = $(".table tbody tr:first");' +
'$("table").prepend("<thead></thead>");true;' + // Fix for crash on ios '$("table").prepend("<thead></thead>");true;' + // Fix for crash on ios
'$("thead").append(header);true;'; '$("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"/>\';' +
'if ($(".hero-unit-form").length > 0 && $("#customBackButton").length === 0)' +
'$(".hero-unit-form").append("' +
'<div style=\'width: 100%; display: flex\'>' +
'<a style=\'margin: auto\' href=\'' + BIB_URL + '\'>' +
'<button id=\'customBackButton\' class=\'btn btn-primary\'>Retour</button>' +
'</a>' +
'</div>");true;';
} }
render() { render() {
@ -63,12 +50,6 @@ export default class AvailableRoomScreen extends React.Component<Props> {
name: i18n.t('availableRoomScreen.computerRoom'), name: i18n.t('availableRoomScreen.computerRoom'),
customJS: this.customInjectedJS 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')}

View file

@ -0,0 +1,66 @@
// @flow
import * as React from 'react';
import WebViewScreen from "../../components/WebViewScreen";
import i18n from "i18n-js";
type Props = {
navigation: Object,
}
const BIB_URL = 'https://bibbox.insa-toulouse.fr/';
const CUSTOM_CSS_GENERAL = 'https://etud.insa-toulouse.fr/~amicale_app/custom_css/rooms/customMobile.css';
const CUSTOM_CSS_Bib = 'https://etud.insa-toulouse.fr/~amicale_app/custom_css/rooms/customBibMobile.css';
/**
* Class defining the app's planex screen.
* This screen uses a webview to render the planex page
*/
export default class AvailableRoomScreen extends React.Component<Props> {
customInjectedJS: string;
customBibInjectedJS: string;
constructor() {
super();
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"/>\';' +
'if ($(".hero-unit-form").length > 0 && $("#customBackButton").length === 0)' +
'$(".hero-unit-form").append("' +
'<div style=\'width: 100%; display: flex\'>' +
'<a style=\'margin: auto\' href=\'' + BIB_URL + '\'>' +
'<button id=\'customBackButton\' class=\'btn btn-primary\'>Retour</button>' +
'</a>' +
'</div>");true;';
}
render() {
const nav = this.props.navigation;
return (
<WebViewScreen
navigation={nav}
data={[
{
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}
hasFooter={false}/>
);
}
}