Removed unused libs and improved style responsiveness

This commit is contained in:
keplyx 2020-03-07 11:49:32 +01:00
parent 38ada0c027
commit 8d914c97f5
27 changed files with 439 additions and 407 deletions

14
App.js
View file

@ -3,7 +3,6 @@
import * as React from 'react';
import {Platform, StatusBar} from 'react-native';
import LocaleManager from './utils/LocaleManager';
import * as Font from 'expo-font';
import AsyncStorageManager from "./utils/AsyncStorageManager";
import CustomIntroSlider from "./components/CustomIntroSlider";
import {SplashScreen} from 'expo';
@ -23,17 +22,6 @@ type State = {
currentTheme: ?Object,
};
const MyTheme = {
dark: false,
colors: {
primary: 'rgb(255, 45, 85)',
background: 'rgb(242, 242, 242)',
card: 'rgb(255, 255, 255)',
text: 'rgb(28, 28, 30)',
border: 'rgb(199, 199, 204)',
},
};
const Stack = createStackNavigator();
export default class App extends React.Component<Props, State> {
@ -54,7 +42,7 @@ export default class App extends React.Component<Props, State> {
}
/**
* Updates the theme and clears the cache to force reloading the app colors. Need to edit shoutem theme for ti to work
* Updates the theme
*/
updateTheme() {
this.setState({

View file

@ -0,0 +1,40 @@
import * as React from 'react';
import {withTheme} from 'react-native-paper';
import {Agenda} from "react-native-calendars";
function CustomAgenda(props) {
const { colors } = props.theme;
return (
<Agenda
{...props}
ref={props.onRef}
theme={{
backgroundColor: colors.agendaBackgroundColor,
calendarBackground: colors.background,
textSectionTitleColor: colors.agendaDayTextColor,
selectedDayBackgroundColor: colors.primary,
selectedDayTextColor: '#ffffff',
todayTextColor: colors.primary,
dayTextColor: colors.text,
textDisabledColor: colors.agendaDayTextColor,
dotColor: colors.primary,
selectedDotColor: '#ffffff',
arrowColor: 'orange',
monthTextColor: colors.primary,
indicatorColor: colors.primary,
textDayFontWeight: '300',
textMonthFontWeight: 'bold',
textDayHeaderFontWeight: '300',
textDayFontSize: 16,
textMonthFontSize: 16,
textDayHeaderFontSize: 16,
agendaDayTextColor: colors.agendaDayTextColor,
agendaDayNumColor: colors.agendaDayTextColor,
agendaTodayColor: colors.primary,
agendaKnobColor: colors.primary,
}}
/>
);
}
export default withTheme(CustomAgenda);

View file

@ -28,12 +28,6 @@ export default class DashboardItem extends React.Component<Props> {
displayEvent: undefined,
};
shouldComponentUpdate(nextProps: Props): boolean {
return nextProps.isAvailable !== this.props.isAvailable ||
nextProps.subtitle !== this.props.subtitle;
}
/**
* Convert the date string given by in the event list json to a date object
* @param dateString

View file

@ -0,0 +1,41 @@
import * as React from 'react';
import {ActivityIndicator, Subheading, withTheme} from 'react-native-paper';
import {View} from "react-native";
import {MaterialCommunityIcons} from "@expo/vector-icons";
function EmptyWebSectionListItem(props) {
const { colors } = props.theme;
return (
<View>
<View style={{
justifyContent: 'center',
alignItems: 'center',
width: '100%',
height: 100,
marginBottom: 20
}}>
{props.refreshing ?
<ActivityIndicator
animating={true}
size={'large'}
color={colors.primary}/>
:
<MaterialCommunityIcons
name={props.icon}
size={100}
color={colors.textDisabled}/>}
</View>
<Subheading style={{
textAlign: 'center',
marginRight: 20,
marginLeft: 20,
color: colors.textDisabled
}}>
{props.text}
</Subheading>
</View>
);
}
export default withTheme(EmptyWebSectionListItem);

42
components/FeedItem.js Normal file
View file

@ -0,0 +1,42 @@
import * as React from 'react';
import {Avatar, Button, Card, withTheme} from 'react-native-paper';
import {TouchableOpacity, View} from "react-native";
import Autolink from "react-native-autolink";
import i18n from "i18n-js";
const ICON_AMICALE = require('../assets/amicale.png');
function FeedItem(props) {
const {colors} = props.theme;
return (
<Card style={{margin: 5}}>
<Card.Title
title={props.title}
subtitle={props.subtitle}
left={props => <Avatar.Image size={48} source={ICON_AMICALE}
style={{backgroundColor: 'transparent'}}/>}
/>
{props.full_picture !== '' && props.full_picture !== undefined ?
<TouchableOpacity onPress={props.onImagePress}>
<Card.Cover source={{uri: props.full_picture}}/>
</TouchableOpacity> : <View/>}
<Card.Content>
{props.message !== undefined ?
<Autolink
text={props.message}
hashtag="facebook"
style={{color: colors.text}}
/> : <View/>
}
</Card.Content>
<Card.Actions>
<Button
color={'#57aeff'}
onPress={props.onOutLinkPress}
icon={'facebook'}>{i18n.t('homeScreen.dashboard.seeMore')}</Button>
</Card.Actions>
</Card>
);
}
export default withTheme(FeedItem);

View file

@ -0,0 +1,16 @@
import * as React from 'react';
import {IconButton, withTheme} from 'react-native-paper';
function HeaderButton(props) {
const { colors } = props.theme;
return (
<IconButton
icon={props.icon}
size={26}
color={colors.text}
onPress={props.onPress}
/>
);
}
export default withTheme(HeaderButton);

View file

@ -0,0 +1,66 @@
import * as React from 'react';
import {Divider, List, Text, withTheme} from 'react-native-paper';
import {View} from "react-native";
import ProxiwashConstants from "../constants/ProxiwashConstants";
function ProxiwashListItem(props) {
const {colors} = props.theme;
let stateColors = {};
stateColors[ProxiwashConstants.machineStates.TERMINE] = colors.proxiwashFinishedColor;
stateColors[ProxiwashConstants.machineStates.DISPONIBLE] = colors.proxiwashReadyColor;
stateColors[ProxiwashConstants.machineStates["EN COURS"]] = colors.proxiwashRunningColor;
stateColors[ProxiwashConstants.machineStates.HS] = colors.proxiwashBrokenColor;
stateColors[ProxiwashConstants.machineStates.ERREUR] = colors.proxiwashErrorColor;
const icon = (
props.isWatched ?
<List.Icon icon={'bell-ring'} color={colors.primary}/> :
<List.Icon icon={props.isDryer ? 'tumble-dryer' : 'washing-machine'}/>
);
return (
<View style={{
backgroundColor:
ProxiwashConstants.machineStates[props.state] === ProxiwashConstants.machineStates["EN COURS"] ?
colors.proxiwashRunningBgColor :
colors.background
}}>
<View style={{
height: '100%',
position: 'absolute',
left: 0,
width: props.progress,
backgroundColor: stateColors[ProxiwashConstants.machineStates[props.state]]
}}/>
<List.Item
title={props.title}
description={props.description}
onPress={props.onPress}
style={{
backgroundColor: 'transparent',
height: 64
}}
left={() => icon}
right={() => (
<View style={{flexDirection: 'row'}}>
<View style={{
justifyContent: 'center',
}}>
<Text style={
ProxiwashConstants.machineStates[props.state] === ProxiwashConstants.machineStates.TERMINE ?
{fontWeight: 'bold',} : {}}
>
{props.statusText}
</Text>
</View>
<List.Icon
color={colors.text}
icon={props.statusIcon}
/>
</View>)}
/>
<Divider/>
</View>
);
}
export default withTheme(ProxiwashListItem);

View file

@ -6,7 +6,7 @@ import i18n from "i18n-js";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import ThemeManager from "../utils/ThemeManager";
import * as WebBrowser from 'expo-web-browser';
import {List} from 'react-native-paper';
import SidebarDivider from "./SidebarDivider";
import {DrawerItem} from '@react-navigation/drawer';
const deviceWidth = Dimensions.get("window").width;
@ -143,6 +143,7 @@ export default class SideBar extends React.Component<Props, State> {
getRenderItem({item}: Object) {
console.log("rendering SideBar Item");
const onListItemPress = this.onListItemPress.bind(this, item);
if (item.icon !== undefined) {
return (
@ -151,7 +152,6 @@ export default class SideBar extends React.Component<Props, State> {
focused={false}
icon={({color, size}) =>
<MaterialCommunityIcons color={color} size={size} name={item.icon}/>}
selected={this.state.active === item.route}
onPress={onListItemPress}
style={{
marginLeft: 0,
@ -163,10 +163,7 @@ export default class SideBar extends React.Component<Props, State> {
);
} else {
return (
<List.Item
title={item.name}
style={{backgroundColor: ThemeManager.getCurrentThemeVariables().dividerBackground}}
/>
<SidebarDivider title={item.name}/>
);
}

View file

@ -0,0 +1,23 @@
import * as React from 'react';
import { withTheme } from 'react-native-paper';
import {DrawerItem} from "@react-navigation/drawer";
function SidebarDivider(props) {
const { colors } = props.theme;
return (
<DrawerItem
label={props.title}
focused={false}
onPress={undefined}
style={{
marginLeft: 0,
marginRight: 0,
padding: 0,
borderRadius: 0,
backgroundColor: colors.dividerBackground
}}
/>
);
}
export default withTheme(SidebarDivider);

View file

@ -0,0 +1,55 @@
import * as React from 'react';
import {Card, Text, Title, withTheme} from 'react-native-paper';
import {View} from "react-native";
import {MaterialCommunityIcons} from "@expo/vector-icons";
function SquareDashboardItem(props) {
const { colors } = props.theme;
return (
<Card
style={{
width: '48%',
marginTop: 10,
marginRight: props.isLeft ? '4%': 0,
overflow: 'hidden',
}}
onPress={props.clickAction}>
<Card.Content>
<View style={{marginLeft: 'auto', marginRight: 'auto'}}>
<MaterialCommunityIcons
name={props.icon}
color={
props.isAvailable ?
props.color :
colors.textDisabled
}
size={50}/>
</View>
<View style={{
width: '100%',
}}>
<Title style={{
color: props.isAvailable ?
colors.text :
colors.textDisabled,
textAlign: 'center',
width: '100%',
}}>
{props.title}
</Title>
<Text style={{
color: props.isAvailable ?
colors.text :
colors.textDisabled,
textAlign: 'center',
width: '100%',
}}>
{props.subtitle}
</Text>
</View>
</Card.Content>
</Card>
);
}
export default withTheme(SquareDashboardItem);

View file

@ -1,12 +1,11 @@
// @flow
import * as React from 'react';
import ThemeManager from '../utils/ThemeManager';
import WebDataManager from "../utils/WebDataManager";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import i18n from "i18n-js";
import {ActivityIndicator, Snackbar, Subheading} from 'react-native-paper';
import {Snackbar} from 'react-native-paper';
import {RefreshControl, SectionList, View} from "react-native";
import EmptyWebSectionListItem from "./EmptyWebSectionListItem";
type Props = {
navigation: Object,
@ -145,35 +144,12 @@ export default class WebSectionList extends React.Component<Props, State> {
getEmptyRenderItem({item}: Object) {
return (
<View>
<View style={{
justifyContent: 'center',
alignItems: 'center',
width: '100%',
height: 100,
marginBottom: 20
}}>
{this.state.refreshing ?
<ActivityIndicator
animating={true}
size={'large'}
color={ThemeManager.getCurrentThemeVariables().primary}/>
:
<MaterialCommunityIcons
name={item.icon}
size={100}
color={ThemeManager.getCurrentThemeVariables().textDisabled}/>}
</View>
<Subheading style={{
textAlign: 'center',
marginRight: 20,
marginLeft: 20,
color: ThemeManager.getCurrentThemeVariables().textDisabled
}}>
{item.text}
</Subheading>
</View>);
<EmptyWebSectionListItem
text={item.text}
icon={item.icon}
refreshing={this.state.refreshing}
/>
);
}
createEmptyDataset() {

View file

@ -3,10 +3,9 @@
import * as React from 'react';
import {View} from 'react-native';
import WebView from "react-native-webview";
import Touchable from "react-native-platform-touchable";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import ThemeManager from "../utils/ThemeManager";
import {ActivityIndicator} from 'react-native-paper';
import HeaderButton from "./HeaderButton";
type Props = {
navigation: Object,
@ -58,14 +57,7 @@ export default class WebViewScreen extends React.Component<Props> {
getHeaderButton(clickAction: Function, icon: string) {
return (
<Touchable
style={{padding: 6}}
onPress={clickAction}>
<MaterialCommunityIcons
name={icon}
size={26}
color={ThemeManager.getCurrentThemeVariables().text}/>
</Touchable>
<HeaderButton icon={icon} onPress={clickAction}/>
);
}

View file

@ -0,0 +1,10 @@
export default {
machineStates: {
"TERMINE": "0",
"DISPONIBLE": "1",
"EN COURS": "2",
"HS": "3",
"ERREUR": "4"
},
};

View file

@ -12,10 +12,7 @@ import BibScreen from "../screens/Websites/BibScreen";
import DebugScreen from '../screens/DebugScreen';
import Sidebar from "../components/Sidebar";
import {createStackNavigator, TransitionPresets} from "@react-navigation/stack";
import {View} from "react-native";
import Touchable from "react-native-platform-touchable";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import ThemeManager from "../utils/ThemeManager";
import HeaderButton from "../components/HeaderButton";
const defaultScreenOptions = {
gestureEnabled: true,
@ -25,20 +22,7 @@ const defaultScreenOptions = {
function getDrawerButton(navigation: Object) {
return (
<View
style={{
flexDirection: 'row',
marginLeft: 10
}}>
<Touchable
style={{padding: 6}}
onPress={navigation.openDrawer}>
<MaterialCommunityIcons
name="menu"
size={26}
color={ThemeManager.getCurrentThemeVariables().text}/>
</Touchable>
</View>
<HeaderButton icon={'menu'} onPress={navigation.openDrawer}/>
);
}

View file

@ -14,8 +14,7 @@ import PlanexScreen from '../screens/Websites/PlanexScreen';
import {MaterialCommunityIcons} from "@expo/vector-icons";
import ThemeManager from "../utils/ThemeManager";
import AsyncStorageManager from "../utils/AsyncStorageManager";
import {View} from "react-native";
import Touchable from "react-native-platform-touchable";
import HeaderButton from "../components/HeaderButton";
const TAB_ICONS = {
Home: 'triangle',
@ -33,20 +32,7 @@ const defaultScreenOptions = {
function getDrawerButton(navigation: Object) {
return (
<View
style={{
flexDirection: 'row',
marginLeft: 10
}}>
<Touchable
style={{padding: 6}}
onPress={navigation.openDrawer}>
<MaterialCommunityIcons
name="menu"
size={26}
color={ThemeManager.getCurrentThemeVariables().text}/>
</Touchable>
</View>
<HeaderButton icon={'menu'} onPress={navigation.openDrawer}/>
);
}

View file

@ -16,7 +16,6 @@
"@react-navigation/native": "^5.0.9",
"@react-navigation/stack": "^5.1.1",
"expo": "^36.0.0",
"expo-font": "~8.0.0",
"expo-linear-gradient": "~8.0.0",
"expo-localization": "~8.0.0",
"expo-permissions": "~8.0.0",
@ -31,12 +30,10 @@
"react-native-gesture-handler": "~1.5.0",
"react-native-modalize": "^1.3.6",
"react-native-paper": "^3.6.0",
"react-native-platform-touchable": "^1.1.1",
"react-native-reanimated": "~1.4.0",
"react-native-render-html": "^4.1.2",
"react-native-safe-area-context": "0.6.0",
"react-native-screens": "2.0.0-alpha.12",
"react-native-status-bar-height": "^2.3.1",
"react-native-webview": "7.4.3"
},
"devDependencies": {

View file

@ -3,18 +3,17 @@
import * as React from 'react';
import {TouchableOpacity, View} from 'react-native';
import i18n from "i18n-js";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import Autolink from 'react-native-autolink';
import ThemeManager from "../utils/ThemeManager";
import DashboardItem from "../components/DashboardItem";
import * as WebBrowser from 'expo-web-browser';
import WebSectionList from "../components/WebSectionList";
import PlatformTouchable from "react-native-platform-touchable";
import {Avatar, Card, Text} from 'react-native-paper';
import {Avatar, Button, Card, Text} from 'react-native-paper';
import FeedItem from "../components/FeedItem";
import SquareDashboardItem from "../components/SquareDashboardItem";
// import DATA from "../dashboard_data.json";
const ICON_AMICALE = require('../assets/amicale.png');
const NAME_AMICALE = 'Amicale INSA Toulouse';
const DATA_URL = "https://etud.insa-toulouse.fr/~amicale_app/dashboard/dashboard_data.json";
@ -373,24 +372,24 @@ export default class HomeScreen extends React.Component<Props> {
flexDirection: 'row',
marginLeft: 10,
marginRight: 10,
marginBottom: 10,
}}>
<DashboardItem
isSquare={true}
<SquareDashboardItem
title={menuTitle}
subtitle={menuSubtitle}
color={menuColor}
icon={menuIcon}
clickAction={this.onMenuClick}
title={menuTitle}
isAvailable={isMenuAvailable}
isSquareLeft={true}/>
<DashboardItem
isSquare={true}
isLeft={true}/>
<SquareDashboardItem
title={proximoTitle}
subtitle={proximoSubtitle}
color={proximoColor}
icon={proximoIcon}
clickAction={this.onProximoClick}
title={proximoTitle}
isAvailable={isProximoAvailable}/>
isAvailable={isProximoAvailable}
isLeft={false}/>
</View>
);
}
@ -477,23 +476,22 @@ export default class HomeScreen extends React.Component<Props> {
marginLeft: 10,
marginRight: 10,
}}>
<DashboardItem
isSquare={true}
<SquareDashboardItem
title={proxiwashTitle}
subtitle={proxiwashSubtitle}
color={proxiwashColor}
icon={proxiwashIcon}
clickAction={this.onProxiwashClick}
title={proxiwashTitle}
isAvailable={proxiwashIsAvailable}
isSquareLeft={true}/>
<DashboardItem
isSquare={true}
isLeft={true}/>
<SquareDashboardItem
title={tutorinsaTitle}
subtitle={tutorinsaSubtitle}
color={tutorinsaColor}
icon={tutorinsaIcon}
clickAction={this.onTutorInsaClick}
title={tutorinsaTitle}
isAvailable={tutorinsaIsAvailable}/>
isAvailable={tutorinsaIsAvailable}
isLeft={false}/>
</View>
);
}
@ -506,36 +504,14 @@ export default class HomeScreen extends React.Component<Props> {
const onImagePress = this.openLink.bind(this, item.full_picture);
const onOutLinkPress = this.openLink.bind(this, item.permalink_url);
return (
<Card style={{margin: 5}}>
<Card.Title
title={NAME_AMICALE}
subtitle={HomeScreen.getFormattedDate(item.created_time)}
left={props => <Avatar.Image size={48} source={ICON_AMICALE}
style={{backgroundColor: 'transparent'}}/>}
/>
{item.full_picture !== '' && item.full_picture !== undefined ?
<TouchableOpacity onPress={onImagePress}>
<Card.Cover source={{uri: item.full_picture}}/>
</TouchableOpacity> : <View/>}
<Card.Content>
{item.message !== undefined ?
<Autolink
text={item.message}
hashtag="facebook"
style={{color: ThemeManager.getCurrentThemeVariables().text}}
/> : <View/>
}
<PlatformTouchable onPress={onOutLinkPress}>
<View style={{flexDirection: 'row', marginTop: 5}}>
<MaterialCommunityIcons
name="facebook"
color="#57aeff"
size={26}/>
<Text style={{color: "#57aeff"}}>En savoir plus</Text>
</View>
</PlatformTouchable>
</Card.Content>
</Card>
<FeedItem
title={NAME_AMICALE}
subtitle={HomeScreen.getFormattedDate(item.created_time)}
full_picture={item.full_picture}
message={item.message}
onImagePress={onImagePress}
onOutLinkPress={onOutLinkPress}
/>
);
}

View file

@ -27,7 +27,7 @@ export default class PlanningDisplayScreen extends React.Component<Props> {
render() {
// console.log("rendering planningDisplayScreen");
return (
<ScrollView style={{padding: 5}}>
<ScrollView style={{paddingLeft: 5, paddingRight: 5}}>
<Title>
{this.displayData.title}
</Title>

View file

@ -4,10 +4,11 @@ import * as React from 'react';
import {BackHandler, Image, View} from 'react-native';
import i18n from "i18n-js";
import ThemeManager from "../utils/ThemeManager";
import {Agenda, LocaleConfig} from 'react-native-calendars';
import {LocaleConfig} from 'react-native-calendars';
import WebDataManager from "../utils/WebDataManager";
import PlanningEventManager from '../utils/PlanningEventManager';
import {Text, Title, List, Avatar, Divider} from 'react-native-paper';
import CustomAgenda from "../components/CustomAgenda";
LocaleConfig.locales['fr'] = {
monthNames: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
@ -64,14 +65,6 @@ export default class PlanningScreen extends React.Component<Props, State> {
constructor(props: any) {
super(props);
this.webDataManager = new WebDataManager(FETCH_URL);
this.didFocusSubscription = props.navigation.addListener(
'didFocus',
() =>
BackHandler.addEventListener(
'hardwareBackPress',
this.onBackButtonPressAndroid
)
);
if (i18n.currentLocale().startsWith("fr")) {
LocaleConfig.defaultLocale = 'fr';
}
@ -88,8 +81,16 @@ export default class PlanningScreen extends React.Component<Props, State> {
componentDidMount() {
this.onRefresh();
this.didFocusSubscription = this.props.navigation.addListener(
'focus',
() =>
BackHandler.addEventListener(
'hardwareBackPress',
this.onBackButtonPressAndroid
)
);
this.willBlurSubscription = this.props.navigation.addListener(
'willBlur',
'blur',
() =>
BackHandler.removeEventListener(
'hardwareBackPress',
@ -235,7 +236,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
render() {
// console.log("rendering PlanningScreen");
return (
<Agenda
<CustomAgenda
// 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
// considered that the date in question is not yet loaded
@ -260,33 +261,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
// If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday.
firstDay={1}
// ref to this agenda in order to handle back button event
ref={this.onAgendaRef}
// agenda theme
theme={{
backgroundColor: ThemeManager.getCurrentThemeVariables().agendaBackgroundColor,
calendarBackground: ThemeManager.getCurrentThemeVariables().background,
textSectionTitleColor: ThemeManager.getCurrentThemeVariables().agendaDayTextColor,
selectedDayBackgroundColor: ThemeManager.getCurrentThemeVariables().primary,
selectedDayTextColor: '#ffffff',
todayTextColor: ThemeManager.getCurrentThemeVariables().primary,
dayTextColor: ThemeManager.getCurrentThemeVariables().text,
textDisabledColor: ThemeManager.getCurrentThemeVariables().agendaDayTextColor,
dotColor: ThemeManager.getCurrentThemeVariables().primary,
selectedDotColor: '#ffffff',
arrowColor: 'orange',
monthTextColor: ThemeManager.getCurrentThemeVariables().primary,
indicatorColor: ThemeManager.getCurrentThemeVariables().primary,
textDayFontWeight: '300',
textMonthFontWeight: 'bold',
textDayHeaderFontWeight: '300',
textDayFontSize: 16,
textMonthFontSize: 16,
textDayHeaderFontSize: 16,
agendaDayTextColor: ThemeManager.getCurrentThemeVariables().agendaDayTextColor,
agendaDayNumColor: ThemeManager.getCurrentThemeVariables().agendaDayTextColor,
agendaTodayColor: ThemeManager.getCurrentThemeVariables().primary,
agendaKnobColor: ThemeManager.getCurrentThemeVariables().primary,
}}
onRef={this.onAgendaRef}
/>
);
}

View file

@ -341,7 +341,7 @@ export default class ProximoListScreen extends React.Component<Props, State> {
}
render() {
// console.log("rendering ProximoListScreen");
console.log("rendering ProximoListScreen");
return (
<View>
<Modalize ref={this.modalRef}

View file

@ -6,6 +6,7 @@ import i18n from "i18n-js";
import ThemeManager from "../../utils/ThemeManager";
import WebSectionList from "../../components/WebSectionList";
import {IconButton, List} from 'react-native-paper';
import HeaderButton from "../../components/HeaderButton";
const DATA_URL = "https://etud.insa-toulouse.fr/~proximo/data/stock-v2.json";
@ -156,18 +157,8 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
style={{
flexDirection: 'row',
}}>
<IconButton
icon="magnify"
size={26}
color={ThemeManager.getCurrentThemeVariables().text}
onPress={this.onPressSearchBtn}
/>
<IconButton
icon="information"
size={26}
color={ThemeManager.getCurrentThemeVariables().text}
onPress={this.onPressAboutBtn}
/>
<HeaderButton icon={'magnify'} onPress={this.onPressSearchBtn}/>
<HeaderButton icon={'information'} onPress={this.onPressAboutBtn}/>
</View>
);
}

View file

@ -9,21 +9,15 @@ import NotificationsManager from "../../utils/NotificationsManager";
import AsyncStorageManager from "../../utils/AsyncStorageManager";
import * as Expo from "expo";
import {Divider, IconButton, List, Text, Title} from 'react-native-paper';
import HeaderButton from "../../components/HeaderButton";
import ProxiwashListItem from "../../components/ProxiwashListItem";
import ProxiwashConstants from "../../constants/ProxiwashConstants";
const DATA_URL = "https://etud.insa-toulouse.fr/~amicale_app/washinsa/washinsa.json";
const MACHINE_STATES = {
"TERMINE": "0",
"DISPONIBLE": "1",
"EN COURS": "2",
"HS": "3",
"ERREUR": "4"
};
let stateStrings = {};
let modalStateStrings = {};
let stateIcons = {};
let stateColors = {};
const REFRESH_TIME = 1000 * 10; // Refresh every 10 seconds
@ -63,30 +57,23 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
*/
constructor() {
super();
let colors = ThemeManager.getCurrentThemeVariables();
stateColors[MACHINE_STATES.TERMINE] = colors.proxiwashFinishedColor;
stateColors[MACHINE_STATES.DISPONIBLE] = colors.proxiwashReadyColor;
stateColors[MACHINE_STATES["EN COURS"]] = colors.proxiwashRunningColor;
stateColors[MACHINE_STATES.HS] = colors.proxiwashBrokenColor;
stateColors[MACHINE_STATES.ERREUR] = colors.proxiwashErrorColor;
stateStrings[ProxiwashConstants.machineStates.TERMINE] = i18n.t('proxiwashScreen.states.finished');
stateStrings[ProxiwashConstants.machineStates.DISPONIBLE] = i18n.t('proxiwashScreen.states.ready');
stateStrings[ProxiwashConstants.machineStates["EN COURS"]] = i18n.t('proxiwashScreen.states.running');
stateStrings[ProxiwashConstants.machineStates.HS] = i18n.t('proxiwashScreen.states.broken');
stateStrings[ProxiwashConstants.machineStates.ERREUR] = i18n.t('proxiwashScreen.states.error');
stateStrings[MACHINE_STATES.TERMINE] = i18n.t('proxiwashScreen.states.finished');
stateStrings[MACHINE_STATES.DISPONIBLE] = i18n.t('proxiwashScreen.states.ready');
stateStrings[MACHINE_STATES["EN COURS"]] = i18n.t('proxiwashScreen.states.running');
stateStrings[MACHINE_STATES.HS] = i18n.t('proxiwashScreen.states.broken');
stateStrings[MACHINE_STATES.ERREUR] = i18n.t('proxiwashScreen.states.error');
modalStateStrings[ProxiwashConstants.machineStates.TERMINE] = i18n.t('proxiwashScreen.modal.finished');
modalStateStrings[ProxiwashConstants.machineStates.DISPONIBLE] = i18n.t('proxiwashScreen.modal.ready');
modalStateStrings[ProxiwashConstants.machineStates["EN COURS"]] = i18n.t('proxiwashScreen.modal.running');
modalStateStrings[ProxiwashConstants.machineStates.HS] = i18n.t('proxiwashScreen.modal.broken');
modalStateStrings[ProxiwashConstants.machineStates.ERREUR] = i18n.t('proxiwashScreen.modal.error');
modalStateStrings[MACHINE_STATES.TERMINE] = i18n.t('proxiwashScreen.modal.finished');
modalStateStrings[MACHINE_STATES.DISPONIBLE] = i18n.t('proxiwashScreen.modal.ready');
modalStateStrings[MACHINE_STATES["EN COURS"]] = i18n.t('proxiwashScreen.modal.running');
modalStateStrings[MACHINE_STATES.HS] = i18n.t('proxiwashScreen.modal.broken');
modalStateStrings[MACHINE_STATES.ERREUR] = i18n.t('proxiwashScreen.modal.error');
stateIcons[MACHINE_STATES.TERMINE] = 'check-circle';
stateIcons[MACHINE_STATES.DISPONIBLE] = 'radiobox-blank';
stateIcons[MACHINE_STATES["EN COURS"]] = 'progress-check';
stateIcons[MACHINE_STATES.HS] = 'alert-octagram-outline';
stateIcons[MACHINE_STATES.ERREUR] = 'alert';
stateIcons[ProxiwashConstants.machineStates.TERMINE] = 'check-circle';
stateIcons[ProxiwashConstants.machineStates.DISPONIBLE] = 'radiobox-blank';
stateIcons[ProxiwashConstants.machineStates["EN COURS"]] = 'progress-check';
stateIcons[ProxiwashConstants.machineStates.HS] = 'alert-octagram-outline';
stateIcons[ProxiwashConstants.machineStates.ERREUR] = 'alert';
// let dataString = AsyncStorageManager.getInstance().preferences.proxiwashWatchedMachines.current;
this.onAboutPress = this.onAboutPress.bind(this);
@ -247,9 +234,9 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
*/
showAlert(title: string, item: Object, isDryer: boolean) {
let buttons = [{text: i18n.t("proxiwashScreen.modal.ok")}];
let message = modalStateStrings[MACHINE_STATES[item.state]];
let message = modalStateStrings[ProxiwashConstants.machineStates[item.state]];
const onPress = this.setupNotifications.bind(this, item.number);
if (MACHINE_STATES[item.state] === MACHINE_STATES["EN COURS"]) {
if (ProxiwashConstants.machineStates[item.state] === ProxiwashConstants.machineStates["EN COURS"]) {
buttons = [
{
text: this.isMachineWatched(item.number) ?
@ -267,7 +254,7 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
end: item.endTime,
remaining: item.remainingTime
});
} else if (MACHINE_STATES[item.state] === MACHINE_STATES.DISPONIBLE) {
} else if (ProxiwashConstants.machineStates[item.state] === ProxiwashConstants.machineStates.DISPONIBLE) {
if (isDryer)
message += '\n' + i18n.t('proxiwashScreen.dryersTariff');
else
@ -286,12 +273,7 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
getRightButton() {
return (
<IconButton
icon="information"
size={26}
color={ThemeManager.getCurrentThemeVariables().text}
onPress={this.onAboutPress}
/>
<HeaderButton icon={'information'} onPress={this.onAboutPress}/>
);
}
@ -327,56 +309,25 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
* @returns {React.Node}
*/
getRenderItem({item, section}: Object) {
let isMachineRunning = MACHINE_STATES[item.state] === MACHINE_STATES["EN COURS"];
let machineName = (section.title === i18n.t('proxiwashScreen.dryers') ? i18n.t('proxiwashScreen.dryer') : i18n.t('proxiwashScreen.washer')) + ' n°' + item.number;
let isDryer = section.title === i18n.t('proxiwashScreen.dryers');
const isMachineRunning = ProxiwashConstants.machineStates[item.state] === ProxiwashConstants.machineStates["EN COURS"];
const machineName = (section.title === i18n.t('proxiwashScreen.dryers') ? i18n.t('proxiwashScreen.dryer') : i18n.t('proxiwashScreen.washer')) + ' n°' + item.number;
const isDryer = section.title === i18n.t('proxiwashScreen.dryers');
const onPress = this.showAlert.bind(this, machineName, item, isDryer);
let width = item.donePercent !== '' ? (parseInt(item.donePercent)).toString() + '%' : 0;
if (MACHINE_STATES[item.state] === '0')
if (ProxiwashConstants.machineStates[item.state] === '0')
width = '100%';
return (
<View>
<View style={{
height: '100%',
position: 'absolute',
left: 0,
width: width,
backgroundColor: stateColors[MACHINE_STATES[item.state]]
}}/>
<List.Item
title={machineName}
description={isMachineRunning ? item.startTime + '/' + item.endTime : ''}
onPress={onPress}
style={{
backgroundColor: 'transparent',
height: 64
}}
left={props => this.isMachineWatched(item.number) ?
<List.Icon {...props} icon={'bell-ring'}
color={ThemeManager.getCurrentThemeVariables().primary}/> :
<List.Icon {...props} icon={isDryer ? 'tumble-dryer' : 'washing-machine'}/>}
right={props => (
<View style={{flexDirection: 'row'}}>
<View style={{
justifyContent: 'center',
}}>
<Text style={
MACHINE_STATES[item.state] === MACHINE_STATES.TERMINE ?
{fontWeight: 'bold',} : {}}
>
{stateStrings[MACHINE_STATES[item.state]]}
</Text>
</View>
<List.Icon
{...props}
color={ThemeManager.getCurrentThemeVariables().text}
icon={stateIcons[MACHINE_STATES[item.state]]}
/>
</View>)}
/>
<Divider/>
</View>
<ProxiwashListItem
title={machineName}
description={isMachineRunning ? item.startTime + '/' + item.endTime : ''}
onPress={onPress}
progress={width}
state={item.state}
isWatched={this.isMachineWatched(item.number)}
isDryer={isDryer}
statusText={stateStrings[ProxiwashConstants.machineStates[item.state]]}
statusIcon={stateIcons[ProxiwashConstants.machineStates[item.state]]}
/>
);
}
}

View file

@ -1,12 +1,12 @@
// @flow
import * as React from 'react';
import {ScrollView, View} from "react-native";
import {ScrollView} from "react-native";
import ThemeManager from '../utils/ThemeManager';
import i18n from "i18n-js";
import AsyncStorageManager from "../utils/AsyncStorageManager";
import NotificationsManager from "../utils/NotificationsManager";
import {Card, List, Switch, RadioButton, Text, TouchableRipple} from 'react-native-paper';
import {Card, List, Switch, ToggleButton} from 'react-native-paper';
type Props = {
navigation: Object,
@ -39,39 +39,6 @@ export default class SettingsScreen extends React.Component<Props, State> {
this.onToggleNightMode = this.onToggleNightMode.bind(this);
}
/**
* Get a list item using the specified control
*
* @param control The custom control to use
* @param icon The icon name to display on the list item
* @param title The text to display as this list item title
* @param subtitle The text to display as this list item subtitle
* @returns {React.Node}
*/
static getGeneralItem(control: React.Node, icon: string, title: string, subtitle: string) {
return (
<List.Item
title={title}
description={subtitle}
left={props => <List.Icon {...props} icon={icon}/>}
right={props => control}
/>
);
}
getRadioButton(onPress: Function, value: string, label: string) {
return (
<TouchableRipple
onPress={onPress}
>
<View pointerEvents="none">
<Text>{label}</Text>
<RadioButton value={value} />
</View>
</TouchableRipple>
);
}
/**
* Save the value for the proxiwash reminder notification time
*
@ -95,11 +62,13 @@ export default class SettingsScreen extends React.Component<Props, State> {
* @param value The value to store
*/
onStartScreenPickerValueChange(value: string) {
let key = AsyncStorageManager.getInstance().preferences.defaultStartScreen.key;
AsyncStorageManager.getInstance().savePref(key, value);
this.setState({
startScreenPickerSelected: value
});
if (value != null) {
let key = AsyncStorageManager.getInstance().preferences.defaultStartScreen.key;
AsyncStorageManager.getInstance().savePref(key, value);
this.setState({
startScreenPickerSelected: value
});
}
}
/**
@ -109,16 +78,14 @@ export default class SettingsScreen extends React.Component<Props, State> {
*/
getProxiwashNotifPicker() {
return (
<RadioButton.Group
<ToggleButton.Row
onValueChange={this.onProxiwashNotifPickerValueChange}
value={this.state.proxiwashNotifPickerSelected}
>
<RadioButton.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.never')} value="never"/>
<RadioButton.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.5')} value="5"/>
<RadioButton.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.10')} value="10"/>
<RadioButton.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.20')} value="20"/>
<RadioButton.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.30')} value="30"/>
</RadioButton.Group>
<ToggleButton icon="close" value="never"/>
<ToggleButton icon="numeric-2" value="2"/>
<ToggleButton icon="numeric-5" value="5"/>
</ToggleButton.Row>
);
}
@ -129,16 +96,16 @@ export default class SettingsScreen extends React.Component<Props, State> {
*/
getStartScreenPicker() {
return (
<RadioButton.Group
<ToggleButton.Row
onValueChange={this.onStartScreenPickerValueChange}
value={this.state.startScreenPickerSelected}
>
<RadioButton.Item label={i18n.t('screens.home')} value="Home" style={{color: "#fff"}}/>
<RadioButton.Item label={i18n.t('screens.planning')} value="Planning"/>
<RadioButton.Item label={i18n.t('screens.proxiwash')} value="Proxiwash"/>
<RadioButton.Item label={i18n.t('screens.proximo')} value="Proximo"/>
<RadioButton.Item label={'Planex'} value="Planex"/>
</RadioButton.Group>
<ToggleButton icon="shopping" value="Proximo"/>
<ToggleButton icon="calendar-range" value="Planning"/>
<ToggleButton icon="triangle" value="Home"/>
<ToggleButton icon="washing-machine" value="Proxiwash"/>
<ToggleButton icon="timetable" value="Planex"/>
</ToggleButton.Row>
);
}
@ -180,11 +147,18 @@ export default class SettingsScreen extends React.Component<Props, State> {
<Card style={{margin: 5}}>
<Card.Title title={i18n.t('settingsScreen.generalCard')}/>
<List.Section>
{this.getToggleItem(this.onToggleNightMode, 'theme-light-dark', i18n.t('settingsScreen.nightMode'), i18n.t('settingsScreen.nightModeSub'))}
{this.getToggleItem(
this.onToggleNightMode,
'theme-light-dark',
i18n.t('settingsScreen.nightMode'),
this.state.nightMode ?
i18n.t('settingsScreen.nightModeSubOn') :
i18n.t('settingsScreen.nightModeSubOff')
)}
<List.Accordion
title={i18n.t('settingsScreen.startScreen')}
description={i18n.t('settingsScreen.startScreenSub')}
left={props => <List.Icon {...props} icon="power" />}
left={props => <List.Icon {...props} icon="power"/>}
>
{this.getStartScreenPicker()}
</List.Accordion>
@ -192,13 +166,15 @@ export default class SettingsScreen extends React.Component<Props, State> {
</Card>
<Card style={{margin: 5}}>
<Card.Title title="Proxiwash"/>
<List.Accordion
title={i18n.t('settingsScreen.proxiwashNotifReminder')}
description={i18n.t('settingsScreen.proxiwashNotifReminderSub')}
left={props => <List.Icon {...props} icon="washing-machine" />}
>
{this.getProxiwashNotifPicker()}
</List.Accordion>
<List.Section>
<List.Accordion
title={i18n.t('settingsScreen.proxiwashNotifReminder')}
description={i18n.t('settingsScreen.proxiwashNotifReminderSub')}
left={props => <List.Icon {...props} icon="washing-machine"/>}
>
{this.getProxiwashNotifPicker()}
</List.Accordion>
</List.Section>
</Card>
</ScrollView>

View file

@ -60,21 +60,12 @@
"settingsScreen": {
"generalCard": "General",
"nightMode": "Night Mode",
"nightModeSub": "Switch the app to a dark or light theme",
"nightModeSubOn": "Your eyes are at peace",
"nightModeSubOff": "Your eyes are burning",
"startScreen": "Start Screen",
"startScreenSub": "Select which screen to start the app on",
"proxiwashNotifReminder": "Machine running reminder",
"proxiwashNotifReminderSub": "Choose when to send a notification to remind you a machine is running with your laundry",
"proxiwashNotifReminderPicker": {
"never": "Never",
"1": "1 min",
"2": "2 min",
"3": "3 min",
"5": "5 min",
"10": "10 min",
"20": "20 min",
"30": "30 min"
}
"proxiwashNotifReminderSub": "How many minutes before",
},
"homeScreen": {
"listUpdated": "List updated!",

View file

@ -60,21 +60,12 @@
"settingsScreen": {
"generalCard": "Général",
"nightMode": "Mode Nuit",
"nightModeSub": "Passer l'application dans un thème sombre ou clair",
"nightModeSubOn": "Vos yeux brulent",
"nightModeSubOff": "Vos yeux vous remercient",
"startScreen": "Écran de démarrage",
"startScreenSub": "Choisissez l'écran utilisé au démarrage",
"proxiwashNotifReminder": "Rappel de machine en cours",
"proxiwashNotifReminderSub": "Choississez quand envoyer une notification pour vous rappeler qu'une machine avec votre linge est en cours",
"proxiwashNotifReminderPicker": {
"never": "Jamais",
"1": "1 min",
"2": "2 min",
"3": "3 min",
"5": "5 min",
"10": "10 min",
"20": "20 min",
"30": "30 min"
}
"proxiwashNotifReminderSub": "Combien de minutes avant",
},
"homeScreen": {
"listUpdated": "List mise à jour!",

View file

@ -38,6 +38,7 @@ export default class ThemeManager {
proxiwashFinishedColor: "rgba(54,165,22,0.31)",
proxiwashReadyColor: "transparent",
proxiwashRunningColor: "rgba(94,104,241,0.3)",
proxiwashRunningBgColor: "rgba(99,109,255,0.14)",
proxiwashBrokenColor: "rgba(162,162,162,0.31)",
proxiwashErrorColor: "rgba(204,7,0,0.31)",
@ -74,6 +75,7 @@ export default class ThemeManager {
proxiwashFinishedColor: "rgba(17,149,32,0.53)",
proxiwashReadyColor: "transparent",
proxiwashRunningColor: "rgba(29,59,175,0.65)",
proxiwashRunningBgColor: "rgba(99,109,255,0.14)",
proxiwashBrokenColor: "#000000",
proxiwashErrorColor: "rgba(213,8,0,0.57)",

View file

@ -24,38 +24,10 @@ export default class WebDataManager {
let response = await fetch(this.FETCH_URL);
fetchedData = await response.json();
} catch (error) {
// console.log('Could not read FetchedData from server');
// console.log(error);
throw new Error('Could not read FetchedData from server');
}
this.lastDataFetched = fetchedData;
return fetchedData;
}
/**
* Detects if the fetched data is not an empty object
*
* @return
*/
isDataObjectValid(): boolean {
return Object.keys(this.lastDataFetched).length > 0;
}
/**
* Show a toast message depending on the validity of the fetched data
*
* @param errorString
*/
showUpdateToast(errorString) {
// let isSuccess = this.isDataObjectValid();
// if (!isSuccess) {
// Toast.show({
// text: errorString,
// buttonText: 'OK',
// type: isSuccess ? "success" : "danger",
// duration: 2000
// });
// }
}
}