Browse Source

Move preferences in separate contextes

This improves performance when updating preferences
Arnaud Vergnet 6 months ago
parent
commit
acbbd2d27d

+ 84
- 16
App.tsx View File

@@ -27,12 +27,26 @@ import URLHandler from './src/utils/URLHandler';
27 27
 import initLocales from './src/utils/Locales';
28 28
 import { NavigationContainerRef } from '@react-navigation/core';
29 29
 import {
30
+  defaultMascotPreferences,
31
+  defaultPlanexPreferences,
30 32
   defaultPreferences,
31
-  PreferenceKeys,
32
-  PreferencesType,
33
+  defaultProxiwashPreferences,
34
+  GeneralPreferenceKeys,
35
+  GeneralPreferencesType,
36
+  MascotPreferenceKeys,
37
+  MascotPreferencesType,
38
+  PlanexPreferenceKeys,
39
+  PlanexPreferencesType,
40
+  ProxiwashPreferenceKeys,
41
+  ProxiwashPreferencesType,
33 42
   retrievePreferences,
34 43
 } from './src/utils/asyncStorage';
35
-import PreferencesProvider from './src/components/providers/PreferencesProvider';
44
+import {
45
+  GeneralPreferencesProvider,
46
+  MascotPreferencesProvider,
47
+  PlanexPreferencesProvider,
48
+  ProxiwashPreferencesProvider,
49
+} from './src/components/providers/PreferencesProvider';
36 50
 import MainApp from './src/screens/MainApp';
37 51
 
38 52
 // Native optimizations https://reactnavigation.org/docs/react-native-screens
@@ -45,9 +59,16 @@ LogBox.ignoreLogs([
45 59
   'Cannot update a component from inside the function body of a different component',
46 60
 ]);
47 61
 
62
+// TODO move preferences in smaller contextes for improved performances
63
+
48 64
 type StateType = {
49 65
   isLoading: boolean;
50
-  initialPreferences: PreferencesType;
66
+  initialPreferences: {
67
+    general: GeneralPreferencesType;
68
+    planex: PlanexPreferencesType;
69
+    proxiwash: ProxiwashPreferencesType;
70
+    mascot: MascotPreferencesType;
71
+  };
51 72
 };
52 73
 
53 74
 export default class App extends React.Component<{}, StateType> {
@@ -63,7 +84,12 @@ export default class App extends React.Component<{}, StateType> {
63 84
     super(props);
64 85
     this.state = {
65 86
       isLoading: true,
66
-      initialPreferences: defaultPreferences,
87
+      initialPreferences: {
88
+        general: defaultPreferences,
89
+        planex: defaultPlanexPreferences,
90
+        proxiwash: defaultProxiwashPreferences,
91
+        mascot: defaultMascotPreferences,
92
+      },
67 93
     };
68 94
     initLocales();
69 95
     this.navigatorRef = React.createRef();
@@ -106,11 +132,24 @@ export default class App extends React.Component<{}, StateType> {
106 132
   /**
107 133
    * Async loading is done, finish processing startup data
108 134
    */
109
-  onLoadFinished = (values: Array<PreferencesType | void>) => {
110
-    const [preferences] = values;
135
+  onLoadFinished = (
136
+    values: Array<
137
+      | GeneralPreferencesType
138
+      | PlanexPreferencesType
139
+      | ProxiwashPreferencesType
140
+      | MascotPreferencesType
141
+      | void
142
+    >
143
+  ) => {
144
+    const [general, planex, proxiwash, mascot] = values;
111 145
     this.setState({
112 146
       isLoading: false,
113
-      initialPreferences: { ...(preferences as PreferencesType) },
147
+      initialPreferences: {
148
+        general: general as GeneralPreferencesType,
149
+        planex: planex as PlanexPreferencesType,
150
+        proxiwash: proxiwash as ProxiwashPreferencesType,
151
+        mascot: mascot as MascotPreferencesType,
152
+      },
114 153
     });
115 154
     SplashScreen.hide();
116 155
   };
@@ -122,7 +161,22 @@ export default class App extends React.Component<{}, StateType> {
122 161
    */
123 162
   loadAssetsAsync() {
124 163
     Promise.all([
125
-      retrievePreferences(Object.values(PreferenceKeys), defaultPreferences),
164
+      retrievePreferences(
165
+        Object.values(GeneralPreferenceKeys),
166
+        defaultPreferences
167
+      ),
168
+      retrievePreferences(
169
+        Object.values(PlanexPreferenceKeys),
170
+        defaultPlanexPreferences
171
+      ),
172
+      retrievePreferences(
173
+        Object.values(ProxiwashPreferenceKeys),
174
+        defaultProxiwashPreferences
175
+      ),
176
+      retrievePreferences(
177
+        Object.values(MascotPreferenceKeys),
178
+        defaultMascotPreferences
179
+      ),
126 180
       ConnectionManager.getInstance().recoverLogin(),
127 181
     ])
128 182
       .then(this.onLoadFinished)
@@ -138,13 +192,27 @@ export default class App extends React.Component<{}, StateType> {
138 192
       return null;
139 193
     }
140 194
     return (
141
-      <PreferencesProvider initialPreferences={this.state.initialPreferences}>
142
-        <MainApp
143
-          ref={this.navigatorRef}
144
-          defaultHomeData={this.defaultHomeData}
145
-          defaultHomeRoute={this.defaultHomeRoute}
146
-        />
147
-      </PreferencesProvider>
195
+      <GeneralPreferencesProvider
196
+        initialPreferences={this.state.initialPreferences.general}
197
+      >
198
+        <PlanexPreferencesProvider
199
+          initialPreferences={this.state.initialPreferences.planex}
200
+        >
201
+          <ProxiwashPreferencesProvider
202
+            initialPreferences={this.state.initialPreferences.proxiwash}
203
+          >
204
+            <MascotPreferencesProvider
205
+              initialPreferences={this.state.initialPreferences.mascot}
206
+            >
207
+              <MainApp
208
+                ref={this.navigatorRef}
209
+                defaultHomeData={this.defaultHomeData}
210
+                defaultHomeRoute={this.defaultHomeRoute}
211
+              />
212
+            </MascotPreferencesProvider>
213
+          </ProxiwashPreferencesProvider>
214
+        </PlanexPreferencesProvider>
215
+      </GeneralPreferencesProvider>
148 216
     );
149 217
   }
150 218
 }

+ 144
- 38
src/components/providers/PreferencesProvider.tsx View File

@@ -1,67 +1,173 @@
1 1
 import React, { useState } from 'react';
2 2
 import {
3
+  defaultMascotPreferences,
4
+  defaultPlanexPreferences,
3 5
   defaultPreferences,
6
+  defaultProxiwashPreferences,
7
+  GeneralPreferenceKeys,
8
+  GeneralPreferencesType,
9
+  MascotPreferenceKeys,
10
+  MascotPreferencesType,
11
+  PlanexPreferenceKeys,
12
+  PlanexPreferencesType,
4 13
   PreferenceKeys,
5 14
   PreferencesType,
15
+  ProxiwashPreferenceKeys,
16
+  ProxiwashPreferencesType,
6 17
   setPreference,
7 18
 } from '../../utils/asyncStorage';
8 19
 import {
20
+  MascotPreferencesContext,
21
+  PlanexPreferencesContext,
9 22
   PreferencesContext,
10 23
   PreferencesContextType,
24
+  ProxiwashPreferencesContext,
11 25
 } from '../../context/preferencesContext';
12 26
 
13
-type Props = {
14
-  children: React.ReactChild;
15
-  initialPreferences: PreferencesType;
16
-};
27
+function updateState<T extends Partial<PreferencesType>, K extends string>(
28
+  key: K,
29
+  value: number | string | boolean | object | Array<any>,
30
+  prevState: PreferencesContextType<T, K>
31
+) {
32
+  const prevPreferences = { ...prevState.preferences };
33
+  const newPrefs = setPreference(key as PreferenceKeys, value, prevPreferences);
34
+  const newSate = {
35
+    ...prevState,
36
+    preferences: { ...newPrefs },
37
+  };
38
+  return newSate;
39
+}
17 40
 
18
-export default function PreferencesProvider(props: Props) {
41
+function resetState<
42
+  T extends Partial<PreferencesType>,
43
+  K extends Partial<PreferenceKeys>
44
+>(
45
+  keys: Array<PreferenceKeys>,
46
+  defaults: T,
47
+  prevState: PreferencesContextType<T, K>
48
+) {
49
+  const prevPreferences = { ...prevState.preferences };
50
+  let newPreferences = { ...prevPreferences };
51
+  keys.forEach((key) => {
52
+    newPreferences = setPreference(key, defaults[key], prevPreferences);
53
+  });
54
+  const newSate = {
55
+    ...prevState,
56
+    preferences: { ...newPreferences },
57
+  };
58
+  return newSate;
59
+}
60
+
61
+function usePreferencesProvider<
62
+  T extends Partial<PreferencesType>,
63
+  K extends Partial<PreferenceKeys>
64
+>(initialPreferences: T, defaults: T, keys: Array<K>) {
19 65
   const updatePreferences = (
20
-    key: PreferenceKeys,
66
+    key: K,
21 67
     value: number | string | boolean | object | Array<any>
22 68
   ) => {
23
-    setPreferencesState((prevState) => {
24
-      const prevPreferences = { ...prevState.preferences };
25
-      const newPrefs = setPreference(key, value, prevPreferences);
26
-      const newSate = {
27
-        ...prevState,
28
-        preferences: { ...newPrefs },
29
-      };
30
-      return newSate;
31
-    });
69
+    setPreferencesState((prevState) => updateState(key, value, prevState));
32 70
   };
33 71
 
34 72
   const resetPreferences = () => {
35
-    setPreferencesState((prevState) => {
36
-      const prevPreferences = { ...prevState.preferences };
37
-      let newPreferences = { ...prevPreferences };
38
-      Object.values(PreferenceKeys).forEach((key) => {
39
-        newPreferences = setPreference(
40
-          key,
41
-          defaultPreferences[key],
42
-          prevPreferences
43
-        );
44
-      });
45
-      const newSate = {
46
-        ...prevState,
47
-        preferences: { ...newPreferences },
48
-      };
49
-      return newSate;
50
-    });
73
+    setPreferencesState((prevState) => resetState(keys, defaults, prevState));
51 74
   };
52 75
 
53
-  const [
54
-    preferencesState,
55
-    setPreferencesState,
56
-  ] = useState<PreferencesContextType>({
57
-    preferences: { ...props.initialPreferences },
76
+  const [preferencesState, setPreferencesState] = useState<
77
+    PreferencesContextType<T, K>
78
+  >({
79
+    preferences: { ...initialPreferences },
58 80
     updatePreferences: updatePreferences,
59 81
     resetPreferences: resetPreferences,
60 82
   });
83
+  return preferencesState;
84
+}
85
+
86
+type PreferencesProviderProps<
87
+  T extends Partial<PreferencesType>,
88
+  K extends Partial<PreferenceKeys>
89
+> = {
90
+  children: React.ReactChild;
91
+  initialPreferences: T;
92
+  defaults: T;
93
+  keys: Array<K>;
94
+  Context: React.Context<PreferencesContextType<T, K>>;
95
+};
96
+
97
+function PreferencesProvider<
98
+  T extends Partial<PreferencesType>,
99
+  K extends Partial<PreferenceKeys>
100
+>(props: PreferencesProviderProps<T, K>) {
101
+  const { Context } = props;
102
+  const preferencesState = usePreferencesProvider<T, K>(
103
+    props.initialPreferences,
104
+    props.defaults,
105
+    Object.values(props.keys)
106
+  );
107
+  return (
108
+    <Context.Provider value={preferencesState}>
109
+      {props.children}
110
+    </Context.Provider>
111
+  );
112
+}
113
+
114
+type Props<T> = {
115
+  children: React.ReactChild;
116
+  initialPreferences: T;
117
+};
118
+
119
+export function GeneralPreferencesProvider(
120
+  props: Props<GeneralPreferencesType>
121
+) {
122
+  return (
123
+    <PreferencesProvider
124
+      Context={PreferencesContext}
125
+      initialPreferences={props.initialPreferences}
126
+      defaults={defaultPreferences}
127
+      keys={Object.values(GeneralPreferenceKeys)}
128
+    >
129
+      {props.children}
130
+    </PreferencesProvider>
131
+  );
132
+}
133
+
134
+export function PlanexPreferencesProvider(props: Props<PlanexPreferencesType>) {
135
+  return (
136
+    <PreferencesProvider
137
+      Context={PlanexPreferencesContext}
138
+      initialPreferences={props.initialPreferences}
139
+      defaults={defaultPlanexPreferences}
140
+      keys={Object.values(PlanexPreferenceKeys)}
141
+    >
142
+      {props.children}
143
+    </PreferencesProvider>
144
+  );
145
+}
146
+
147
+export function ProxiwashPreferencesProvider(
148
+  props: Props<ProxiwashPreferencesType>
149
+) {
150
+  return (
151
+    <PreferencesProvider
152
+      Context={ProxiwashPreferencesContext}
153
+      initialPreferences={props.initialPreferences}
154
+      defaults={defaultProxiwashPreferences}
155
+      keys={Object.values(ProxiwashPreferenceKeys)}
156
+    >
157
+      {props.children}
158
+    </PreferencesProvider>
159
+  );
160
+}
61 161
 
162
+export function MascotPreferencesProvider(props: Props<MascotPreferencesType>) {
62 163
   return (
63
-    <PreferencesContext.Provider value={preferencesState}>
164
+    <PreferencesProvider
165
+      Context={MascotPreferencesContext}
166
+      initialPreferences={props.initialPreferences}
167
+      defaults={defaultMascotPreferences}
168
+      keys={Object.values(MascotPreferenceKeys)}
169
+    >
64 170
       {props.children}
65
-    </PreferencesContext.Provider>
171
+    </PreferencesProvider>
66 172
   );
67 173
 }

+ 79
- 16
src/context/preferencesContext.tsx View File

@@ -2,11 +2,21 @@ import { useNavigation } from '@react-navigation/core';
2 2
 import React, { useContext } from 'react';
3 3
 import { Appearance } from 'react-native-appearance';
4 4
 import {
5
+  defaultMascotPreferences,
6
+  defaultPlanexPreferences,
5 7
   defaultPreferences,
8
+  defaultProxiwashPreferences,
6 9
   getPreferenceBool,
7 10
   getPreferenceObject,
8
-  isValidPreferenceKey,
9
-  PreferenceKeys,
11
+  MascotPreferenceKeys,
12
+  MascotPreferencesType,
13
+  PlanexPreferenceKeys,
14
+  PlanexPreferencesType,
15
+  GeneralPreferenceKeys,
16
+  GeneralPreferencesType,
17
+  ProxiwashPreferenceKeys,
18
+  ProxiwashPreferencesType,
19
+  isValidMascotPreferenceKey,
10 20
   PreferencesType,
11 21
 } from '../utils/asyncStorage';
12 22
 import {
@@ -18,35 +28,83 @@ import {
18 28
 
19 29
 const colorScheme = Appearance.getColorScheme();
20 30
 
21
-export type PreferencesContextType = {
22
-  preferences: PreferencesType;
31
+export type PreferencesContextType<
32
+  T extends Partial<PreferencesType>,
33
+  K extends string
34
+> = {
35
+  preferences: T;
23 36
   updatePreferences: (
24
-    key: PreferenceKeys,
37
+    key: K,
25 38
     value: number | string | boolean | object | Array<any>
26 39
   ) => void;
27 40
   resetPreferences: () => void;
28 41
 };
29 42
 
30
-export const PreferencesContext = React.createContext<PreferencesContextType>({
43
+// CONTEXTES
44
+// Preferences are separated into several contextes to improve performances
45
+
46
+export const PreferencesContext = React.createContext<
47
+  PreferencesContextType<GeneralPreferencesType, GeneralPreferenceKeys>
48
+>({
31 49
   preferences: defaultPreferences,
32 50
   updatePreferences: () => undefined,
33 51
   resetPreferences: () => undefined,
34 52
 });
35 53
 
54
+export const PlanexPreferencesContext = React.createContext<
55
+  PreferencesContextType<PlanexPreferencesType, PlanexPreferenceKeys>
56
+>({
57
+  preferences: defaultPlanexPreferences,
58
+  updatePreferences: () => undefined,
59
+  resetPreferences: () => undefined,
60
+});
61
+
62
+export const ProxiwashPreferencesContext = React.createContext<
63
+  PreferencesContextType<ProxiwashPreferencesType, ProxiwashPreferenceKeys>
64
+>({
65
+  preferences: defaultProxiwashPreferences,
66
+  updatePreferences: () => undefined,
67
+  resetPreferences: () => undefined,
68
+});
69
+
70
+export const MascotPreferencesContext = React.createContext<
71
+  PreferencesContextType<MascotPreferencesType, MascotPreferenceKeys>
72
+>({
73
+  preferences: defaultMascotPreferences,
74
+  updatePreferences: () => undefined,
75
+  resetPreferences: () => undefined,
76
+});
77
+
78
+// Context Hooks
79
+
36 80
 export function usePreferences() {
37 81
   return useContext(PreferencesContext);
38 82
 }
39 83
 
84
+export function usePlanexPreferences() {
85
+  return useContext(PlanexPreferencesContext);
86
+}
87
+
88
+export function useProxiwashPreferences() {
89
+  return useContext(ProxiwashPreferencesContext);
90
+}
91
+
92
+export function useMascotPreferences() {
93
+  return useContext(MascotPreferencesContext);
94
+}
95
+
96
+// Custom Hooks
97
+
40 98
 export function useShouldShowMascot(route: string) {
41
-  const { preferences, updatePreferences } = usePreferences();
99
+  const { preferences, updatePreferences } = useMascotPreferences();
42 100
   const key = route + 'ShowMascot';
43 101
   let shouldShow = false;
44
-  if (isValidPreferenceKey(key)) {
102
+  if (isValidMascotPreferenceKey(key)) {
45 103
     shouldShow = getPreferenceBool(key, preferences) !== false;
46 104
   }
47 105
 
48 106
   const setShouldShow = (show: boolean) => {
49
-    if (isValidPreferenceKey(key)) {
107
+    if (isValidMascotPreferenceKey(key)) {
50 108
       updatePreferences(key, show);
51 109
     } else {
52 110
       console.log('Invalid preference key: ' + key);
@@ -59,12 +117,17 @@ export function useShouldShowMascot(route: string) {
59 117
 export function useDarkTheme() {
60 118
   const { preferences } = usePreferences();
61 119
   return (
62
-    (getPreferenceBool(PreferenceKeys.nightMode, preferences) !== false &&
63
-      (getPreferenceBool(PreferenceKeys.nightModeFollowSystem, preferences) ===
64
-        false ||
65
-        colorScheme === 'no-preference')) ||
66
-    (getPreferenceBool(PreferenceKeys.nightModeFollowSystem, preferences) !==
120
+    (getPreferenceBool(GeneralPreferenceKeys.nightMode, preferences) !==
67 121
       false &&
122
+      (getPreferenceBool(
123
+        GeneralPreferenceKeys.nightModeFollowSystem,
124
+        preferences
125
+      ) === false ||
126
+        colorScheme === 'no-preference')) ||
127
+    (getPreferenceBool(
128
+      GeneralPreferenceKeys.nightModeFollowSystem,
129
+      preferences
130
+    ) !== false &&
68 131
       colorScheme === 'dark')
69 132
   );
70 133
 }
@@ -73,12 +136,12 @@ export function useCurrentDashboard() {
73 136
   const { preferences, updatePreferences } = usePreferences();
74 137
   const navigation = useNavigation();
75 138
   const dashboardIdList = getPreferenceObject(
76
-    PreferenceKeys.dashboardItems,
139
+    GeneralPreferenceKeys.dashboardItems,
77 140
     preferences
78 141
   ) as Array<string>;
79 142
 
80 143
   const updateCurrentDashboard = (newList: Array<string>) => {
81
-    updatePreferences(PreferenceKeys.dashboardItems, newList);
144
+    updatePreferences(GeneralPreferenceKeys.dashboardItems, newList);
82 145
   };
83 146
 
84 147
   const allDatasets = [

+ 8
- 2
src/navigation/MainNavigator.tsx View File

@@ -47,7 +47,10 @@ import DashboardEditScreen from '../screens/Other/Settings/DashboardEditScreen';
47 47
 import GameStartScreen from '../screens/Game/screens/GameStartScreen';
48 48
 import ImageGalleryScreen from '../screens/Media/ImageGalleryScreen';
49 49
 import { usePreferences } from '../context/preferencesContext';
50
-import { getPreferenceBool, PreferenceKeys } from '../utils/asyncStorage';
50
+import {
51
+  getPreferenceBool,
52
+  GeneralPreferenceKeys,
53
+} from '../utils/asyncStorage';
51 54
 import IntroScreen from '../screens/Intro/IntroScreen';
52 55
 
53 56
 export enum MainRoutes {
@@ -319,7 +322,10 @@ type PropsType = {
319 322
 
320 323
 function MainNavigator(props: PropsType) {
321 324
   const { preferences } = usePreferences();
322
-  const showIntro = getPreferenceBool(PreferenceKeys.showIntro, preferences);
325
+  const showIntro = getPreferenceBool(
326
+    GeneralPreferenceKeys.showIntro,
327
+    preferences
328
+  );
323 329
   const createTabNavigator = () => <TabNavigator {...props} />;
324 330
   return (
325 331
     <MainStackComponent

+ 5
- 2
src/navigation/TabNavigator.tsx View File

@@ -41,7 +41,10 @@ import ServicesSectionScreen from '../screens/Services/ServicesSectionScreen';
41 41
 import AmicaleContactScreen from '../screens/Amicale/AmicaleContactScreen';
42 42
 import Mascot, { MASCOT_STYLE } from '../components/Mascot/Mascot';
43 43
 import { usePreferences } from '../context/preferencesContext';
44
-import { getPreferenceString, PreferenceKeys } from '../utils/asyncStorage';
44
+import {
45
+  getPreferenceString,
46
+  GeneralPreferenceKeys,
47
+} from '../utils/asyncStorage';
45 48
 
46 49
 const styles = StyleSheet.create({
47 50
   header: {
@@ -267,7 +270,7 @@ const ICONS: {
267 270
 function TabNavigator(props: PropsType) {
268 271
   const { preferences } = usePreferences();
269 272
   let defaultRoute = getPreferenceString(
270
-    PreferenceKeys.defaultStartScreen,
273
+    GeneralPreferenceKeys.defaultStartScreen,
271 274
     preferences
272 275
   );
273 276
   if (!defaultRoute) {

+ 4
- 4
src/screens/About/DebugScreen.tsx View File

@@ -33,8 +33,8 @@ import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatLis
33 33
 import { usePreferences } from '../../context/preferencesContext';
34 34
 import {
35 35
   defaultPreferences,
36
-  isValidPreferenceKey,
37
-  PreferenceKeys,
36
+  GeneralPreferenceKeys,
37
+  isValidGeneralPreferenceKey,
38 38
 } from '../../utils/asyncStorage';
39 39
 
40 40
 type PreferenceItemType = {
@@ -70,7 +70,7 @@ function DebugScreen() {
70 70
   ] = useState<PreferenceItemType | null>(null);
71 71
 
72 72
   const currentPreferences: Array<PreferenceItemType> = [];
73
-  Object.values(PreferenceKeys).forEach((key) => {
73
+  Object.values(GeneralPreferenceKeys).forEach((key) => {
74 74
     const newObject: PreferenceItemType = {
75 75
       key: key,
76 76
       current: preferences[key],
@@ -141,7 +141,7 @@ function DebugScreen() {
141 141
   };
142 142
 
143 143
   const saveNewPrefs = (key: string, value: string) => {
144
-    if (isValidPreferenceKey(key)) {
144
+    if (isValidGeneralPreferenceKey(key)) {
145 145
       updatePreferences(key, value);
146 146
     }
147 147
     if (modalRef.current) {

+ 10
- 8
src/screens/Intro/IntroScreen.tsx View File

@@ -6,29 +6,31 @@ import AprilFoolsManager from '../../managers/AprilFoolsManager';
6 6
 import {
7 7
   getPreferenceBool,
8 8
   getPreferenceNumber,
9
-  PreferenceKeys,
9
+  GeneralPreferenceKeys,
10 10
 } from '../../utils/asyncStorage';
11 11
 
12 12
 export default function IntroScreen() {
13 13
   const { preferences, updatePreferences } = usePreferences();
14 14
 
15 15
   const onDone = () => {
16
-    updatePreferences(PreferenceKeys.showIntro, false);
17
-    updatePreferences(PreferenceKeys.updateNumber, Update.number);
18
-    updatePreferences(PreferenceKeys.showAprilFoolsStart, false);
16
+    updatePreferences(GeneralPreferenceKeys.showIntro, false);
17
+    updatePreferences(GeneralPreferenceKeys.updateNumber, Update.number);
18
+    updatePreferences(GeneralPreferenceKeys.showAprilFoolsStart, false);
19 19
   };
20 20
 
21 21
   const showIntro =
22
-    getPreferenceBool(PreferenceKeys.showIntro, preferences) !== false;
22
+    getPreferenceBool(GeneralPreferenceKeys.showIntro, preferences) !== false;
23 23
 
24 24
   const isUpdate =
25
-    getPreferenceNumber(PreferenceKeys.updateNumber, preferences) !==
25
+    getPreferenceNumber(GeneralPreferenceKeys.updateNumber, preferences) !==
26 26
       Update.number && !showIntro;
27 27
 
28 28
   const isAprilFools =
29 29
     AprilFoolsManager.getInstance().isAprilFoolsEnabled() &&
30
-    getPreferenceBool(PreferenceKeys.showAprilFoolsStart, preferences) !==
31
-      false &&
30
+    getPreferenceBool(
31
+      GeneralPreferenceKeys.showAprilFoolsStart,
32
+      preferences
33
+    ) !== false &&
32 34
     !showIntro;
33 35
 
34 36
   return (

+ 42
- 22
src/screens/Other/Settings/SettingsScreen.tsx View File

@@ -32,13 +32,17 @@ import { Appearance } from 'react-native-appearance';
32 32
 import CustomSlider from '../../../components/Overrides/CustomSlider';
33 33
 import CollapsibleScrollView from '../../../components/Collapsible/CollapsibleScrollView';
34 34
 import GENERAL_STYLES from '../../../constants/Styles';
35
-import { usePreferences } from '../../../context/preferencesContext';
35
+import {
36
+  usePreferences,
37
+  useProxiwashPreferences,
38
+} from '../../../context/preferencesContext';
36 39
 import { useNavigation } from '@react-navigation/core';
37 40
 import {
38 41
   getPreferenceBool,
39 42
   getPreferenceNumber,
40 43
   getPreferenceString,
41
-  PreferenceKeys,
44
+  GeneralPreferenceKeys,
45
+  ProxiwashPreferenceKeys,
42 46
 } from '../../../utils/asyncStorage';
43 47
 
44 48
 const styles = StyleSheet.create({
@@ -61,42 +65,49 @@ const styles = StyleSheet.create({
61 65
 function SettingsScreen() {
62 66
   const navigation = useNavigation();
63 67
   const theme = useTheme();
64
-  const { preferences, updatePreferences } = usePreferences();
68
+  const generalPreferences = usePreferences();
69
+  const proxiwashPreferences = useProxiwashPreferences();
65 70
 
66 71
   const nightMode = getPreferenceBool(
67
-    PreferenceKeys.nightMode,
68
-    preferences
72
+    GeneralPreferenceKeys.nightMode,
73
+    generalPreferences.preferences
69 74
   ) as boolean;
70 75
   const nightModeFollowSystem =
71 76
     (getPreferenceBool(
72
-      PreferenceKeys.nightModeFollowSystem,
73
-      preferences
77
+      GeneralPreferenceKeys.nightModeFollowSystem,
78
+      generalPreferences.preferences
74 79
     ) as boolean) && Appearance.getColorScheme() !== 'no-preference';
75 80
   const startScreenPickerSelected = getPreferenceString(
76
-    PreferenceKeys.defaultStartScreen,
77
-    preferences
81
+    GeneralPreferenceKeys.defaultStartScreen,
82
+    generalPreferences.preferences
78 83
   ) as string;
79 84
   const selectedWash = getPreferenceString(
80
-    PreferenceKeys.selectedWash,
81
-    preferences
85
+    ProxiwashPreferenceKeys.selectedWash,
86
+    proxiwashPreferences.preferences
82 87
   ) as string;
83 88
   const isDebugUnlocked = getPreferenceBool(
84
-    PreferenceKeys.debugUnlocked,
85
-    preferences
89
+    GeneralPreferenceKeys.debugUnlocked,
90
+    generalPreferences.preferences
86 91
   ) as boolean;
87 92
   const notif = getPreferenceNumber(
88
-    PreferenceKeys.proxiwashNotifications,
89
-    preferences
93
+    ProxiwashPreferenceKeys.proxiwashNotifications,
94
+    proxiwashPreferences.preferences
90 95
   );
91 96
   const savedNotificationReminder = !notif || Number.isNaN(notif) ? 0 : notif;
92 97
 
93 98
   const onProxiwashNotifPickerValueChange = (value: number) => {
94
-    updatePreferences(PreferenceKeys.proxiwashNotifications, value);
99
+    proxiwashPreferences.updatePreferences(
100
+      ProxiwashPreferenceKeys.proxiwashNotifications,
101
+      value
102
+    );
95 103
   };
96 104
 
97 105
   const onStartScreenPickerValueChange = (value: string) => {
98 106
     if (value != null) {
99
-      updatePreferences(PreferenceKeys.defaultStartScreen, value);
107
+      generalPreferences.updatePreferences(
108
+        GeneralPreferenceKeys.defaultStartScreen,
109
+        value
110
+      );
100 111
     }
101 112
   };
102 113
 
@@ -150,12 +161,15 @@ function SettingsScreen() {
150 161
   };
151 162
 
152 163
   const onToggleNightMode = () => {
153
-    updatePreferences(PreferenceKeys.nightMode, !nightMode);
164
+    generalPreferences.updatePreferences(
165
+      GeneralPreferenceKeys.nightMode,
166
+      !nightMode
167
+    );
154 168
   };
155 169
 
156 170
   const onToggleNightModeFollowSystem = () => {
157
-    updatePreferences(
158
-      PreferenceKeys.nightModeFollowSystem,
171
+    generalPreferences.updatePreferences(
172
+      GeneralPreferenceKeys.nightModeFollowSystem,
159 173
       !nightModeFollowSystem
160 174
     );
161 175
   };
@@ -220,12 +234,18 @@ function SettingsScreen() {
220 234
 
221 235
   const onSelectWashValueChange = (value: string) => {
222 236
     if (value != null) {
223
-      updatePreferences(PreferenceKeys.selectedWash, value);
237
+      proxiwashPreferences.updatePreferences(
238
+        ProxiwashPreferenceKeys.selectedWash,
239
+        value
240
+      );
224 241
     }
225 242
   };
226 243
 
227 244
   const unlockDebugMode = () => {
228
-    updatePreferences(PreferenceKeys.debugUnlocked, true);
245
+    generalPreferences.updatePreferences(
246
+      GeneralPreferenceKeys.debugUnlocked,
247
+      true
248
+    );
229 249
   };
230 250
 
231 251
   return (

+ 9
- 6
src/screens/Planex/GroupSelectionScreen.tsx View File

@@ -28,8 +28,11 @@ import Urls from '../../constants/Urls';
28 28
 import { readData } from '../../utils/WebData';
29 29
 import { useNavigation } from '@react-navigation/core';
30 30
 import { useCachedPlanexGroups } from '../../context/cacheContext';
31
-import { usePreferences } from '../../context/preferencesContext';
32
-import { getPreferenceObject, PreferenceKeys } from '../../utils/asyncStorage';
31
+import { usePlanexPreferences } from '../../context/preferencesContext';
32
+import {
33
+  getPreferenceObject,
34
+  PlanexPreferenceKeys,
35
+} from '../../utils/asyncStorage';
33 36
 
34 37
 export type PlanexGroupType = {
35 38
   name: string;
@@ -59,13 +62,13 @@ function sortName(
59 62
 
60 63
 function GroupSelectionScreen() {
61 64
   const navigation = useNavigation();
62
-  const { preferences, updatePreferences } = usePreferences();
65
+  const { preferences, updatePreferences } = usePlanexPreferences();
63 66
   const { groups, setGroups } = useCachedPlanexGroups();
64 67
   const [currentSearchString, setCurrentSearchString] = useState('');
65 68
 
66 69
   const getFavoriteGroups = (): Array<PlanexGroupType> => {
67 70
     const data = getPreferenceObject(
68
-      PreferenceKeys.planexFavoriteGroups,
71
+      PlanexPreferenceKeys.planexFavoriteGroups,
69 72
       preferences
70 73
     );
71 74
     if (data) {
@@ -146,7 +149,7 @@ function GroupSelectionScreen() {
146 149
    * @param item The article pressed
147 150
    */
148 151
   const onListItemPress = (item: PlanexGroupType) => {
149
-    updatePreferences(PreferenceKeys.planexCurrentGroup, item);
152
+    updatePreferences(PlanexPreferenceKeys.planexCurrentGroup, item);
150 153
     navigation.goBack();
151 154
   };
152 155
 
@@ -158,7 +161,7 @@ function GroupSelectionScreen() {
158 161
   const onListFavoritePress = useCallback(
159 162
     (group: PlanexGroupType) => {
160 163
       const updateFavorites = (newValue: Array<PlanexGroupType>) => {
161
-        updatePreferences(PreferenceKeys.planexFavoriteGroups, newValue);
164
+        updatePreferences(PlanexPreferenceKeys.planexFavoriteGroups, newValue);
162 165
       };
163 166
 
164 167
       const removeGroupFromFavorites = (g: PlanexGroupType) => {

+ 9
- 5
src/screens/Planex/PlanexScreen.tsx View File

@@ -33,8 +33,12 @@ import { getPrettierPlanexGroupName } from '../../utils/Utils';
33 33
 import GENERAL_STYLES from '../../constants/Styles';
34 34
 import PlanexWebview from '../../components/Screens/PlanexWebview';
35 35
 import PlanexBottomBar from '../../components/Animations/PlanexBottomBar';
36
-import { usePreferences } from '../../context/preferencesContext';
37
-import { getPreferenceString, PreferenceKeys } from '../../utils/asyncStorage';
36
+import {
37
+  getPreferenceString,
38
+  GeneralPreferenceKeys,
39
+  PlanexPreferenceKeys,
40
+} from '../../utils/asyncStorage';
41
+import { usePlanexPreferences } from '../../context/preferencesContext';
38 42
 
39 43
 const styles = StyleSheet.create({
40 44
   container: {
@@ -50,7 +54,7 @@ const styles = StyleSheet.create({
50 54
 function PlanexScreen() {
51 55
   const navigation = useNavigation();
52 56
   const theme = useTheme();
53
-  const { preferences } = usePreferences();
57
+  const { preferences } = usePlanexPreferences();
54 58
 
55 59
   const [dialogContent, setDialogContent] = useState<
56 60
     | undefined
@@ -64,7 +68,7 @@ function PlanexScreen() {
64 68
 
65 69
   const getCurrentGroup: () => PlanexGroupType | undefined = useCallback(() => {
66 70
     let currentGroupString = getPreferenceString(
67
-      PreferenceKeys.planexCurrentGroup,
71
+      PlanexPreferenceKeys.planexCurrentGroup,
68 72
       preferences
69 73
     );
70 74
     let group: PlanexGroupType;
@@ -184,7 +188,7 @@ function PlanexScreen() {
184 188
 
185 189
   const showMascot =
186 190
     getPreferenceString(
187
-      PreferenceKeys.defaultStartScreen,
191
+      GeneralPreferenceKeys.defaultStartScreen,
188 192
       preferences
189 193
     )?.toLowerCase() !== 'planex';
190 194
 

+ 14
- 8
src/screens/Proxiwash/ProxiwashScreen.tsx View File

@@ -52,13 +52,13 @@ import { readData } from '../../utils/WebData';
52 52
 import { useNavigation } from '@react-navigation/core';
53 53
 import { setupMachineNotification } from '../../utils/Notifications';
54 54
 import ProximoListHeader from '../../components/Lists/Proximo/ProximoListHeader';
55
-import { usePreferences } from '../../context/preferencesContext';
56 55
 import {
57 56
   getPreferenceNumber,
58 57
   getPreferenceObject,
59 58
   getPreferenceString,
60
-  PreferenceKeys,
59
+  ProxiwashPreferenceKeys,
61 60
 } from '../../utils/asyncStorage';
61
+import { useProxiwashPreferences } from '../../context/preferencesContext';
62 62
 
63 63
 const REFRESH_TIME = 1000 * 10; // Refresh every 10 seconds
64 64
 const LIST_ITEM_HEIGHT = 64;
@@ -97,26 +97,29 @@ const styles = StyleSheet.create({
97 97
 function ProxiwashScreen() {
98 98
   const navigation = useNavigation();
99 99
   const theme = useTheme();
100
-  const { preferences, updatePreferences } = usePreferences();
100
+  const { preferences, updatePreferences } = useProxiwashPreferences();
101 101
   const [
102 102
     modalCurrentDisplayItem,
103 103
     setModalCurrentDisplayItem,
104 104
   ] = useState<React.ReactElement | null>(null);
105 105
   const reminder = getPreferenceNumber(
106
-    PreferenceKeys.proxiwashNotifications,
106
+    ProxiwashPreferenceKeys.proxiwashNotifications,
107 107
     preferences
108 108
   );
109 109
 
110 110
   const getMachinesWatched = () => {
111 111
     const data = getPreferenceObject(
112
-      PreferenceKeys.proxiwashWatchedMachines,
112
+      ProxiwashPreferenceKeys.proxiwashWatchedMachines,
113 113
       preferences
114 114
     ) as Array<ProxiwashMachineType>;
115 115
     return data ? (data as Array<ProxiwashMachineType>) : [];
116 116
   };
117 117
 
118 118
   const getSelectedWash = () => {
119
-    const data = getPreferenceString(PreferenceKeys.selectedWash, preferences);
119
+    const data = getPreferenceString(
120
+      ProxiwashPreferenceKeys.selectedWash,
121
+      preferences
122
+    );
120 123
     if (data !== 'washinsa' && data !== 'tripodeB') {
121 124
       return 'washinsa';
122 125
     } else {
@@ -350,7 +353,10 @@ function ProxiwashScreen() {
350 353
         ...data.washers,
351 354
       ]);
352 355
       if (cleanedList.length !== machinesWatched.length) {
353
-        updatePreferences(PreferenceKeys.proxiwashWatchedMachines, cleanedList);
356
+        updatePreferences(
357
+          ProxiwashPreferenceKeys.proxiwashWatchedMachines,
358
+          cleanedList
359
+        );
354 360
       }
355 361
       return [
356 362
         {
@@ -415,7 +421,7 @@ function ProxiwashScreen() {
415 421
   };
416 422
 
417 423
   const saveNewWatchedList = (list: Array<ProxiwashMachineType>) => {
418
-    updatePreferences(PreferenceKeys.proxiwashWatchedMachines, list);
424
+    updatePreferences(ProxiwashPreferenceKeys.proxiwashWatchedMachines, list);
419 425
   };
420 426
 
421 427
   const renderListHeaderComponent = (

+ 123
- 68
src/utils/asyncStorage.ts View File

@@ -1,15 +1,30 @@
1 1
 import AsyncStorage from '@react-native-async-storage/async-storage';
2 2
 import { SERVICES_KEY } from './Services';
3 3
 
4
-export enum PreferenceKeys {
4
+export enum GeneralPreferenceKeys {
5 5
   debugUnlocked = 'debugUnlocked',
6 6
   showIntro = 'showIntro',
7 7
   updateNumber = 'updateNumber',
8
-  proxiwashNotifications = 'proxiwashNotifications',
9 8
   nightModeFollowSystem = 'nightModeFollowSystem',
10 9
   nightMode = 'nightMode',
11 10
   defaultStartScreen = 'defaultStartScreen',
11
+  showAprilFoolsStart = 'showAprilFoolsStart',
12
+  dashboardItems = 'dashboardItems',
13
+  gameScores = 'gameScores',
14
+}
12 15
 
16
+export enum PlanexPreferenceKeys {
17
+  planexCurrentGroup = 'planexCurrentGroup',
18
+  planexFavoriteGroups = 'planexFavoriteGroups',
19
+}
20
+
21
+export enum ProxiwashPreferenceKeys {
22
+  proxiwashNotifications = 'proxiwashNotifications',
23
+  proxiwashWatchedMachines = 'proxiwashWatchedMachines',
24
+  selectedWash = 'selectedWash',
25
+}
26
+
27
+export enum MascotPreferenceKeys {
13 28
   servicesShowMascot = 'servicesShowMascot',
14 29
   proxiwashShowMascot = 'proxiwashShowMascot',
15 30
   homeShowMascot = 'homeShowMascot',
@@ -19,68 +34,109 @@ export enum PreferenceKeys {
19 34
   voteShowMascot = 'voteShowMascot',
20 35
   equipmentShowMascot = 'equipmentShowMascot',
21 36
   gameShowMascot = 'gameShowMascot',
22
-
23
-  proxiwashWatchedMachines = 'proxiwashWatchedMachines',
24
-  showAprilFoolsStart = 'showAprilFoolsStart',
25
-  planexCurrentGroup = 'planexCurrentGroup',
26
-  planexFavoriteGroups = 'planexFavoriteGroups',
27
-  dashboardItems = 'dashboardItems',
28
-  gameScores = 'gameScores',
29
-  selectedWash = 'selectedWash',
30 37
 }
31 38
 
39
+export const PreferenceKeys = {
40
+  ...GeneralPreferenceKeys,
41
+  ...PlanexPreferenceKeys,
42
+  ...ProxiwashPreferenceKeys,
43
+  ...MascotPreferenceKeys,
44
+};
45
+export type PreferenceKeys =
46
+  | GeneralPreferenceKeys
47
+  | PlanexPreferenceKeys
48
+  | ProxiwashPreferenceKeys
49
+  | MascotPreferenceKeys;
50
+
32 51
 export type PreferencesType = { [key in PreferenceKeys]: string };
52
+export type GeneralPreferencesType = { [key in GeneralPreferenceKeys]: string };
53
+export type PlanexPreferencesType = {
54
+  [key in PlanexPreferenceKeys]: string;
55
+};
56
+export type ProxiwashPreferencesType = {
57
+  [key in ProxiwashPreferenceKeys]: string;
58
+};
59
+export type MascotPreferencesType = { [key in MascotPreferenceKeys]: string };
60
+
61
+export const defaultPlanexPreferences: {
62
+  [key in PlanexPreferenceKeys]: string;
63
+} = {
64
+  [PlanexPreferenceKeys.planexCurrentGroup]: '',
65
+  [PlanexPreferenceKeys.planexFavoriteGroups]: '[]',
66
+};
67
+
68
+export const defaultProxiwashPreferences: {
69
+  [key in ProxiwashPreferenceKeys]: string;
70
+} = {
71
+  [ProxiwashPreferenceKeys.proxiwashNotifications]: '5',
72
+  [ProxiwashPreferenceKeys.proxiwashWatchedMachines]: '[]',
73
+  [ProxiwashPreferenceKeys.selectedWash]: 'washinsa',
74
+};
75
+
76
+export const defaultMascotPreferences: {
77
+  [key in MascotPreferenceKeys]: string;
78
+} = {
79
+  [MascotPreferenceKeys.servicesShowMascot]: '1',
80
+  [MascotPreferenceKeys.proxiwashShowMascot]: '1',
81
+  [MascotPreferenceKeys.homeShowMascot]: '1',
82
+  [MascotPreferenceKeys.eventsShowMascot]: '1',
83
+  [MascotPreferenceKeys.planexShowMascot]: '1',
84
+  [MascotPreferenceKeys.loginShowMascot]: '1',
85
+  [MascotPreferenceKeys.voteShowMascot]: '1',
86
+  [MascotPreferenceKeys.equipmentShowMascot]: '1',
87
+  [MascotPreferenceKeys.gameShowMascot]: '1',
88
+};
33 89
 
34
-export const defaultPreferences: { [key in PreferenceKeys]: string } = {
35
-  [PreferenceKeys.debugUnlocked]: '0',
36
-  [PreferenceKeys.showIntro]: '1',
37
-  [PreferenceKeys.updateNumber]: '0',
38
-  [PreferenceKeys.proxiwashNotifications]: '5',
39
-  [PreferenceKeys.nightModeFollowSystem]: '1',
40
-  [PreferenceKeys.nightMode]: '1',
41
-  [PreferenceKeys.defaultStartScreen]: 'home',
42
-  [PreferenceKeys.servicesShowMascot]: '1',
43
-  [PreferenceKeys.proxiwashShowMascot]: '1',
44
-  [PreferenceKeys.homeShowMascot]: '1',
45
-  [PreferenceKeys.eventsShowMascot]: '1',
46
-  [PreferenceKeys.planexShowMascot]: '1',
47
-  [PreferenceKeys.loginShowMascot]: '1',
48
-  [PreferenceKeys.voteShowMascot]: '1',
49
-  [PreferenceKeys.equipmentShowMascot]: '1',
50
-  [PreferenceKeys.gameShowMascot]: '1',
51
-  [PreferenceKeys.proxiwashWatchedMachines]: '[]',
52
-  [PreferenceKeys.showAprilFoolsStart]: '1',
53
-  [PreferenceKeys.planexCurrentGroup]: '',
54
-  [PreferenceKeys.planexFavoriteGroups]: '[]',
55
-  [PreferenceKeys.dashboardItems]: JSON.stringify([
90
+export const defaultPreferences: { [key in GeneralPreferenceKeys]: string } = {
91
+  [GeneralPreferenceKeys.debugUnlocked]: '0',
92
+  [GeneralPreferenceKeys.showIntro]: '1',
93
+  [GeneralPreferenceKeys.updateNumber]: '0',
94
+  [GeneralPreferenceKeys.nightModeFollowSystem]: '1',
95
+  [GeneralPreferenceKeys.nightMode]: '1',
96
+  [GeneralPreferenceKeys.defaultStartScreen]: 'home',
97
+  [GeneralPreferenceKeys.showAprilFoolsStart]: '1',
98
+
99
+  [GeneralPreferenceKeys.dashboardItems]: JSON.stringify([
56 100
     SERVICES_KEY.EMAIL,
57 101
     SERVICES_KEY.WASHERS,
58 102
     SERVICES_KEY.PROXIMO,
59 103
     SERVICES_KEY.TUTOR_INSA,
60 104
     SERVICES_KEY.RU,
61 105
   ]),
62
-  [PreferenceKeys.gameScores]: '[]',
63
-  [PreferenceKeys.selectedWash]: 'washinsa',
106
+
107
+  [GeneralPreferenceKeys.gameScores]: '[]',
64 108
 };
65 109
 
110
+export function isValidGeneralPreferenceKey(
111
+  key: string
112
+): key is GeneralPreferenceKeys {
113
+  return key in Object.values(GeneralPreferenceKeys);
114
+}
115
+
116
+export function isValidMascotPreferenceKey(
117
+  key: string
118
+): key is MascotPreferenceKeys {
119
+  return key in Object.values(MascotPreferenceKeys);
120
+}
121
+
66 122
 /**
67 123
  * Set preferences object current values from AsyncStorage.
68 124
  * This function should be called once on start.
69 125
  *
70 126
  * @return {Promise<PreferencesType>}
71 127
  */
72
-export function retrievePreferences(
73
-  keys: Array<PreferenceKeys>,
74
-  defaults: PreferencesType
75
-): Promise<PreferencesType> {
76
-  return new Promise((resolve: (preferences: PreferencesType) => void) => {
128
+export function retrievePreferences<
129
+  Keys extends PreferenceKeys,
130
+  T extends Partial<PreferencesType>
131
+>(keys: Array<Keys>, defaults: T): Promise<T> {
132
+  return new Promise((resolve: (preferences: T) => void) => {
77 133
     AsyncStorage.multiGet(keys)
78 134
       .then((result) => {
79 135
         const preferences = { ...defaults };
80 136
         result.forEach((item) => {
81 137
           let [key, value] = item;
82 138
           if (value !== null) {
83
-            preferences[key as PreferenceKeys] = value;
139
+            preferences[key as Keys] = value;
84 140
           }
85 141
         });
86 142
         resolve(preferences);
@@ -96,11 +152,14 @@ export function retrievePreferences(
96 152
  * @param key
97 153
  * @param value
98 154
  */
99
-export function setPreference(
100
-  key: PreferenceKeys,
101
-  value: number | string | boolean | object | Array<any>,
102
-  prevPreferences: PreferencesType
103
-): PreferencesType {
155
+export function setPreference<
156
+  Keys extends PreferenceKeys,
157
+  T extends Partial<PreferencesType>
158
+>(
159
+  key: Keys,
160
+  value: number | string | boolean | object | Array<any> | undefined,
161
+  prevPreferences: T
162
+): T {
104 163
   let convertedValue: string;
105 164
   if (typeof value === 'string') {
106 165
     convertedValue = value;
@@ -116,20 +175,16 @@ export function setPreference(
116 175
   return prevPreferences;
117 176
 }
118 177
 
119
-export function isValidPreferenceKey(key: string): key is PreferenceKeys {
120
-  return key in Object.values(PreferenceKeys);
121
-}
122
-
123 178
 /**
124 179
  * Gets the boolean value of the given preference
125 180
  *
126 181
  * @param key
127 182
  * @returns {boolean}
128 183
  */
129
-export function getPreferenceString(
130
-  key: PreferenceKeys,
131
-  preferences: PreferencesType
132
-): string | undefined {
184
+export function getPreferenceString<
185
+  Keys extends PreferenceKeys,
186
+  T extends Partial<PreferencesType>
187
+>(key: Keys, preferences: T): string | undefined {
133 188
   return preferences[key];
134 189
 }
135 190
 
@@ -139,10 +194,10 @@ export function getPreferenceString(
139 194
  * @param key
140 195
  * @returns {boolean}
141 196
  */
142
-export function getPreferenceBool(
143
-  key: PreferenceKeys,
144
-  preferences: PreferencesType
145
-): boolean | undefined {
197
+export function getPreferenceBool<
198
+  Keys extends PreferenceKeys,
199
+  T extends Partial<PreferencesType>
200
+>(key: Keys, preferences: T): boolean | undefined {
146 201
   const value = preferences[key];
147 202
   return value ? value === '1' || value === 'true' : undefined;
148 203
 }
@@ -153,12 +208,12 @@ export function getPreferenceBool(
153 208
  * @param key
154 209
  * @returns {number}
155 210
  */
156
-export function getPreferenceNumber(
157
-  key: PreferenceKeys,
158
-  preferences: PreferencesType
159
-): number | undefined {
160
-  const value = preferences[key];
161
-  return value !== undefined ? parseFloat(value) : undefined;
211
+export function getPreferenceNumber<
212
+  Keys extends PreferenceKeys,
213
+  T extends Partial<PreferencesType>
214
+>(key: Keys, preferences: T): number | undefined {
215
+  const value = preferences[key] as string | undefined;
216
+  return value ? parseFloat(value) : undefined;
162 217
 }
163 218
 
164 219
 /**
@@ -167,10 +222,10 @@ export function getPreferenceNumber(
167 222
  * @param key
168 223
  * @returns {{...}}
169 224
  */
170
-export function getPreferenceObject(
171
-  key: PreferenceKeys,
172
-  preferences: PreferencesType
173
-): object | Array<any> | undefined {
174
-  const value = preferences[key];
225
+export function getPreferenceObject<
226
+  Keys extends PreferenceKeys,
227
+  T extends Partial<PreferencesType>
228
+>(key: Keys, preferences: T): object | Array<any> | undefined {
229
+  const value = preferences[key] as string | undefined;
175 230
   return value ? JSON.parse(value) : undefined;
176 231
 }

Loading…
Cancel
Save