Browse Source

Improved settings screen elements

Arnaud Vergnet 3 years ago
parent
commit
0b7191887d

+ 1
- 0
package.json View File

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

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

@@ -18,7 +18,7 @@ type Props = {
18 18
 }
19 19
 
20 20
 type State = {
21
-    expanded: boolean
21
+    expanded: boolean,
22 22
 }
23 23
 
24 24
 const AnimatedListIcon = Animatable.createAnimatableComponent(List.Icon);
@@ -56,16 +56,14 @@ class AnimatedAccordion extends React.Component<Props, State> {
56 56
     }
57 57
 
58 58
     toggleAccordion = () => {
59
-        if (this.chevronRef.current != null)
59
+        if (this.chevronRef.current != null) {
60 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 69
     render() {

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

@@ -0,0 +1,58 @@
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,39 +1,47 @@
1 1
 // @flow
2 2
 
3 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 6
 import ThemeManager from '../../managers/ThemeManager';
6 7
 import i18n from "i18n-js";
7 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 10
 import {Appearance} from "react-native-appearance";
10
-import AnimatedAccordion from "../../components/Animations/AnimatedAccordion";
11
+import CustomSlider from "../../components/Overrides/CustomSlider";
11 12
 
12 13
 type Props = {
13
-    navigation: Object,
14
+    theme: CustomTheme,
14 15
 };
15 16
 
16 17
 type State = {
17 18
     nightMode: boolean,
18 19
     nightModeFollowSystem: boolean,
19
-    proxiwashNotifPickerSelected: string,
20
+    notificationReminderSelected: number,
20 21
     startScreenPickerSelected: string,
21 22
 };
22 23
 
23 24
 /**
24 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 31
     constructor() {
36 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,14 +49,10 @@ export default class SettingsScreen extends React.Component<Props, State> {
41 49
      *
42 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,15 +77,16 @@ export default class SettingsScreen extends React.Component<Props, State> {
73 77
      */
74 78
     getProxiwashNotifPicker() {
75 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 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,6 +138,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
133 138
      * @param icon The icon name to display on the list item
134 139
      * @param title The text to display as this list item title
135 140
      * @param subtitle The text to display as this list item subtitle
141
+     * @param state The current state of the switch
136 142
      * @returns {React.Node}
137 143
      */
138 144
     getToggleItem(onPressCallback: Function, icon: string, title: string, subtitle: string, state: boolean) {
@@ -141,7 +147,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
141 147
                 title={title}
142 148
                 description={subtitle}
143 149
                 left={props => <List.Icon {...props} icon={icon}/>}
144
-                right={props =>
150
+                right={() =>
145 151
                     <Switch
146 152
                         value={state}
147 153
                         onValueChange={onPressCallback}
@@ -177,28 +183,31 @@ export default class SettingsScreen extends React.Component<Props, State> {
177 183
                                     this.state.nightMode
178 184
                                 ) : null
179 185
                         }
180
-                        <AnimatedAccordion
186
+                        <List.Item
181 187
                             title={i18n.t('settingsScreen.startScreen')}
182 188
                             subtitle={i18n.t('settingsScreen.startScreenSub')}
183 189
                             left={props => <List.Icon {...props} icon="power"/>}
184
-                        >
185
-                            {this.getStartScreenPicker()}
186
-                        </AnimatedAccordion>
190
+                        />
191
+                        {this.getStartScreenPicker()}
187 192
                     </List.Section>
188 193
                 </Card>
189 194
                 <Card style={{margin: 5}}>
190 195
                     <Card.Title title="Proxiwash"/>
191 196
                     <List.Section>
192
-                        <AnimatedAccordion
197
+                        <List.Item
193 198
                             title={i18n.t('settingsScreen.proxiwashNotifReminder')}
194 199
                             description={i18n.t('settingsScreen.proxiwashNotifReminderSub')}
195 200
                             left={props => <List.Icon {...props} icon="washing-machine"/>}
196
-                        >
201
+                            opened={true}
202
+                        />
203
+                        <View style={{marginLeft: 30}}>
197 204
                             {this.getProxiwashNotifPicker()}
198
-                        </AnimatedAccordion>
205
+                        </View>
199 206
                     </List.Section>
200 207
                 </Card>
201 208
             </ScrollView>
202 209
         );
203 210
     }
204 211
 }
212
+
213
+export default withTheme(SettingsScreen);

Loading…
Cancel
Save