forked from vergnet/application-amicale
Added notification support for proxiwash
This commit is contained in:
parent
18fae8346f
commit
be67c70a95
9 changed files with 442 additions and 57 deletions
90
dataProxiwash.json
Normal file
90
dataProxiwash.json
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
{
|
||||||
|
"dryers": [
|
||||||
|
{
|
||||||
|
"number": "1",
|
||||||
|
"state": "TERMINE",
|
||||||
|
"startTime": "",
|
||||||
|
"endTime": "",
|
||||||
|
"donePercent": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": "2",
|
||||||
|
"state": "DISPONIBLE",
|
||||||
|
"startTime": "",
|
||||||
|
"endTime": "",
|
||||||
|
"donePercent": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": "3",
|
||||||
|
"state": "FONCTIONNE",
|
||||||
|
"startTime": "10:16",
|
||||||
|
"endTime": "10:50",
|
||||||
|
"donePercent": "36.5"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"washers": [
|
||||||
|
{
|
||||||
|
"number": "4",
|
||||||
|
"state": "DISPONIBLE",
|
||||||
|
"startTime": "",
|
||||||
|
"endTime": "",
|
||||||
|
"donePercent": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": "5",
|
||||||
|
"state": "DISPONIBLE",
|
||||||
|
"startTime": "",
|
||||||
|
"endTime": "",
|
||||||
|
"donePercent": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": "6",
|
||||||
|
"state": "DISPONIBLE",
|
||||||
|
"startTime": "",
|
||||||
|
"endTime": "",
|
||||||
|
"donePercent": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": "7",
|
||||||
|
"state": "DISPONIBLE",
|
||||||
|
"startTime": "",
|
||||||
|
"endTime": "",
|
||||||
|
"donePercent": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": "8",
|
||||||
|
"state": "DISPONIBLE",
|
||||||
|
"startTime": "",
|
||||||
|
"endTime": "",
|
||||||
|
"donePercent": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": "9",
|
||||||
|
"state": "FONCTIONNE",
|
||||||
|
"startTime": "09:46",
|
||||||
|
"endTime": "10:31",
|
||||||
|
"donePercent": "93.9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": "10",
|
||||||
|
"state": "DISPONIBLE",
|
||||||
|
"startTime": "",
|
||||||
|
"endTime": "",
|
||||||
|
"donePercent": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": "11",
|
||||||
|
"state": "HS",
|
||||||
|
"startTime": "",
|
||||||
|
"endTime": "",
|
||||||
|
"donePercent": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": "12",
|
||||||
|
"state": "DISPONIBLE",
|
||||||
|
"startTime": "",
|
||||||
|
"endTime": "",
|
||||||
|
"donePercent": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -12,6 +12,7 @@
|
||||||
"expo": "^33.0.0",
|
"expo": "^33.0.0",
|
||||||
"expo-font": "^5.0.1",
|
"expo-font": "^5.0.1",
|
||||||
"expo-localization": "^5.0.1",
|
"expo-localization": "^5.0.1",
|
||||||
|
"expo-permissions": "^5.0.1",
|
||||||
"i18n-js": "^3.3.0",
|
"i18n-js": "^3.3.0",
|
||||||
"i18next": "latest",
|
"i18next": "latest",
|
||||||
"native-base": "latest",
|
"native-base": "latest",
|
||||||
|
@ -20,13 +21,13 @@
|
||||||
"react-i18next": "latest",
|
"react-i18next": "latest",
|
||||||
"react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz",
|
"react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz",
|
||||||
"react-native-paper": "latest",
|
"react-native-paper": "latest",
|
||||||
|
"react-native-platform-touchable": "latest",
|
||||||
"react-native-settings-page": "latest",
|
"react-native-settings-page": "latest",
|
||||||
"react-native-status-bar-height": "latest",
|
"react-native-status-bar-height": "latest",
|
||||||
"react-native-web": "^0.11.4",
|
"react-native-web": "^0.11.4",
|
||||||
"react-native-week-view": "latest",
|
"react-native-week-view": "latest",
|
||||||
"react-navigation": "latest",
|
"react-navigation": "latest",
|
||||||
"react-navigation-material-bottom-tabs": "latest",
|
"react-navigation-material-bottom-tabs": "latest"
|
||||||
"react-native-platform-touchable": "latest"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-preset-expo": "^5.1.1",
|
"babel-preset-expo": "^5.1.1",
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import {Container, Content, Text, Button, Icon} from 'native-base';
|
import {Container, Content, Text, Button, Icon} from 'native-base';
|
||||||
import CustomHeader from '../components/CustomHeader';
|
import CustomHeader from '../components/CustomHeader';
|
||||||
import i18n from "i18n-js";
|
import i18n from "i18n-js";
|
||||||
|
import NotificationsManager from '../utils/NotificationsManager'
|
||||||
import { Notifications } from 'expo';
|
import { Notifications } from 'expo';
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ export default class HomeScreen extends React.Component {
|
||||||
<Container>
|
<Container>
|
||||||
<CustomHeader navigation={nav} title={i18n.t('screens.home')}/>
|
<CustomHeader navigation={nav} title={i18n.t('screens.home')}/>
|
||||||
<Content padder>
|
<Content padder>
|
||||||
<Button>
|
<Button onPress={() => NotificationsManager.sendNotificationImmediately('coucou', 'whoa')}>
|
||||||
<Icon
|
<Icon
|
||||||
active
|
active
|
||||||
name={'bell-ring'}
|
name={'bell-ring'}
|
||||||
|
|
|
@ -54,7 +54,6 @@ export default class ProximoMainScreen extends React.Component {
|
||||||
this.setState({data: undefined});
|
this.setState({data: undefined});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,46 +80,44 @@ export default class ProximoMainScreen extends React.Component {
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<CustomHeader navigation={nav} title={'Proximo'}/>
|
<CustomHeader navigation={nav} title={'Proximo'}/>
|
||||||
<Content>
|
<FlatList
|
||||||
<FlatList
|
data={this.state.data}
|
||||||
data={this.state.data}
|
extraData={this.state}
|
||||||
extraData={this.state}
|
keyExtractor={(item, index) => item.type}
|
||||||
keyExtractor={(item, index) => item.type}
|
refreshControl={
|
||||||
refreshControl={
|
<RefreshControl
|
||||||
<RefreshControl
|
refreshing={this.state.refreshing}
|
||||||
refreshing={this.state.refreshing}
|
onRefresh={this._onRefresh}
|
||||||
onRefresh={this._onRefresh}
|
/>
|
||||||
/>
|
}
|
||||||
}
|
style={{minHeight: 300, width: '100%'}}
|
||||||
style={{minHeight: 300, width: '100%'}}
|
renderItem={({item}) =>
|
||||||
renderItem={({item}) =>
|
<ListItem
|
||||||
<ListItem
|
button
|
||||||
button
|
thumbnail
|
||||||
thumbnail
|
onPress={() => {
|
||||||
onPress={() => {
|
nav.navigate('ProximoListScreen', item);
|
||||||
nav.navigate('ProximoListScreen', item);
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<Left>
|
||||||
<Left>
|
<Icon name={typesIcons[item.type] ? typesIcons[item.type] : typesIcons.Default}
|
||||||
<Icon name={typesIcons[item.type] ? typesIcons[item.type] : typesIcons.Default}
|
type={'MaterialCommunityIcons'}
|
||||||
type={'MaterialCommunityIcons'}
|
style={styles.icon}/>
|
||||||
style={styles.icon}/>
|
</Left>
|
||||||
</Left>
|
<Body>
|
||||||
<Body>
|
<Text>
|
||||||
<Text>
|
{item.type}
|
||||||
{item.type}
|
</Text>
|
||||||
</Text>
|
<Badge><Text>
|
||||||
<Badge><Text>
|
{item.data.length} {item.data.length > 1 ? i18n.t('proximoScreen.articles') : i18n.t('proximoScreen.article')}
|
||||||
{item.data.length} {item.data.length > 1 ? i18n.t('proximoScreen.articles') : i18n.t('proximoScreen.article')}
|
</Text></Badge>
|
||||||
</Text></Badge>
|
</Body>
|
||||||
</Body>
|
<Right>
|
||||||
<Right>
|
<Icon name="chevron-right"
|
||||||
<Icon name="chevron-right"
|
type={'MaterialCommunityIcons'}/>
|
||||||
type={'MaterialCommunityIcons'}/>
|
</Right>
|
||||||
</Right>
|
</ListItem>}
|
||||||
</ListItem>}
|
/>
|
||||||
/>
|
|
||||||
</Content>
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,240 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {StyleSheet, View} from 'react-native';
|
import {SectionList, RefreshControl, StyleSheet, View, ScrollView} from 'react-native';
|
||||||
import {Container, Text} from 'native-base';
|
import {Badge, Body, Container, Content, Icon, Left, ListItem, Right, Text, Toast, H2, Button} from 'native-base';
|
||||||
import CustomHeader from "../components/CustomHeader";
|
import CustomHeader from "../components/CustomHeader";
|
||||||
|
import NotificationsManager from '../utils/NotificationsManager';
|
||||||
|
import i18n from "i18n-js";
|
||||||
|
import {AsyncStorage} from 'react-native'
|
||||||
|
|
||||||
|
const DATA_URL = "https://etud.insa-toulouse.fr/~vergnet/appli-amicale/dataProxiwash.json";
|
||||||
|
const WATCHED_MACHINES_PREFKEY = "proxiwash.watchedMachines";
|
||||||
|
|
||||||
|
const remainderNotifTime = 5;
|
||||||
|
|
||||||
|
const MACHINE_STATES = {
|
||||||
|
TERMINE: "0",
|
||||||
|
DISPONIBLE: "1",
|
||||||
|
FONCTIONNE: "2",
|
||||||
|
HS: "3",
|
||||||
|
ERREUR: "4"
|
||||||
|
};
|
||||||
|
|
||||||
|
let stateStrings = {};
|
||||||
|
|
||||||
|
let stateColors = {};
|
||||||
|
|
||||||
|
|
||||||
export default class ProxiwashScreen extends React.Component {
|
export default class ProxiwashScreen extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
stateColors[MACHINE_STATES.TERMINE] = 'rgba(54,165,22,0.4)';
|
||||||
|
stateColors[MACHINE_STATES.DISPONIBLE] = '#ffffff';
|
||||||
|
stateColors[MACHINE_STATES.FONCTIONNE] = 'rgba(241,237,41,0.4)';
|
||||||
|
stateColors[MACHINE_STATES.HS] = '#a2a2a2';
|
||||||
|
stateColors[MACHINE_STATES.ERREUR] = 'rgba(204,7,0,0.4)';
|
||||||
|
|
||||||
|
stateStrings[MACHINE_STATES.TERMINE] = i18n.t('proxiwashScreen.states.finished');
|
||||||
|
stateStrings[MACHINE_STATES.DISPONIBLE] = i18n.t('proxiwashScreen.states.ready');
|
||||||
|
stateStrings[MACHINE_STATES.FONCTIONNE] = i18n.t('proxiwashScreen.states.running');
|
||||||
|
stateStrings[MACHINE_STATES.HS] = i18n.t('proxiwashScreen.states.broken');
|
||||||
|
stateStrings[MACHINE_STATES.ERREUR] = i18n.t('proxiwashScreen.states.error');
|
||||||
|
this.state = {
|
||||||
|
refreshing: false,
|
||||||
|
data: {},
|
||||||
|
machinesWatched: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async readData() {
|
||||||
|
try {
|
||||||
|
let response = await fetch(DATA_URL);
|
||||||
|
let responseJson = await response.json();
|
||||||
|
// This prevents end notifications from showing
|
||||||
|
// let watchList = this.state.machinesWatched;
|
||||||
|
// for (let i = 0; i < watchList.length; i++) {
|
||||||
|
// if (responseJson[MACHINE_STATES[watchList[i].machineNumber.state]] !== MACHINE_STATES.FONCTIONNE)
|
||||||
|
// this.disableNotification(watchList[i].machineNumber);
|
||||||
|
// }
|
||||||
|
this.setState({
|
||||||
|
data: responseJson
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentWillMount() {
|
||||||
|
let dataString = await AsyncStorage.getItem(WATCHED_MACHINES_PREFKEY);
|
||||||
|
if (dataString === null)
|
||||||
|
dataString = '[]';
|
||||||
|
this.setState({machinesWatched: JSON.parse(dataString)});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this._onRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
_onRefresh = () => {
|
||||||
|
this.setState({refreshing: true});
|
||||||
|
this.readData().then(() => {
|
||||||
|
this.setState({refreshing: false});
|
||||||
|
Toast.show({
|
||||||
|
text: i18n.t('proxiwashScreen.listUpdated'),
|
||||||
|
buttonText: 'OK',
|
||||||
|
type: "success",
|
||||||
|
duration: 2000
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
static getRemainingTime(startString, endString, percentDone) {
|
||||||
|
let startArray = startString.split(':');
|
||||||
|
let endArray = endString.split(':');
|
||||||
|
let startDate = new Date();
|
||||||
|
startDate.setHours(parseInt(startArray[0]), parseInt(startArray[1]), 0, 0);
|
||||||
|
let endDate = new Date();
|
||||||
|
endDate.setHours(parseInt(endArray[0]), parseInt(endArray[1]), 0, 0);
|
||||||
|
return (((100 - percentDone) / 100) * (endDate - startDate) / (60 * 1000)).toFixed(0); // Convert milliseconds into minutes
|
||||||
|
}
|
||||||
|
|
||||||
|
async setupNotifications(number, remainingTime) {
|
||||||
|
if (!this.isMachineWatched(number)) {
|
||||||
|
let endNotifID = await NotificationsManager.scheduleNotification(
|
||||||
|
i18n.t('proxiwashScreen.notifications.machineFinishedTitle'),
|
||||||
|
i18n.t('proxiwashScreen.notifications.machineFinishedBody', {number: number}),
|
||||||
|
new Date().getTime() + remainingTime * (60 * 1000) // Convert back to milliseconds
|
||||||
|
);
|
||||||
|
let remainderNotifID = undefined;
|
||||||
|
if (remainingTime > remainderNotifTime) {
|
||||||
|
remainderNotifID = await NotificationsManager.scheduleNotification(
|
||||||
|
i18n.t('proxiwashScreen.notifications.machineRunningTitle', {time: remainderNotifTime}),
|
||||||
|
i18n.t('proxiwashScreen.notifications.machineRunningBody', {number: number}),
|
||||||
|
new Date().getTime() + (remainingTime - remainderNotifTime) * (60 * 1000) // Convert back to milliseconds
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let data = this.state.machinesWatched;
|
||||||
|
data.push({machineNumber: number, endNotifID: endNotifID, remainderNotifID: remainderNotifID});
|
||||||
|
this.setState({machinesWatched: data});
|
||||||
|
AsyncStorage.setItem(WATCHED_MACHINES_PREFKEY, JSON.stringify(data));
|
||||||
|
} else
|
||||||
|
this.disableNotification(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
disableNotification(number) {
|
||||||
|
let data = this.state.machinesWatched;
|
||||||
|
if (data.length > 0) {
|
||||||
|
let elem = this.state.machinesWatched.find(function (elem) {
|
||||||
|
return elem.machineNumber === number
|
||||||
|
});
|
||||||
|
let arrayIndex = data.indexOf(elem);
|
||||||
|
NotificationsManager.cancelScheduledNoification(data[arrayIndex].endNotifID);
|
||||||
|
if (data[arrayIndex].remainderNotifID !== undefined)
|
||||||
|
NotificationsManager.cancelScheduledNoification(data[arrayIndex].remainderNotifID);
|
||||||
|
data.splice(arrayIndex, 1);
|
||||||
|
this.setState({machinesWatched: data});
|
||||||
|
AsyncStorage.setItem(WATCHED_MACHINES_PREFKEY, JSON.stringify(data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isMachineWatched(number) {
|
||||||
|
return this.state.machinesWatched.find(function (elem) {
|
||||||
|
return elem.machineNumber === number
|
||||||
|
}) !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderItem(item, section, data) {
|
||||||
|
return (
|
||||||
|
<ListItem
|
||||||
|
thumbnail
|
||||||
|
style={{
|
||||||
|
marginLeft: 0,
|
||||||
|
backgroundColor: stateColors[MACHINE_STATES[item.state]]
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={{
|
||||||
|
height: '100%',
|
||||||
|
position: 'absolute',
|
||||||
|
alignSelf: 'flex-end',
|
||||||
|
right: 0,
|
||||||
|
width: item.donePercent !== '' ? (100 - parseInt(item.donePercent)).toString() + '%' : 0,
|
||||||
|
backgroundColor: '#fff'
|
||||||
|
}}>
|
||||||
|
</View>
|
||||||
|
<Left>
|
||||||
|
<Icon name={section.title === data[0].title ? 'tumble-dryer' : 'washing-machine'}
|
||||||
|
type={'MaterialCommunityIcons'}
|
||||||
|
style={{fontSize: 30, width: 30}}
|
||||||
|
/>
|
||||||
|
</Left>
|
||||||
|
<Body>
|
||||||
|
<Text>
|
||||||
|
{section.title === data[0].title ? i18n.t('proxiwashScreen.dryer') : i18n.t('proxiwashScreen.washer')} n°{item.number}
|
||||||
|
</Text>
|
||||||
|
<Text note>
|
||||||
|
{item.startTime !== '' ? item.startTime + '/' + item.endTime : ''}
|
||||||
|
</Text>
|
||||||
|
</Body>
|
||||||
|
<Right>
|
||||||
|
{item.startTime !== '' ?
|
||||||
|
<Button
|
||||||
|
style={this.isMachineWatched(item.number) ?
|
||||||
|
{backgroundColor: '#ba7c1f'} : {}}
|
||||||
|
onPress={() => {
|
||||||
|
this.setupNotifications(item.number, ProxiwashScreen.getRemainingTime(item.startTime, item.endTime, item.donePercent))
|
||||||
|
}}>
|
||||||
|
<Text>
|
||||||
|
{ProxiwashScreen.getRemainingTime(item.startTime, item.endTime, item.donePercent) + ' ' + i18n.t('proxiwashScreen.min')}
|
||||||
|
</Text>
|
||||||
|
<Icon name={this.isMachineWatched(item.number) ? 'bell-ring' : 'bell'}
|
||||||
|
type={'MaterialCommunityIcons'}
|
||||||
|
style={{fontSize: 30, width: 30}}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
: <Text style={MACHINE_STATES[item.state] === MACHINE_STATES.TERMINE ?
|
||||||
|
{fontWeight: 'bold'} : {}}
|
||||||
|
>{stateStrings[MACHINE_STATES[item.state]]}</Text>
|
||||||
|
|
||||||
|
}
|
||||||
|
</Right>
|
||||||
|
</ListItem>);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const nav = this.props.navigation;
|
const nav = this.props.navigation;
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
title: i18n.t('proxiwashScreen.dryers'),
|
||||||
|
data: this.state.data.dryers === undefined ? [] : this.state.data.dryers,
|
||||||
|
extraData: this.state
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: i18n.t('proxiwashScreen.washers'),
|
||||||
|
data: this.state.data.washers === undefined ? [] : this.state.data.washers,
|
||||||
|
extraData: this.state
|
||||||
|
},
|
||||||
|
];
|
||||||
|
console.log(this.state.machinesWatched);
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<CustomHeader navigation={nav} title={'Proxiwash'}/>
|
<CustomHeader navigation={nav} title={'Proxiwash'}/>
|
||||||
|
<SectionList
|
||||||
|
sections={data}
|
||||||
|
keyExtractor={(item) => item.number}
|
||||||
|
refreshControl={
|
||||||
|
<RefreshControl
|
||||||
|
refreshing={this.state.refreshing}
|
||||||
|
onRefresh={this._onRefresh}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
renderSectionHeader={({section: {title}}) => (
|
||||||
|
<H2 style={{textAlign: 'center', paddingVertical: 10}}>{title}</H2>
|
||||||
|
)}
|
||||||
|
renderItem={({item, section}) =>
|
||||||
|
this.renderItem(item, section, data)
|
||||||
|
}
|
||||||
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
flex: 1,
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -28,5 +28,26 @@
|
||||||
"sortName": "Sort by name",
|
"sortName": "Sort by name",
|
||||||
"sortPrice": "Sort by price",
|
"sortPrice": "Sort by price",
|
||||||
"listUpdated": "Article list updated!"
|
"listUpdated": "Article list updated!"
|
||||||
|
},
|
||||||
|
"proxiwashScreen": {
|
||||||
|
"dryer": "Dryer",
|
||||||
|
"dryers": "Dryers",
|
||||||
|
"washer": "Washer",
|
||||||
|
"washers": "Washers",
|
||||||
|
"min": "min",
|
||||||
|
"listUpdated": "Machines state updated",
|
||||||
|
"states": {
|
||||||
|
"finished": "FINISHED",
|
||||||
|
"ready": "READY",
|
||||||
|
"running": "RUNNING",
|
||||||
|
"broken": "BROKEN",
|
||||||
|
"error": "ERROR"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"machineFinishedTitle": "Laundry Ready",
|
||||||
|
"machineFinishedBody": "The machine n°{{number}} is finished and your laundry is ready to pickup",
|
||||||
|
"machineRunningTitle": "Laundry running: {{time}} minutes left",
|
||||||
|
"machineRunningBody": "The machine n°{{number}} is still running"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,5 +28,26 @@
|
||||||
"sortName": "Trier par nom",
|
"sortName": "Trier par nom",
|
||||||
"sortPrice": "Trier par prix",
|
"sortPrice": "Trier par prix",
|
||||||
"listUpdated": "Liste des articles mise à jour !"
|
"listUpdated": "Liste des articles mise à jour !"
|
||||||
|
},
|
||||||
|
"proxiwashScreen": {
|
||||||
|
"dryer": "Sèche Linge",
|
||||||
|
"dryers": "Sèche Linges",
|
||||||
|
"washer": "Lave Linge",
|
||||||
|
"washers": "Lave Linges",
|
||||||
|
"min": "min",
|
||||||
|
"listUpdated": "Etat des machines mis à jour",
|
||||||
|
"states": {
|
||||||
|
"finished": "TERMINE",
|
||||||
|
"ready": "DISPONIBLE",
|
||||||
|
"running": "En COURS",
|
||||||
|
"broken": "HORS SERVICE",
|
||||||
|
"error": "ERREUR"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"machineFinishedTitle": "Linge prêt",
|
||||||
|
"machineFinishedBody": "La machine n°{{number}} est terminée et votre linge est prêt à être récupéré",
|
||||||
|
"machineRunningTitle": "Machine en cours: {{time}} minutes restantes",
|
||||||
|
"machineRunningBody": "La machine n°{{number}} n'est pas encore terminée"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
40
utils/NotificationsManager.js
Normal file
40
utils/NotificationsManager.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import * as Permissions from 'expo-permissions';
|
||||||
|
import { Notifications } from 'expo';
|
||||||
|
|
||||||
|
export default class NotificationsManager {
|
||||||
|
|
||||||
|
static async askPermissions() {
|
||||||
|
const {status: existingStatus} = await Permissions.getAsync(Permissions.NOTIFICATIONS);
|
||||||
|
let finalStatus = existingStatus;
|
||||||
|
if (existingStatus !== 'granted') {
|
||||||
|
const {status} = await Permissions.askAsync(Permissions.NOTIFICATIONS);
|
||||||
|
finalStatus = status;
|
||||||
|
}
|
||||||
|
return finalStatus === 'granted';
|
||||||
|
}
|
||||||
|
|
||||||
|
static async sendNotificationImmediately (title, body) {
|
||||||
|
await NotificationsManager.askPermissions();
|
||||||
|
return await Notifications.presentLocalNotificationAsync({
|
||||||
|
title: title,
|
||||||
|
body: body,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
static async scheduleNotification(title, body, time) {
|
||||||
|
await NotificationsManager.askPermissions();
|
||||||
|
return Notifications.scheduleLocalNotificationAsync(
|
||||||
|
{
|
||||||
|
title: title,
|
||||||
|
body: body,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
time: time,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
static async cancelScheduledNoification(notifID) {
|
||||||
|
await Notifications.cancelScheduledNotificationAsync(notifID);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
import {DefaultTheme} from 'react-native-paper';
|
|
||||||
import {AsyncStorage} from 'react-native'
|
import {AsyncStorage} from 'react-native'
|
||||||
import platform from '../native-base-theme/variables/platform';
|
import platform from '../native-base-theme/variables/platform';
|
||||||
import platformDark from '../native-base-theme/variables/platformDark';
|
import platformDark from '../native-base-theme/variables/platformDark';
|
||||||
|
|
Loading…
Reference in a new issue