forked from vergnet/application-amicale
Improved proxiwash screen + show help banner on proxiwash and planex
This commit is contained in:
parent
24ad1076a0
commit
7f7ae68664
8 changed files with 197 additions and 64 deletions
|
@ -1,5 +1,5 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {Divider, List, Text, withTheme} from 'react-native-paper';
|
import {Card, Avatar, List, Text, withTheme} from 'react-native-paper';
|
||||||
import {View} from "react-native";
|
import {View} from "react-native";
|
||||||
import ProxiwashConstants from "../constants/ProxiwashConstants";
|
import ProxiwashConstants from "../constants/ProxiwashConstants";
|
||||||
|
|
||||||
|
@ -13,27 +13,48 @@ function ProxiwashListItem(props) {
|
||||||
stateColors[ProxiwashConstants.machineStates.ERREUR] = colors.proxiwashErrorColor;
|
stateColors[ProxiwashConstants.machineStates.ERREUR] = colors.proxiwashErrorColor;
|
||||||
const icon = (
|
const icon = (
|
||||||
props.isWatched ?
|
props.isWatched ?
|
||||||
<List.Icon icon={'bell-ring'} color={colors.primary}/> :
|
<Avatar.Icon
|
||||||
<List.Icon icon={props.isDryer ? 'tumble-dryer' : 'washing-machine'}/>
|
icon={'bell-ring'}
|
||||||
|
size={45}
|
||||||
|
color={colors.primary}
|
||||||
|
style={{backgroundColor: 'transparent'}}
|
||||||
|
/> :
|
||||||
|
<Avatar.Icon
|
||||||
|
icon={props.isDryer ? 'tumble-dryer' : 'washing-machine'}
|
||||||
|
color={colors.text}
|
||||||
|
size={40}
|
||||||
|
style={{backgroundColor: 'transparent'}}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<View style={{
|
<Card
|
||||||
backgroundColor:
|
style={{
|
||||||
ProxiwashConstants.machineStates[props.state] === ProxiwashConstants.machineStates["EN COURS"] ?
|
margin: 5,
|
||||||
colors.proxiwashRunningBgColor :
|
}}
|
||||||
colors.background
|
onPress={props.onPress}
|
||||||
}}>
|
>
|
||||||
<View style={{
|
{ProxiwashConstants.machineStates[props.state] === ProxiwashConstants.machineStates["EN COURS"] ?
|
||||||
|
<Card style={{
|
||||||
|
height: '100%',
|
||||||
|
position: 'absolute',
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
backgroundColor: colors.proxiwashRunningBgColor,
|
||||||
|
elevation: 0
|
||||||
|
}}/> : null
|
||||||
|
}
|
||||||
|
|
||||||
|
<Card style={{
|
||||||
height: '100%',
|
height: '100%',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: 0,
|
left: 0,
|
||||||
width: props.progress,
|
width: props.progress,
|
||||||
backgroundColor: stateColors[ProxiwashConstants.machineStates[props.state]]
|
backgroundColor: stateColors[ProxiwashConstants.machineStates[props.state]],
|
||||||
|
elevation: 0
|
||||||
}}/>
|
}}/>
|
||||||
<List.Item
|
<Card.Title
|
||||||
title={props.title}
|
title={props.title}
|
||||||
description={props.description}
|
subtitle={props.description}
|
||||||
onPress={props.onPress}
|
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
height: 64
|
height: 64
|
||||||
|
@ -52,14 +73,15 @@ function ProxiwashListItem(props) {
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<List.Icon
|
<Avatar.Icon
|
||||||
color={colors.text}
|
|
||||||
icon={props.statusIcon}
|
icon={props.statusIcon}
|
||||||
|
color={colors.text}
|
||||||
|
size={30}
|
||||||
|
style={{backgroundColor: 'transparent'}}
|
||||||
/>
|
/>
|
||||||
</View>)}
|
</View>)}
|
||||||
/>
|
/>
|
||||||
<Divider/>
|
</Card>
|
||||||
</View>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -187,7 +187,7 @@ export default class WebSectionList extends React.Component<Props, State> {
|
||||||
render() {
|
render() {
|
||||||
let dataset = this.props.createDataset(this.state.fetchedData);
|
let dataset = this.props.createDataset(this.state.fetchedData);
|
||||||
const isEmpty = dataset[0].data.length === 0;
|
const isEmpty = dataset[0].data.length === 0;
|
||||||
const shouldRenderHeader = !isEmpty || (this.props.renderSectionHeader !== null);
|
const shouldRenderHeader = !isEmpty && (this.props.renderSectionHeader !== null);
|
||||||
if (isEmpty)
|
if (isEmpty)
|
||||||
dataset = this.createEmptyDataset();
|
dataset = this.createEmptyDataset();
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -2,13 +2,12 @@
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {Alert, Platform, View} from 'react-native';
|
import {Alert, Platform, View} from 'react-native';
|
||||||
import ThemeManager from '../../utils/ThemeManager';
|
|
||||||
import i18n from "i18n-js";
|
import i18n from "i18n-js";
|
||||||
import WebSectionList from "../../components/WebSectionList";
|
import WebSectionList from "../../components/WebSectionList";
|
||||||
import NotificationsManager from "../../utils/NotificationsManager";
|
import NotificationsManager from "../../utils/NotificationsManager";
|
||||||
import AsyncStorageManager from "../../utils/AsyncStorageManager";
|
import AsyncStorageManager from "../../utils/AsyncStorageManager";
|
||||||
import * as Expo from "expo";
|
import * as Expo from "expo";
|
||||||
import {Divider, IconButton, List, Text, Title} from 'react-native-paper';
|
import {Card, Banner, Avatar} from 'react-native-paper';
|
||||||
import HeaderButton from "../../components/HeaderButton";
|
import HeaderButton from "../../components/HeaderButton";
|
||||||
import ProxiwashListItem from "../../components/ProxiwashListItem";
|
import ProxiwashListItem from "../../components/ProxiwashListItem";
|
||||||
import ProxiwashConstants from "../../constants/ProxiwashConstants";
|
import ProxiwashConstants from "../../constants/ProxiwashConstants";
|
||||||
|
@ -30,6 +29,7 @@ type State = {
|
||||||
firstLoading: boolean,
|
firstLoading: boolean,
|
||||||
fetchedData: Object,
|
fetchedData: Object,
|
||||||
machinesWatched: Array<string>,
|
machinesWatched: Array<string>,
|
||||||
|
bannerVisible: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
getRenderItem: Function;
|
getRenderItem: Function;
|
||||||
getRenderSectionHeader: Function;
|
getRenderSectionHeader: Function;
|
||||||
createDataset: Function;
|
createDataset: Function;
|
||||||
|
onHideBanner: Function;
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
refreshing: false,
|
refreshing: false,
|
||||||
|
@ -50,6 +51,7 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
fetchedData: {},
|
fetchedData: {},
|
||||||
// machinesWatched: JSON.parse(dataString),
|
// machinesWatched: JSON.parse(dataString),
|
||||||
machinesWatched: [],
|
machinesWatched: [],
|
||||||
|
bannerVisible: AsyncStorageManager.getInstance().preferences.proxiwashShowBanner.current === '1',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,6 +82,15 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
this.getRenderItem = this.getRenderItem.bind(this);
|
this.getRenderItem = this.getRenderItem.bind(this);
|
||||||
this.getRenderSectionHeader = this.getRenderSectionHeader.bind(this);
|
this.getRenderSectionHeader = this.getRenderSectionHeader.bind(this);
|
||||||
this.createDataset = this.createDataset.bind(this);
|
this.createDataset = this.createDataset.bind(this);
|
||||||
|
this.onHideBanner = this.onHideBanner.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
onHideBanner() {
|
||||||
|
this.setState({bannerVisible: false});
|
||||||
|
AsyncStorageManager.getInstance().savePref(
|
||||||
|
AsyncStorageManager.getInstance().preferences.proxiwashShowBanner.key,
|
||||||
|
'0'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -280,24 +291,57 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
render() {
|
render() {
|
||||||
const nav = this.props.navigation;
|
const nav = this.props.navigation;
|
||||||
return (
|
return (
|
||||||
<WebSectionList
|
<View>
|
||||||
createDataset={this.createDataset}
|
<Banner
|
||||||
navigation={nav}
|
visible={this.state.bannerVisible}
|
||||||
refreshTime={REFRESH_TIME}
|
actions={[
|
||||||
fetchUrl={DATA_URL}
|
{
|
||||||
renderItem={this.getRenderItem}
|
label: 'OK',
|
||||||
renderSectionHeader={this.getRenderSectionHeader}/>
|
onPress: this.onHideBanner,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
icon={() => <Avatar.Icon
|
||||||
|
icon={'information'}
|
||||||
|
size={40}
|
||||||
|
/>}
|
||||||
|
>
|
||||||
|
{i18n.t('proxiwashScreen.enableNotificationsTip')}
|
||||||
|
</Banner>
|
||||||
|
<WebSectionList
|
||||||
|
createDataset={this.createDataset}
|
||||||
|
navigation={nav}
|
||||||
|
refreshTime={REFRESH_TIME}
|
||||||
|
fetchUrl={DATA_URL}
|
||||||
|
renderItem={this.getRenderItem}
|
||||||
|
renderSectionHeader={this.getRenderSectionHeader}/>
|
||||||
|
</View>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRenderSectionHeader({section}: Object) {
|
getRenderSectionHeader({section}: Object) {
|
||||||
return (
|
return (
|
||||||
<Title style={{
|
<Card style={{
|
||||||
marginTop: 10,
|
width: '80%',
|
||||||
textAlign: 'center'
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginBottom: 10,
|
||||||
|
marginTop: 20,
|
||||||
}}>
|
}}>
|
||||||
{section.title}
|
<Card.Title
|
||||||
</Title>
|
title={section.title}
|
||||||
|
// subtitle={''} // TODO display num available
|
||||||
|
titleStyle={{
|
||||||
|
textAlign: 'center'
|
||||||
|
}}
|
||||||
|
subtitleStyle={{
|
||||||
|
textAlign: 'center'
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
paddingLeft: 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,19 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import ThemeManager from "../../utils/ThemeManager";
|
import ThemeManager from "../../utils/ThemeManager";
|
||||||
import WebViewScreen from "../../components/WebViewScreen";
|
import WebViewScreen from "../../components/WebViewScreen";
|
||||||
|
import {Avatar, Banner} from "react-native-paper";
|
||||||
|
import i18n from "i18n-js";
|
||||||
|
import {View} from "react-native";
|
||||||
|
import AsyncStorageManager from "../../utils/AsyncStorageManager";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
navigation: Object,
|
navigation: Object,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
bannerVisible: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const PLANEX_URL = 'http://planex.insa-toulouse.fr/';
|
const PLANEX_URL = 'http://planex.insa-toulouse.fr/';
|
||||||
|
|
||||||
|
@ -75,9 +83,11 @@ const OBSERVE_MUTATIONS_INJECTED =
|
||||||
* Class defining the app's planex screen.
|
* Class defining the app's planex screen.
|
||||||
* This screen uses a webview to render the planex page
|
* This screen uses a webview to render the planex page
|
||||||
*/
|
*/
|
||||||
export default class PlanexScreen extends React.Component<Props> {
|
export default class PlanexScreen extends React.Component<Props, State> {
|
||||||
|
|
||||||
customInjectedJS: string;
|
customInjectedJS: string;
|
||||||
|
onHideBanner: Function;
|
||||||
|
onGoToSettings: Function;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
@ -93,26 +103,70 @@ export default class PlanexScreen extends React.Component<Props> {
|
||||||
this.customInjectedJS +=
|
this.customInjectedJS +=
|
||||||
'removeAlpha();' +
|
'removeAlpha();' +
|
||||||
'});true;'; // Prevent crash on ios
|
'});true;'; // Prevent crash on ios
|
||||||
|
this.onHideBanner = this.onHideBanner.bind(this);
|
||||||
|
this.onGoToSettings = this.onGoToSettings.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
bannerVisible:
|
||||||
|
AsyncStorageManager.getInstance().preferences.planexShowBanner.current === '1' &&
|
||||||
|
AsyncStorageManager.getInstance().preferences.defaultStartScreen.current !== 'Planex',
|
||||||
|
};
|
||||||
|
|
||||||
|
onHideBanner() {
|
||||||
|
this.setState({bannerVisible: false});
|
||||||
|
AsyncStorageManager.getInstance().savePref(
|
||||||
|
AsyncStorageManager.getInstance().preferences.planexShowBanner.key,
|
||||||
|
'0'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onGoToSettings() {
|
||||||
|
this.onHideBanner();
|
||||||
|
this.props.navigation.navigate('SettingsScreen');
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const nav = this.props.navigation;
|
const nav = this.props.navigation;
|
||||||
return (
|
return (
|
||||||
<WebViewScreen
|
<View style={{
|
||||||
navigation={nav}
|
height: '100%'
|
||||||
data={[
|
}}>
|
||||||
{
|
<Banner
|
||||||
url: PLANEX_URL,
|
visible={this.state.bannerVisible}
|
||||||
icon: '',
|
actions={[
|
||||||
name: '',
|
{
|
||||||
customJS: this.customInjectedJS
|
label: i18n.t('planexScreen.enableStartOK'),
|
||||||
},
|
onPress: this.onGoToSettings,
|
||||||
]}
|
},
|
||||||
customInjectedJS={this.customInjectedJS}
|
{
|
||||||
headerTitle={'Planex'}
|
label: i18n.t('planexScreen.enableStartCancel'),
|
||||||
hasHeaderBackButton={false}
|
onPress: this.onHideBanner,
|
||||||
hasFooter={false}/>
|
},
|
||||||
|
|
||||||
|
]}
|
||||||
|
icon={() => <Avatar.Icon
|
||||||
|
icon={'information'}
|
||||||
|
size={40}
|
||||||
|
/>}
|
||||||
|
>
|
||||||
|
{i18n.t('planexScreen.enableStartScreen')}
|
||||||
|
</Banner>
|
||||||
|
<WebViewScreen
|
||||||
|
navigation={nav}
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
url: PLANEX_URL,
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
customJS: this.customInjectedJS
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
customInjectedJS={this.customInjectedJS}
|
||||||
|
headerTitle={'Planex'}
|
||||||
|
hasHeaderBackButton={false}
|
||||||
|
hasFooter={false}/>
|
||||||
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,6 +160,7 @@
|
||||||
"dryerTips": "The advised dryer length is 35 minutes for 14 kg of laundry. You can choose a shorter length if the dryer is not fully charged.",
|
"dryerTips": "The advised dryer length is 35 minutes for 14 kg of laundry. You can choose a shorter length if the dryer is not fully charged.",
|
||||||
"procedure": "Procedure",
|
"procedure": "Procedure",
|
||||||
"tips": "Tips",
|
"tips": "Tips",
|
||||||
|
"enableNotificationsTip": "Click on a running machine to enable notifications",
|
||||||
"modal": {
|
"modal": {
|
||||||
"enableNotifications": "Notify me",
|
"enableNotifications": "Notify me",
|
||||||
"disableNotifications": "Stop notifications",
|
"disableNotifications": "Stop notifications",
|
||||||
|
@ -188,8 +189,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"planexScreen": {
|
"planexScreen": {
|
||||||
"rotateToLandscape": "Turn your screen to see the whole week",
|
"enableStartScreen": "Come here often? Set it as default screen!",
|
||||||
"rotateToPortrait": "Turn your screen to see only 2 days"
|
"enableStartOK": "Yes please!",
|
||||||
|
"enableStartCancel": "Later"
|
||||||
},
|
},
|
||||||
"availableRoomScreen": {
|
"availableRoomScreen": {
|
||||||
"normalRoom": "Work",
|
"normalRoom": "Work",
|
||||||
|
|
|
@ -160,7 +160,7 @@
|
||||||
"dryerTips": "La durée conseillée est de 35 minutes pour 14kg de linge. Vous pouvez choisir une durée plus courte si le sèche-linge n'est pas chargé.",
|
"dryerTips": "La durée conseillée est de 35 minutes pour 14kg de linge. Vous pouvez choisir une durée plus courte si le sèche-linge n'est pas chargé.",
|
||||||
"procedure": "Procédure",
|
"procedure": "Procédure",
|
||||||
"tips": "Conseils",
|
"tips": "Conseils",
|
||||||
|
"enableNotificationsTip": "Cliquez sur une machine en cours pour activer les notifications",
|
||||||
"modal": {
|
"modal": {
|
||||||
"enableNotifications": "Me Notifier",
|
"enableNotifications": "Me Notifier",
|
||||||
"disableNotifications": "Désactiver les notifications",
|
"disableNotifications": "Désactiver les notifications",
|
||||||
|
@ -190,8 +190,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"planexScreen": {
|
"planexScreen": {
|
||||||
"rotateToLandscape": "Tournez votre téléphone pour voir la semaine entière",
|
"enableStartScreen": "Vous venez souvent ici ? Démarrez l'appli sur cette page!",
|
||||||
"rotateToPortrait": "Tournez votre téléphone pour voir seulement 2 jours"
|
"enableStartOK": "Oui svp!",
|
||||||
|
"enableStartCancel": "Plus tard"
|
||||||
},
|
},
|
||||||
"availableRoomScreen": {
|
"availableRoomScreen": {
|
||||||
"normalRoom": "Travail",
|
"normalRoom": "Travail",
|
||||||
|
|
|
@ -63,7 +63,17 @@ export default class AsyncStorageManager {
|
||||||
key: 'defaultStartScreen',
|
key: 'defaultStartScreen',
|
||||||
default: 'Home',
|
default: 'Home',
|
||||||
current: '',
|
current: '',
|
||||||
}
|
},
|
||||||
|
proxiwashShowBanner: {
|
||||||
|
key: 'proxiwashShowBanner',
|
||||||
|
default: '1',
|
||||||
|
current: '',
|
||||||
|
},
|
||||||
|
planexShowBanner: {
|
||||||
|
key: 'planexShowBanner',
|
||||||
|
default: '1',
|
||||||
|
current: '',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,12 +35,12 @@ export default class ThemeManager {
|
||||||
agendaDayTextColor: '#636363',
|
agendaDayTextColor: '#636363',
|
||||||
|
|
||||||
// PROXIWASH
|
// PROXIWASH
|
||||||
proxiwashFinishedColor: "rgba(54,165,22,0.31)",
|
proxiwashFinishedColor: "#a5dc9d",
|
||||||
proxiwashReadyColor: "transparent",
|
proxiwashReadyColor: "transparent",
|
||||||
proxiwashRunningColor: "rgba(94,104,241,0.3)",
|
proxiwashRunningColor: "#a0ceff",
|
||||||
proxiwashRunningBgColor: "rgba(99,109,255,0.14)",
|
proxiwashRunningBgColor: "#c7e3ff",
|
||||||
proxiwashBrokenColor: "rgba(162,162,162,0.31)",
|
proxiwashBrokenColor: "#8e8e8e",
|
||||||
proxiwashErrorColor: "rgba(204,7,0,0.31)",
|
proxiwashErrorColor: "rgba(204,7,0,0.31)#e35f57",
|
||||||
|
|
||||||
// Screens
|
// Screens
|
||||||
planningColor: '#d9b10a',
|
planningColor: '#d9b10a',
|
||||||
|
@ -72,12 +72,12 @@ export default class ThemeManager {
|
||||||
agendaDayTextColor: '#6d6d6d',
|
agendaDayTextColor: '#6d6d6d',
|
||||||
|
|
||||||
// PROXIWASH
|
// PROXIWASH
|
||||||
proxiwashFinishedColor: "rgba(17,149,32,0.53)",
|
proxiwashFinishedColor: "#31682c",
|
||||||
proxiwashReadyColor: "transparent",
|
proxiwashReadyColor: "transparent",
|
||||||
proxiwashRunningColor: "rgba(29,59,175,0.65)",
|
proxiwashRunningColor: "#213c79",
|
||||||
proxiwashRunningBgColor: "rgba(99,109,255,0.14)",
|
proxiwashRunningBgColor: "#1a2033",
|
||||||
proxiwashBrokenColor: "#000000",
|
proxiwashBrokenColor: "#656565",
|
||||||
proxiwashErrorColor: "rgba(213,8,0,0.57)",
|
proxiwashErrorColor: "#7e2e2f",
|
||||||
|
|
||||||
// Screens
|
// Screens
|
||||||
planningColor: '#d99e09',
|
planningColor: '#d99e09',
|
||||||
|
|
Loading…
Reference in a new issue