Added setting to set proxiwash reminder notification

This commit is contained in:
keplyx 2019-06-28 13:47:52 +02:00
parent 7cd543ac74
commit f2cd3bec0d
11 changed files with 224 additions and 50 deletions

7
App.js
View file

@ -35,8 +35,7 @@ export default class App extends React.Component {
} }
updateTheme() { updateTheme() {
console.log('update theme called'); // console.log('update theme called');
// Change not propagating, need to restart the app
this.setState({ this.setState({
currentTheme: ThemeManager.getInstance().getCurrentTheme() currentTheme: ThemeManager.getInstance().getCurrentTheme()
}); });
@ -47,8 +46,8 @@ export default class App extends React.Component {
if (this.state.isLoading) { if (this.state.isLoading) {
return <View/>; return <View/>;
} }
console.log('rendering'); // console.log('rendering');
console.log(this.state.currentTheme.variables.containerBgColor); // console.log(this.state.currentTheme.variables.containerBgColor);
return ( return (
<Root> <Root>
<StyleProvider style={this.state.currentTheme}> <StyleProvider style={this.state.currentTheme}>

View file

@ -1,6 +1,6 @@
{ {
"expo": { "expo": {
"name": "Application Amicale", "name": "Amicale INSAT",
"slug": "application-amicale", "slug": "application-amicale",
"privacy": "public", "privacy": "public",
"sdkVersion": "33.0.0", "sdkVersion": "33.0.0",
@ -15,7 +15,7 @@
"primaryColor": "#e42612", "primaryColor": "#e42612",
"splash": { "splash": {
"image": "./assets/splash.png", "image": "./assets/splash.png",
"resizeMode": "contain", "resizeMode": "cover",
"backgroundColor": "#fff" "backgroundColor": "#fff"
}, },
"updates": { "updates": {

View file

@ -118,7 +118,7 @@ export default {
containerBgColor: "#333333", containerBgColor: "#333333",
//Date Picker //Date Picker
datePickerTextColor: "#000", datePickerTextColor: "#fff",
datePickerBg: "transparent", datePickerBg: "transparent",
// Font // Font

19
package-lock.json generated
View file

@ -1782,6 +1782,11 @@
} }
} }
}, },
"base-64": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz",
"integrity": "sha1-eAqZyE59YAJgNhURxId2E78k9rs="
},
"base64-js": { "base64-js": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
@ -6253,6 +6258,15 @@
} }
} }
}, },
"react-native-fs": {
"version": "2.13.3",
"resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.13.3.tgz",
"integrity": "sha512-B62LSSAEYQGItg7KVTzTVVCxezOYFBYp4DMVFbdoZUd1mZVFdqR2sy1HY1mye1VI/Lf3IbxSyZEQ0GmrrdwLjg==",
"requires": {
"base-64": "^0.1.0",
"utf8": "^2.1.1"
}
},
"react-native-gesture-handler": { "react-native-gesture-handler": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-1.2.1.tgz", "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-1.2.1.tgz",
@ -8374,6 +8388,11 @@
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
}, },
"utf8": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz",
"integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY="
},
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",

View file

@ -22,6 +22,7 @@
"react-dom": "^16.8.6", "react-dom": "^16.8.6",
"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-fs": "^2.13.3",
"react-native-paper": "latest", "react-native-paper": "latest",
"react-native-platform-touchable": "latest", "react-native-platform-touchable": "latest",
"react-native-settings-page": "latest", "react-native-settings-page": "latest",

View file

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import {StyleSheet, RefreshControl, FlatList} from 'react-native'; import {RefreshControl, SectionList} from 'react-native';
import {Container, Text, Content, ListItem, Left, Right, Body, Badge, Icon, Toast} from 'native-base'; import {Container, Text, Content, ListItem, Left, Right, Body, Badge, Icon, Toast, H2} from 'native-base';
import CustomHeader from "../../components/CustomHeader"; import CustomHeader from "../../components/CustomHeader";
import i18n from "i18n-js"; import i18n from "i18n-js";
import CustomMaterialIcon from "../../components/CustomMaterialIcon"; import CustomMaterialIcon from "../../components/CustomMaterialIcon";
@ -82,12 +82,24 @@ export default class ProximoMainScreen extends React.Component {
render() { render() {
const nav = this.props.navigation; const nav = this.props.navigation;
const data = [
{
title: i18n.t('proximoScreen.listTitle'),
data: this.state.data,
extraData: this.state,
}
];
const loadingData = [
{
title: i18n.t('proximoScreen.loading'),
data: []
}
];
return ( return (
<Container> <Container>
<CustomHeader navigation={nav} title={'Proximo'}/> <CustomHeader navigation={nav} title={'Proximo'}/>
<FlatList <SectionList
data={this.state.data} sections={this.state.firstLoading ? loadingData : data}
extraData={this.state}
keyExtractor={(item, index) => item.type} keyExtractor={(item, index) => item.type}
refreshControl={ refreshControl={
<RefreshControl <RefreshControl
@ -96,6 +108,9 @@ export default class ProximoMainScreen extends React.Component {
/> />
} }
style={{minHeight: 300, width: '100%'}} style={{minHeight: 300, width: '100%'}}
renderSectionHeader={({section: {title}}) => (
<H2 style={{textAlign: 'center', paddingVertical: 10}}>{title}</H2>
)}
renderItem={({item}) => renderItem={({item}) =>
<ListItem <ListItem
button button

View file

@ -11,7 +11,7 @@ import CustomMaterialIcon from "../components/CustomMaterialIcon";
const DATA_URL = "https://etud.insa-toulouse.fr/~vergnet/appli-amicale/dataProxiwash.json"; const DATA_URL = "https://etud.insa-toulouse.fr/~vergnet/appli-amicale/dataProxiwash.json";
const WATCHED_MACHINES_PREFKEY = "proxiwash.watchedMachines"; const WATCHED_MACHINES_PREFKEY = "proxiwash.watchedMachines";
const remainderNotifTime = 5; let reminderNotifTime = 5;
const MACHINE_STATES = { const MACHINE_STATES = {
TERMINE: "0", TERMINE: "0",
@ -72,9 +72,12 @@ export default class ProxiwashScreen extends React.Component {
let dataString = await AsyncStorage.getItem(WATCHED_MACHINES_PREFKEY); let dataString = await AsyncStorage.getItem(WATCHED_MACHINES_PREFKEY);
if (dataString === null) if (dataString === null)
dataString = '[]'; dataString = '[]';
this.setState({machinesWatched: JSON.parse(dataString)}); this.setState({
machinesWatched: JSON.parse(dataString)
});
} }
componentDidMount() { componentDidMount() {
this._onRefresh(); this._onRefresh();
} }
@ -112,16 +115,24 @@ export default class ProxiwashScreen extends React.Component {
i18n.t('proxiwashScreen.notifications.machineFinishedBody', {number: number}), i18n.t('proxiwashScreen.notifications.machineFinishedBody', {number: number}),
new Date().getTime() + remainingTime * (60 * 1000) // Convert back to milliseconds new Date().getTime() + remainingTime * (60 * 1000) // Convert back to milliseconds
); );
let remainderNotifID = undefined; let reminderNotifID = undefined;
if (remainingTime > remainderNotifTime) { let val = await AsyncStorage.getItem('proxiwashNotifKey');
remainderNotifID = await NotificationsManager.scheduleNotification( if (val === null)
i18n.t('proxiwashScreen.notifications.machineRunningTitle', {time: remainderNotifTime}), val = "5";
if (val !== "never")
reminderNotifTime = parseInt(val);
else
reminderNotifTime = -1;
console.log(reminderNotifTime);
if (remainingTime > reminderNotifTime && reminderNotifTime > 0) {
reminderNotifID = await NotificationsManager.scheduleNotification(
i18n.t('proxiwashScreen.notifications.machineRunningTitle', {time: reminderNotifTime}),
i18n.t('proxiwashScreen.notifications.machineRunningBody', {number: number}), i18n.t('proxiwashScreen.notifications.machineRunningBody', {number: number}),
new Date().getTime() + (remainingTime - remainderNotifTime) * (60 * 1000) // Convert back to milliseconds new Date().getTime() + (remainingTime - reminderNotifTime) * (60 * 1000) // Convert back to milliseconds
); );
} }
let data = this.state.machinesWatched; let data = this.state.machinesWatched;
data.push({machineNumber: number, endNotifID: endNotifID, remainderNotifID: remainderNotifID}); data.push({machineNumber: number, endNotifID: endNotifID, reminderNotifID: reminderNotifID});
this.setState({machinesWatched: data}); this.setState({machinesWatched: data});
AsyncStorage.setItem(WATCHED_MACHINES_PREFKEY, JSON.stringify(data)); AsyncStorage.setItem(WATCHED_MACHINES_PREFKEY, JSON.stringify(data));
} else } else
@ -136,8 +147,8 @@ export default class ProxiwashScreen extends React.Component {
}); });
let arrayIndex = data.indexOf(elem); let arrayIndex = data.indexOf(elem);
NotificationsManager.cancelScheduledNoification(data[arrayIndex].endNotifID); NotificationsManager.cancelScheduledNoification(data[arrayIndex].endNotifID);
if (data[arrayIndex].remainderNotifID !== undefined) if (data[arrayIndex].reminderNotifID !== undefined)
NotificationsManager.cancelScheduledNoification(data[arrayIndex].remainderNotifID); NotificationsManager.cancelScheduledNoification(data[arrayIndex].reminderNotifID);
data.splice(arrayIndex, 1); data.splice(arrayIndex, 1);
this.setState({machinesWatched: data}); this.setState({machinesWatched: data});
AsyncStorage.setItem(WATCHED_MACHINES_PREFKEY, JSON.stringify(data)); AsyncStorage.setItem(WATCHED_MACHINES_PREFKEY, JSON.stringify(data));

View file

@ -1,22 +1,74 @@
import React from 'react'; import React from 'react';
import {Container, Content, Left, ListItem, Right, Text, List, CheckBox, Button} from "native-base"; import {
Container,
Content,
Left,
ListItem,
Right,
Text,
List,
CheckBox,
Body,
CardItem,
Card,
Picker,
} from "native-base";
import CustomHeader from "../components/CustomHeader"; 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"; import {NavigationActions, StackActions} from "react-navigation";
import CustomMaterialIcon from "../components/CustomMaterialIcon"; import CustomMaterialIcon from "../components/CustomMaterialIcon";
import {AsyncStorage} from 'react-native'
const proxiwashNotifKey = "proxiwashNotifKey";
const nightModeKey = 'nightMode';
export default class SettingsScreen extends React.Component { export default class SettingsScreen extends React.Component {
state = { state = {
nightMode: ThemeManager.getInstance().getNightMode(), nightMode: ThemeManager.getInstance().getNightMode(),
proxiwashNotifPickerSelected: "5"
}; };
async componentWillMount() {
let val = await AsyncStorage.getItem(proxiwashNotifKey);
if (val === null)
val = "5";
this.setState({
proxiwashNotifPickerSelected: val,
});
}
onProxiwashNotidPickerValueChange(value) {
AsyncStorage.setItem(proxiwashNotifKey, value);
this.setState({
proxiwashNotifPickerSelected: value
});
}
getproxiwashNotifPicker() {
return (
<Picker
note
mode="dropdown"
style={{width: 120}}
selectedValue={this.state.proxiwashNotifPickerSelected}
onValueChange={(value) => this.onProxiwashNotidPickerValueChange(value)}
>
<Picker.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.never')} value="never"/>
<Picker.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.1')} value="1"/>
<Picker.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.2')} value="2"/>
<Picker.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.3')} value="3"/>
<Picker.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.5')} value="5"/>
<Picker.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.10')} value="10"/>
<Picker.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.20')} value="20"/>
<Picker.Item label={i18n.t('settingsScreen.proxiwashNotifReminderPicker.30')} value="30"/>
</Picker>
);
}
toggleNightMode() { toggleNightMode() {
this.setState({nightMode: !this.state.nightMode});
ThemeManager.getInstance().setNightmode(!this.state.nightMode); ThemeManager.getInstance().setNightmode(!this.state.nightMode);
this.setState({nightMode: !this.state.nightMode});
// Alert.alert(i18n.t('settingsScreen.nightMode'), i18n.t('settingsScreen.restart')); // Alert.alert(i18n.t('settingsScreen.nightMode'), i18n.t('settingsScreen.restart'));
this.resetStack(); this.resetStack();
} }
@ -25,35 +77,84 @@ export default class SettingsScreen extends React.Component {
const resetAction = StackActions.reset({ const resetAction = StackActions.reset({
index: 0, index: 0,
key: null, key: null,
actions: [NavigationActions.navigate({ routeName: 'Main' })], actions: [NavigationActions.navigate({routeName: 'Main'})],
}); });
this.props.navigation.dispatch(resetAction); this.props.navigation.dispatch(resetAction);
this.props.navigation.navigate('Settings'); this.props.navigation.navigate('Settings');
} }
getToggleItem(onPressCallback, icon, text, subtitle) {
return (
<ListItem
button
thumbnail
onPress={onPressCallback}
>
<Left>
<CustomMaterialIcon icon={icon}/>
</Left>
<Body>
<Text>
{text}
</Text>
<Text note>
{subtitle}
</Text>
</Body>
<Right style={{flex: 1}}>
<CheckBox checked={this.state.nightMode}
onPress={() => this.toggleNightMode()}/>
</Right>
</ListItem>
);
}
getGeneralItem(control, icon, text, subtitle) {
return (
<ListItem
thumbnail
>
<Left>
<CustomMaterialIcon icon={icon}/>
</Left>
<Body>
<Text>
{text}
</Text>
<Text note>
{subtitle}
</Text>
</Body>
<Right style={{flex: 1}}>
{control}
</Right>
</ListItem>
);
}
render() { render() {
const nav = this.props.navigation; const nav = this.props.navigation;
return ( return (
<Container> <Container>
<CustomHeader navigation={nav} title={i18n.t('screens.settings')}/> <CustomHeader navigation={nav} title={i18n.t('screens.settings')}/>
<Content> <Content>
<List> <Card>
<ListItem <CardItem header>
button <Text>{i18n.t('settingsScreen.appearanceCard')}</Text>
onPress={() => this.toggleNightMode()} </CardItem>
> <List>
<Left> {this.getToggleItem(() => this.toggleNightMode(), 'theme-light-dark', i18n.t('settingsScreen.nightMode'), i18n.t('settingsScreen.nightModeSub'))}
<CustomMaterialIcon icon={'theme-light-dark'} /> </List>
<Text> </Card>
{i18n.t('settingsScreen.nightMode')} <Card>
</Text> <CardItem header>
</Left> <Text>Proxiwash</Text>
<Right style={{flex: 1}}> </CardItem>
<CheckBox checked={this.state.nightMode} <List>
onPress={() => this.toggleNightMode()}/> {this.getGeneralItem(this.getproxiwashNotifPicker(), 'washing-machine', i18n.t('settingsScreen.proxiwashNotifReminder'), i18n.t('settingsScreen.proxiwashNotifReminderSub'))}
</Right> </List>
</ListItem> </Card>
</List>
</Content> </Content>
</Container> </Container>

View file

@ -6,8 +6,21 @@
"about": "About" "about": "About"
}, },
"settingsScreen": { "settingsScreen": {
"appearanceCard": "Appearance",
"nightMode": "Night Mode", "nightMode": "Night Mode",
"restart": "Restart the app to apply changes" "nightModeSub": "Switch the app to a dark or light theme",
"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"
}
}, },
"aboutScreen": { "aboutScreen": {
"appstore": "See on the Appstore", "appstore": "See on the Appstore",
@ -27,7 +40,9 @@
"articles": "Articles", "articles": "Articles",
"sortName": "Sort by name", "sortName": "Sort by name",
"sortPrice": "Sort by price", "sortPrice": "Sort by price",
"listUpdated": "Article list updated!" "listUpdated": "Article list updated!",
"loading": "Loading...",
"listTitle": "Choose a category"
}, },
"proxiwashScreen": { "proxiwashScreen": {
"dryer": "Dryer", "dryer": "Dryer",

View file

@ -6,8 +6,21 @@
"about": "À Propos" "about": "À Propos"
}, },
"settingsScreen": { "settingsScreen": {
"appearanceCard": "Apparence",
"nightMode": "Mode Nuit", "nightMode": "Mode Nuit",
"restart": "Redémarrez l'application pour appliquer les changements" "nightModeSub": "Passer l'application dans un thème sombre ou clair",
"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"
}
}, },
"aboutScreen": { "aboutScreen": {
"appstore": "Voir sur l'Appstore", "appstore": "Voir sur l'Appstore",
@ -27,7 +40,9 @@
"articles": "Articles", "articles": "Articles",
"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 !",
"loading": "Chargement...",
"listTitle": "Choisissez une catégorie"
}, },
"proxiwashScreen": { "proxiwashScreen": {
"dryer": "Sèche Linge", "dryer": "Sèche Linge",

View file

@ -23,8 +23,6 @@ export default class ThemeManager {
setUpdateThemeCallback(callback) { setUpdateThemeCallback(callback) {
this.updateThemeCallback = callback; this.updateThemeCallback = callback;
console.log(this.updateThemeCallback);
} }
async getDataFromPreferences() { async getDataFromPreferences() {