Browse Source

Improved settings screen elements

Arnaud Vergnet 4 years ago
parent
commit
0b7191887d

+ 1
- 0
package.json View File

22
     "@nartc/react-native-barcode-mask": "^1.1.9",
22
     "@nartc/react-native-barcode-mask": "^1.1.9",
23
     "@react-native-community/masked-view": "0.1.6",
23
     "@react-native-community/masked-view": "0.1.6",
24
     "@react-native-community/push-notification-ios": "^1.1.1",
24
     "@react-native-community/push-notification-ios": "^1.1.1",
25
+    "@react-native-community/slider": "^2.0.9",
25
     "@react-navigation/bottom-tabs": "^5.1.1",
26
     "@react-navigation/bottom-tabs": "^5.1.1",
26
     "@react-navigation/drawer": "^5.1.1",
27
     "@react-navigation/drawer": "^5.1.1",
27
     "@react-navigation/native": "^5.0.9",
28
     "@react-navigation/native": "^5.0.9",

+ 6
- 8
src/components/Animations/AnimatedAccordion.js View File

18
 }
18
 }
19
 
19
 
20
 type State = {
20
 type State = {
21
-    expanded: boolean
21
+    expanded: boolean,
22
 }
22
 }
23
 
23
 
24
 const AnimatedListIcon = Animatable.createAnimatableComponent(List.Icon);
24
 const AnimatedListIcon = Animatable.createAnimatableComponent(List.Icon);
56
     }
56
     }
57
 
57
 
58
     toggleAccordion = () => {
58
     toggleAccordion = () => {
59
-        if (this.chevronRef.current != null)
59
+        if (this.chevronRef.current != null) {
60
             this.chevronRef.current.transitionTo({rotate: this.state.expanded ? this.animStart : this.animEnd});
60
             this.chevronRef.current.transitionTo({rotate: this.state.expanded ? this.animStart : this.animEnd});
61
-        this.setState({expanded: !this.state.expanded})
61
+            this.setState({expanded: !this.state.expanded})
62
+        }
62
     };
63
     };
63
 
64
 
64
-    shouldComponentUpdate(nextProps: Props) {
65
-        if (nextProps.opened != null)
66
-            this.state.expanded = nextProps.opened;
67
-        this.setupChevron();
68
-        return true;
65
+    shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
66
+        return nextState.expanded !== this.state.expanded;
69
     }
67
     }
70
 
68
 
71
     render() {
69
     render() {

+ 58
- 0
src/components/Overrides/CustomSlider.js View File

1
+// @flow
2
+
3
+import * as React from 'react';
4
+import {Text, withTheme} from 'react-native-paper';
5
+import {View} from "react-native-animatable";
6
+import type {CustomTheme} from "../../managers/ThemeManager";
7
+import Slider, {SliderProps} from "@react-native-community/slider";
8
+
9
+type Props = {
10
+    theme: CustomTheme,
11
+    valueSuffix: string,
12
+    ...SliderProps
13
+}
14
+
15
+type State = {
16
+    currentValue: number,
17
+}
18
+
19
+/**
20
+ * Abstraction layer for Modalize component, using custom configuration
21
+ *
22
+ * @param props Props to pass to the element. Must specify an onRef prop to get an Modalize ref.
23
+ * @return {*}
24
+ */
25
+class CustomSlider extends React.Component<Props, State> {
26
+
27
+    static defaultProps = {
28
+        valueSuffix: "",
29
+    }
30
+
31
+    state = {
32
+        currentValue: this.props.value,
33
+    }
34
+
35
+    onValueChange = (value: number) => {
36
+        this.setState({currentValue: value});
37
+        if (this.props.onValueChange != null)
38
+            this.props.onValueChange(value);
39
+    }
40
+
41
+    render() {
42
+        return (
43
+            <View style={{flex: 1, flexDirection: 'row'}}>
44
+                <Text style={{marginHorizontal: 10, marginTop: 'auto', marginBottom: 'auto'}}>
45
+                    {this.state.currentValue}min
46
+                </Text>
47
+                <Slider
48
+                    {...this.props}
49
+                    onValueChange={this.onValueChange}
50
+                />
51
+            </View>
52
+        );
53
+    }
54
+
55
+}
56
+
57
+export default withTheme(CustomSlider);
58
+

+ 46
- 37
src/screens/Other/SettingsScreen.js View File

1
 // @flow
1
 // @flow
2
 
2
 
3
 import * as React from 'react';
3
 import * as React from 'react';
4
-import {ScrollView} from "react-native";
4
+import {ScrollView, View} from "react-native";
5
+import type {CustomTheme} from "../../managers/ThemeManager";
5
 import ThemeManager from '../../managers/ThemeManager';
6
 import ThemeManager from '../../managers/ThemeManager';
6
 import i18n from "i18n-js";
7
 import i18n from "i18n-js";
7
 import AsyncStorageManager from "../../managers/AsyncStorageManager";
8
 import AsyncStorageManager from "../../managers/AsyncStorageManager";
8
-import {Card, List, Switch, ToggleButton} from 'react-native-paper';
9
+import {Card, List, Switch, ToggleButton, withTheme} from 'react-native-paper';
9
 import {Appearance} from "react-native-appearance";
10
 import {Appearance} from "react-native-appearance";
10
-import AnimatedAccordion from "../../components/Animations/AnimatedAccordion";
11
+import CustomSlider from "../../components/Overrides/CustomSlider";
11
 
12
 
12
 type Props = {
13
 type Props = {
13
-    navigation: Object,
14
+    theme: CustomTheme,
14
 };
15
 };
15
 
16
 
16
 type State = {
17
 type State = {
17
     nightMode: boolean,
18
     nightMode: boolean,
18
     nightModeFollowSystem: boolean,
19
     nightModeFollowSystem: boolean,
19
-    proxiwashNotifPickerSelected: string,
20
+    notificationReminderSelected: number,
20
     startScreenPickerSelected: string,
21
     startScreenPickerSelected: string,
21
 };
22
 };
22
 
23
 
23
 /**
24
 /**
24
  * Class defining the Settings screen. This screen shows controls to modify app preferences.
25
  * Class defining the Settings screen. This screen shows controls to modify app preferences.
25
  */
26
  */
26
-export default class SettingsScreen extends React.Component<Props, State> {
27
-    state = {
28
-        nightMode: ThemeManager.getNightMode(),
29
-        nightModeFollowSystem: AsyncStorageManager.getInstance().preferences.nightModeFollowSystem.current === '1' &&
30
-            Appearance.getColorScheme() !== 'no-preference',
31
-        proxiwashNotifPickerSelected: AsyncStorageManager.getInstance().preferences.proxiwashNotifications.current,
32
-        startScreenPickerSelected: AsyncStorageManager.getInstance().preferences.defaultStartScreen.current,
33
-    };
27
+class SettingsScreen extends React.Component<Props, State> {
28
+
29
+    savedNotificationReminder: number;
34
 
30
 
35
     constructor() {
31
     constructor() {
36
         super();
32
         super();
33
+        let notifReminder = AsyncStorageManager.getInstance().preferences.proxiwashNotifications.current;
34
+        this.savedNotificationReminder = parseInt(notifReminder);
35
+        if (isNaN(this.savedNotificationReminder))
36
+            this.savedNotificationReminder = 0;
37
+
38
+        this.state = {
39
+            nightMode: ThemeManager.getNightMode(),
40
+            nightModeFollowSystem: AsyncStorageManager.getInstance().preferences.nightModeFollowSystem.current === '1' &&
41
+                Appearance.getColorScheme() !== 'no-preference',
42
+            notificationReminderSelected: this.savedNotificationReminder,
43
+            startScreenPickerSelected: AsyncStorageManager.getInstance().preferences.defaultStartScreen.current,
44
+        };
37
     }
45
     }
38
 
46
 
39
     /**
47
     /**
41
      *
49
      *
42
      * @param value The value to store
50
      * @param value The value to store
43
      */
51
      */
44
-    onProxiwashNotifPickerValueChange = (value: string) => {
45
-        if (value != null) {
46
-            let key = AsyncStorageManager.getInstance().preferences.proxiwashNotifications.key;
47
-            AsyncStorageManager.getInstance().savePref(key, value);
48
-            this.setState({
49
-                proxiwashNotifPickerSelected: value
50
-            });
51
-        }
52
+    onProxiwashNotifPickerValueChange = (value: number) => {
53
+        let key = AsyncStorageManager.getInstance().preferences.proxiwashNotifications.key;
54
+        AsyncStorageManager.getInstance().savePref(key, value.toString());
55
+        this.setState({notificationReminderSelected: value})
52
     };
56
     };
53
 
57
 
54
     /**
58
     /**
73
      */
77
      */
74
     getProxiwashNotifPicker() {
78
     getProxiwashNotifPicker() {
75
         return (
79
         return (
76
-            <ToggleButton.Row
80
+            <CustomSlider
81
+                style={{flex: 1, marginHorizontal: 10, height: 50}}
82
+                minimumValue={0}
83
+                maximumValue={10}
84
+                step={1}
85
+                value={this.savedNotificationReminder}
77
                 onValueChange={this.onProxiwashNotifPickerValueChange}
86
                 onValueChange={this.onProxiwashNotifPickerValueChange}
78
-                value={this.state.proxiwashNotifPickerSelected}
79
-                style={{marginLeft: 'auto', marginRight: 'auto'}}
80
-            >
81
-                <ToggleButton icon="close" value="never"/>
82
-                <ToggleButton icon="numeric-2" value="2"/>
83
-                <ToggleButton icon="numeric-5" value="5"/>
84
-            </ToggleButton.Row>
87
+                thumbTintColor={this.props.theme.colors.primary}
88
+                minimumTrackTintColor={this.props.theme.colors.primary}
89
+            />
85
         );
90
         );
86
     }
91
     }
87
 
92
 
133
      * @param icon The icon name to display on the list item
138
      * @param icon The icon name to display on the list item
134
      * @param title The text to display as this list item title
139
      * @param title The text to display as this list item title
135
      * @param subtitle The text to display as this list item subtitle
140
      * @param subtitle The text to display as this list item subtitle
141
+     * @param state The current state of the switch
136
      * @returns {React.Node}
142
      * @returns {React.Node}
137
      */
143
      */
138
     getToggleItem(onPressCallback: Function, icon: string, title: string, subtitle: string, state: boolean) {
144
     getToggleItem(onPressCallback: Function, icon: string, title: string, subtitle: string, state: boolean) {
141
                 title={title}
147
                 title={title}
142
                 description={subtitle}
148
                 description={subtitle}
143
                 left={props => <List.Icon {...props} icon={icon}/>}
149
                 left={props => <List.Icon {...props} icon={icon}/>}
144
-                right={props =>
150
+                right={() =>
145
                     <Switch
151
                     <Switch
146
                         value={state}
152
                         value={state}
147
                         onValueChange={onPressCallback}
153
                         onValueChange={onPressCallback}
177
                                     this.state.nightMode
183
                                     this.state.nightMode
178
                                 ) : null
184
                                 ) : null
179
                         }
185
                         }
180
-                        <AnimatedAccordion
186
+                        <List.Item
181
                             title={i18n.t('settingsScreen.startScreen')}
187
                             title={i18n.t('settingsScreen.startScreen')}
182
                             subtitle={i18n.t('settingsScreen.startScreenSub')}
188
                             subtitle={i18n.t('settingsScreen.startScreenSub')}
183
                             left={props => <List.Icon {...props} icon="power"/>}
189
                             left={props => <List.Icon {...props} icon="power"/>}
184
-                        >
185
-                            {this.getStartScreenPicker()}
186
-                        </AnimatedAccordion>
190
+                        />
191
+                        {this.getStartScreenPicker()}
187
                     </List.Section>
192
                     </List.Section>
188
                 </Card>
193
                 </Card>
189
                 <Card style={{margin: 5}}>
194
                 <Card style={{margin: 5}}>
190
                     <Card.Title title="Proxiwash"/>
195
                     <Card.Title title="Proxiwash"/>
191
                     <List.Section>
196
                     <List.Section>
192
-                        <AnimatedAccordion
197
+                        <List.Item
193
                             title={i18n.t('settingsScreen.proxiwashNotifReminder')}
198
                             title={i18n.t('settingsScreen.proxiwashNotifReminder')}
194
                             description={i18n.t('settingsScreen.proxiwashNotifReminderSub')}
199
                             description={i18n.t('settingsScreen.proxiwashNotifReminderSub')}
195
                             left={props => <List.Icon {...props} icon="washing-machine"/>}
200
                             left={props => <List.Icon {...props} icon="washing-machine"/>}
196
-                        >
201
+                            opened={true}
202
+                        />
203
+                        <View style={{marginLeft: 30}}>
197
                             {this.getProxiwashNotifPicker()}
204
                             {this.getProxiwashNotifPicker()}
198
-                        </AnimatedAccordion>
205
+                        </View>
199
                     </List.Section>
206
                     </List.Section>
200
                 </Card>
207
                 </Card>
201
             </ScrollView>
208
             </ScrollView>
202
         );
209
         );
203
     }
210
     }
204
 }
211
 }
212
+
213
+export default withTheme(SettingsScreen);

Loading…
Cancel
Save