Browse Source

Allow mascot popup to be controlled directly with a pref key

Arnaud Vergnet 3 years ago
parent
commit
5349e210cb

+ 59
- 29
src/components/Mascot/MascotPopup.js View File

@@ -7,9 +7,9 @@ import * as Animatable from "react-native-animatable";
7 7
 import {BackHandler, Dimensions, ScrollView, TouchableWithoutFeedback, View} from "react-native";
8 8
 import type {CustomTheme} from "../../managers/ThemeManager";
9 9
 import SpeechArrow from "./SpeechArrow";
10
+import AsyncStorageManager from "../../managers/AsyncStorageManager";
10 11
 
11 12
 type Props = {
12
-    visible: boolean,
13 13
     theme: CustomTheme,
14 14
     icon: string,
15 15
     title: string,
@@ -19,34 +19,34 @@ type Props = {
19 19
             message: string,
20 20
             icon: string | null,
21 21
             color: string | null,
22
-            onPress: () => void,
22
+            onPress?: () => void,
23 23
         },
24 24
         cancel: {
25 25
             message: string,
26 26
             icon: string | null,
27 27
             color: string | null,
28
-            onPress: () => void,
28
+            onPress?: () => void,
29 29
         }
30 30
     },
31 31
     emotion: number,
32
+    visible?: boolean,
33
+    prefKey?: string,
32 34
 }
33 35
 
34 36
 type State = {
35
-    shouldShowDialog: boolean;
37
+    shouldRenderDialog: boolean, // Used to stop rendering after hide animation
38
+    dialogVisible: boolean,
36 39
 }
37 40
 
38
-
41
+/**
42
+ * Component used to display a popup with the mascot.
43
+ */
39 44
 class MascotPopup extends React.Component<Props, State> {
40 45
 
41 46
     mascotSize: number;
42 47
     windowWidth: number;
43 48
     windowHeight: number;
44 49
 
45
-    state = {
46
-        shouldShowDialog: this.props.visible,
47
-    };
48
-
49
-
50 50
     constructor(props: Props) {
51 51
         super(props);
52 52
 
@@ -54,18 +54,40 @@ class MascotPopup extends React.Component<Props, State> {
54 54
         this.windowHeight = Dimensions.get('window').height;
55 55
 
56 56
         this.mascotSize = Dimensions.get('window').height / 6;
57
+
58
+        if (this.props.visible != null) {
59
+            this.state = {
60
+                shouldRenderDialog: this.props.visible,
61
+                dialogVisible: this.props.visible,
62
+            };
63
+        } else if (this.props.prefKey != null) {
64
+            const visible = AsyncStorageManager.getBool(this.props.prefKey);
65
+            this.state = {
66
+                shouldRenderDialog: visible,
67
+                dialogVisible: visible,
68
+            };
69
+        } else {
70
+            this.state = {
71
+                shouldRenderDialog: false,
72
+                dialogVisible: false,
73
+            };
74
+        }
75
+
57 76
     }
58 77
 
59 78
     onAnimationEnd = () => {
60 79
         this.setState({
61
-            shouldShowDialog: this.props.visible,
80
+            shouldRenderDialog: false,
62 81
         })
63 82
     }
64 83
 
65
-    shouldComponentUpdate(nextProps: Props): boolean {
84
+    shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
66 85
         if (nextProps.visible) {
67
-            this.state.shouldShowDialog = true;
68
-        } else if (nextProps.visible !== this.props.visible) {
86
+            this.state.shouldRenderDialog = true;
87
+            this.state.dialogVisible = true;
88
+        } else if (nextProps.visible !== this.props.visible
89
+            || (!nextState.dialogVisible && nextState.dialogVisible !== this.state.dialogVisible)) {
90
+            this.state.dialogVisible = false;
69 91
             setTimeout(this.onAnimationEnd, 300);
70 92
         }
71 93
         return true;
@@ -79,13 +101,13 @@ class MascotPopup extends React.Component<Props, State> {
79 101
     }
80 102
 
81 103
     onBackButtonPressAndroid = () => {
82
-        if (this.state.shouldShowDialog) {
104
+        if (this.state.dialogVisible) {
83 105
             const cancel = this.props.buttons.cancel;
84 106
             const action = this.props.buttons.action;
85 107
             if (cancel != null)
86
-                cancel.onPress();
108
+                this.onDismiss(cancel.onPress);
87 109
             else
88
-                action.onPress();
110
+                this.onDismiss(action.onPress);
89 111
             return true;
90 112
         } else {
91 113
             return false;
@@ -100,8 +122,8 @@ class MascotPopup extends React.Component<Props, State> {
100 122
                     marginRight: "10%",
101 123
                 }}
102 124
                 useNativeDriver={true}
103
-                animation={this.props.visible ? "bounceInLeft" : "bounceOutLeft"}
104
-                duration={this.props.visible ? 1000 : 300}
125
+                animation={this.state.dialogVisible ? "bounceInLeft" : "bounceOutLeft"}
126
+                duration={this.state.dialogVisible ? 1000 : 300}
105 127
             >
106 128
                 <SpeechArrow
107 129
                     style={{marginLeft: this.mascotSize / 3}}
@@ -149,8 +171,8 @@ class MascotPopup extends React.Component<Props, State> {
149 171
         return (
150 172
             <Animatable.View
151 173
                 useNativeDriver={true}
152
-                animation={this.props.visible ? "bounceInLeft" : "bounceOutLeft"}
153
-                duration={this.props.visible ? 1500 : 200}
174
+                animation={this.state.dialogVisible ? "bounceInLeft" : "bounceOutLeft"}
175
+                duration={this.state.dialogVisible ? 1500 : 200}
154 176
             >
155 177
                 <Mascot
156 178
                     style={{width: this.mascotSize}}
@@ -181,7 +203,7 @@ class MascotPopup extends React.Component<Props, State> {
181 203
                         mode={"contained"}
182 204
                         icon={action.icon}
183 205
                         color={action.color}
184
-                        onPress={action.onPress}
206
+                        onPress={() => this.onDismiss(action.onPress)}
185 207
                     >
186 208
                         {action.message}
187 209
                     </Button>
@@ -195,7 +217,7 @@ class MascotPopup extends React.Component<Props, State> {
195 217
                         mode={"contained"}
196 218
                         icon={cancel.icon}
197 219
                         color={cancel.color}
198
-                        onPress={cancel.onPress}
220
+                        onPress={() => this.onDismiss(cancel.onPress)}
199 221
                     >
200 222
                         {cancel.message}
201 223
                     </Button>
@@ -206,7 +228,7 @@ class MascotPopup extends React.Component<Props, State> {
206 228
 
207 229
     getBackground() {
208 230
         return (
209
-            <TouchableWithoutFeedback onPress={this.props.buttons.cancel.onPress}>
231
+            <TouchableWithoutFeedback onPress={() => this.onDismiss(this.props.buttons.cancel.onPress)}>
210 232
                 <Animatable.View
211 233
                     style={{
212 234
                         position: "absolute",
@@ -215,16 +237,25 @@ class MascotPopup extends React.Component<Props, State> {
215 237
                         height: "100%",
216 238
                     }}
217 239
                     useNativeDriver={true}
218
-                    animation={this.props.visible ? "fadeIn" : "fadeOut"}
219
-                    duration={this.props.visible ? 300 : 300}
240
+                    animation={this.state.dialogVisible ? "fadeIn" : "fadeOut"}
241
+                    duration={this.state.dialogVisible ? 300 : 300}
220 242
                 />
221 243
             </TouchableWithoutFeedback>
222 244
 
223 245
         );
224 246
     }
225 247
 
248
+    onDismiss = (callback?: ()=> void) => {
249
+        if (this.props.prefKey != null) {
250
+            AsyncStorageManager.set(this.props.prefKey, false);
251
+            this.setState({dialogVisible: false});
252
+        }
253
+        if (callback != null)
254
+            callback();
255
+    }
256
+
226 257
     render() {
227
-        if (this.state.shouldShowDialog) {
258
+        if (this.state.shouldRenderDialog) {
228 259
             return (
229 260
                 <Portal>
230 261
                     {this.getBackground()}
@@ -242,8 +273,7 @@ class MascotPopup extends React.Component<Props, State> {
242 273
 
243 274
                     </View>
244 275
                 </Portal>
245
-            )
246
-                ;
276
+            );
247 277
         } else
248 278
             return null;
249 279
 

+ 2
- 16
src/screens/Game/screens/GameStartScreen.js View File

@@ -33,11 +33,7 @@ type Props = {
33 33
     theme: CustomTheme,
34 34
 }
35 35
 
36
-type State = {
37
-    mascotDialogVisible: boolean,
38
-}
39
-
40
-class GameStartScreen extends React.Component<Props, State> {
36
+class GameStartScreen extends React.Component<Props> {
41 37
 
42 38
     gridManager: GridManager;
43 39
     scores: Array<number>;
@@ -45,10 +41,6 @@ class GameStartScreen extends React.Component<Props, State> {
45 41
     gameStats: GameStats | null;
46 42
     isHighScore: boolean;
47 43
 
48
-    state = {
49
-        mascotDialogVisible: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.gameStartShowBanner.key),
50
-    }
51
-
52 44
     constructor(props: Props) {
53 45
         super(props);
54 46
         this.gridManager = new GridManager(4, 4, props.theme);
@@ -75,11 +67,6 @@ class GameStartScreen extends React.Component<Props, State> {
75 67
         AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.gameScores.key, this.scores);
76 68
     }
77 69
 
78
-    hideMascotDialog = () => {
79
-        AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.gameStartShowBanner.key, false);
80
-        this.setState({mascotDialogVisible: false})
81
-    };
82
-
83 70
     getPiecesBackground() {
84 71
         let gridList = [];
85 72
         for (let i = 0; i < 18; i++) {
@@ -415,7 +402,7 @@ class GameStartScreen extends React.Component<Props, State> {
415 402
                     <CollapsibleScrollView>
416 403
                         {this.getMainContent()}
417 404
                         <MascotPopup
418
-                            visible={this.state.mascotDialogVisible}
405
+                            prefKey={AsyncStorageManager.PREFERENCES.gameStartShowBanner.key}
419 406
                             title={i18n.t("screens.game.mascotDialog.title")}
420 407
                             message={i18n.t("screens.game.mascotDialog.message")}
421 408
                             icon={"gamepad-variant"}
@@ -424,7 +411,6 @@ class GameStartScreen extends React.Component<Props, State> {
424 411
                                 cancel: {
425 412
                                     message: i18n.t("screens.game.mascotDialog.button"),
426 413
                                     icon: "check",
427
-                                    onPress: this.hideMascotDialog,
428 414
                                 }
429 415
                             }}
430 416
                             emotion={MASCOT_STYLE.COOL}

+ 21
- 33
src/screens/Home/HomeScreen.js View File

@@ -84,7 +84,6 @@ type Props = {
84 84
 
85 85
 type State = {
86 86
     dialogVisible: boolean,
87
-    mascotDialogVisible: boolean,
88 87
 }
89 88
 
90 89
 /**
@@ -112,9 +111,6 @@ class HomeScreen extends React.Component<Props, State> {
112 111
         });
113 112
         this.state = {
114 113
             dialogVisible: false,
115
-            mascotDialogVisible: AsyncStorageManager.getBool(
116
-                AsyncStorageManager.PREFERENCES.homeShowBanner.key)
117
-                && !this.isLoggedIn,
118 114
         }
119 115
     }
120 116
 
@@ -184,11 +180,6 @@ class HomeScreen extends React.Component<Props, State> {
184 180
         </MaterialHeaderButtons>;
185 181
     };
186 182
 
187
-    hideMascotDialog = () => {
188
-        AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.homeShowBanner.key, false);
189
-        this.setState({mascotDialogVisible: false})
190
-    };
191
-
192 183
     showDisconnectDialog = () => this.setState({dialogVisible: true});
193 184
 
194 185
     hideDisconnectDialog = () => this.setState({dialogVisible: false});
@@ -525,10 +516,7 @@ class HomeScreen extends React.Component<Props, State> {
525 516
      * Callback when pressing the login button on the banner.
526 517
      * This hides the banner and takes the user to the login page.
527 518
      */
528
-    onLogin = () => {
529
-        this.hideMascotDialog();
530
-        this.props.navigation.navigate("login", {nextScreen: "profile"});
531
-    }
519
+    onLogin = () => this.props.navigation.navigate("login", {nextScreen: "profile"});
532 520
 
533 521
     render() {
534 522
         return (
@@ -554,26 +542,26 @@ class HomeScreen extends React.Component<Props, State> {
554 542
                         renderListHeaderComponent={this.getListHeader}
555 543
                     />
556 544
                 </View>
557
-                <MascotPopup
558
-                    visible={this.state.mascotDialogVisible}
559
-                    title={i18n.t("screens.home.mascotDialog.title")}
560
-                    message={i18n.t("screens.home.mascotDialog.message")}
561
-                    icon={"human-greeting"}
562
-                    buttons={{
563
-                        action: {
564
-                            message: i18n.t("screens.home.mascotDialog.login"),
565
-                            icon: "login",
566
-                            onPress: this.onLogin,
567
-                        },
568
-                        cancel: {
569
-                            message: i18n.t("screens.home.mascotDialog.later"),
570
-                            icon: "close",
571
-                            color: this.props.theme.colors.warning,
572
-                            onPress: this.hideMascotDialog,
573
-                        }
574
-                    }}
575
-                    emotion={MASCOT_STYLE.CUTE}
576
-                />
545
+                {!this.isLoggedIn
546
+                    ? <MascotPopup
547
+                        prefKey={AsyncStorageManager.PREFERENCES.homeShowBanner.key}
548
+                        title={i18n.t("screens.home.mascotDialog.title")}
549
+                        message={i18n.t("screens.home.mascotDialog.message")}
550
+                        icon={"human-greeting"}
551
+                        buttons={{
552
+                            action: {
553
+                                message: i18n.t("screens.home.mascotDialog.login"),
554
+                                icon: "login",
555
+                                onPress: this.onLogin,
556
+                            },
557
+                            cancel: {
558
+                                message: i18n.t("screens.home.mascotDialog.later"),
559
+                                icon: "close",
560
+                                color: this.props.theme.colors.warning,
561
+                            }
562
+                        }}
563
+                        emotion={MASCOT_STYLE.CUTE}
564
+                    /> : null}
577 565
                 <AnimatedFAB
578 566
                     {...this.props}
579 567
                     ref={this.fabRef}

+ 6
- 23
src/screens/Planex/PlanexScreen.js View File

@@ -26,7 +26,6 @@ type Props = {
26 26
 }
27 27
 
28 28
 type State = {
29
-    mascotDialogVisible: boolean,
30 29
     dialogVisible: boolean,
31 30
     dialogTitle: string,
32 31
     dialogMessage: string,
@@ -143,10 +142,6 @@ class PlanexScreen extends React.Component<Props, State> {
143 142
             props.navigation.setOptions({title: currentGroup.name})
144 143
         }
145 144
         this.state = {
146
-            mascotDialogVisible:
147
-                AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.planexShowBanner.key)
148
-                && AsyncStorageManager.getString(AsyncStorageManager.PREFERENCES.defaultStartScreen.key)
149
-                    .toLowerCase() !== 'planex',
150 145
             dialogVisible: false,
151 146
             dialogTitle: "",
152 147
             dialogMessage: "",
@@ -163,23 +158,10 @@ class PlanexScreen extends React.Component<Props, State> {
163 158
     }
164 159
 
165 160
     /**
166
-     * Callback used when closing the banner.
167
-     * This hides the banner and saves to preferences to prevent it from reopening
168
-     */
169
-    onMascotDialogCancel = () => {
170
-        this.setState({mascotDialogVisible: false});
171
-        AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.planexShowBanner.key, false);
172
-    };
173
-
174
-
175
-    /**
176 161
      * Callback used when the user clicks on the navigate to settings button.
177 162
      * This will hide the banner and open the SettingsScreen
178 163
      */
179
-    onGoToSettings = () => {
180
-        this.onMascotDialogCancel();
181
-        this.props.navigation.navigate('settings');
182
-    };
164
+    onGoToSettings = () => this.props.navigation.navigate('settings');
183 165
 
184 166
     onScreenFocus = () => {
185 167
         this.handleNavigationParams();
@@ -357,8 +339,10 @@ class PlanexScreen extends React.Component<Props, State> {
357 339
                         ? this.getWebView()
358 340
                         : <View style={{height: '100%'}}>{this.getWebView()}</View>}
359 341
                 </View>
360
-                <MascotPopup
361
-                    visible={this.state.mascotDialogVisible}
342
+                {AsyncStorageManager.getString(AsyncStorageManager.PREFERENCES.defaultStartScreen.key)
343
+                    .toLowerCase() !== 'planex'
344
+                    ? <MascotPopup
345
+                    prefKey={AsyncStorageManager.PREFERENCES.planexShowBanner.key}
362 346
                     title={i18n.t("screens.planex.mascotDialog.title")}
363 347
                     message={i18n.t("screens.planex.mascotDialog.message")}
364 348
                     icon={"emoticon-kiss"}
@@ -372,11 +356,10 @@ class PlanexScreen extends React.Component<Props, State> {
372 356
                             message: i18n.t("screens.planex.mascotDialog.cancel"),
373 357
                             icon: "close",
374 358
                             color: this.props.theme.colors.warning,
375
-                            onPress: this.onMascotDialogCancel,
376 359
                         }
377 360
                     }}
378 361
                     emotion={MASCOT_STYLE.INTELLO}
379
-                />
362
+                /> : null }
380 363
                 <AlertDialog
381 364
                     visible={this.state.dialogVisible}
382 365
                     onDismiss={this.hideDialog}

+ 1
- 13
src/screens/Planning/PlanningScreen.js View File

@@ -36,7 +36,6 @@ type State = {
36 36
     refreshing: boolean,
37 37
     agendaItems: Object,
38 38
     calendarShowing: boolean,
39
-    mascotDialogVisible: boolean,
40 39
 };
41 40
 
42 41
 const FETCH_URL = "https://www.amicale-insat.fr/api/event/list";
@@ -56,7 +55,6 @@ class PlanningScreen extends React.Component<Props, State> {
56 55
         refreshing: false,
57 56
         agendaItems: {},
58 57
         calendarShowing: false,
59
-        mascotDialogVisible: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.eventsShowBanner.key)
60 58
     };
61 59
 
62 60
     currentDate = getDateOnlyString(getCurrentDateString());
@@ -106,15 +104,6 @@ class PlanningScreen extends React.Component<Props, State> {
106 104
     };
107 105
 
108 106
     /**
109
-     * Callback used when closing the banner.
110
-     * This hides the banner and saves to preferences to prevent it from reopening
111
-     */
112
-    onHideMascotDialog = () => {
113
-        this.setState({mascotDialogVisible: false});
114
-        AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.eventsShowBanner.key, false);
115
-    };
116
-
117
-    /**
118 107
      * Function used to check if a row has changed
119 108
      *
120 109
      * @param r1
@@ -250,7 +239,7 @@ class PlanningScreen extends React.Component<Props, State> {
250 239
                     onRef={this.onAgendaRef}
251 240
                 />
252 241
                 <MascotPopup
253
-                    visible={this.state.mascotDialogVisible}
242
+                    prefKey={AsyncStorageManager.PREFERENCES.eventsShowBanner.key}
254 243
                     title={i18n.t("screens.planning.mascotDialog.title")}
255 244
                     message={i18n.t("screens.planning.mascotDialog.message")}
256 245
                     icon={"party-popper"}
@@ -259,7 +248,6 @@ class PlanningScreen extends React.Component<Props, State> {
259 248
                         cancel: {
260 249
                             message: i18n.t("screens.planning.mascotDialog.button"),
261 250
                             icon: "check",
262
-                            onPress: this.onHideMascotDialog,
263 251
                         }
264 252
                     }}
265 253
                     emotion={MASCOT_STYLE.HAPPY}

+ 1
- 13
src/screens/Proxiwash/ProxiwashScreen.js View File

@@ -46,7 +46,6 @@ type State = {
46 46
     refreshing: boolean,
47 47
     modalCurrentDisplayItem: React.Node,
48 48
     machinesWatched: Array<Machine>,
49
-    mascotDialogVisible: boolean,
50 49
 };
51 50
 
52 51
 
@@ -67,7 +66,6 @@ class ProxiwashScreen extends React.Component<Props, State> {
67 66
         refreshing: false,
68 67
         modalCurrentDisplayItem: null,
69 68
         machinesWatched: AsyncStorageManager.getObject(AsyncStorageManager.PREFERENCES.proxiwashWatchedMachines.key),
70
-        mascotDialogVisible: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.proxiwashShowBanner.key),
71 69
     };
72 70
 
73 71
     /**
@@ -85,15 +83,6 @@ class ProxiwashScreen extends React.Component<Props, State> {
85 83
     }
86 84
 
87 85
     /**
88
-     * Callback used when closing the banner.
89
-     * This hides the banner and saves to preferences to prevent it from reopening
90
-     */
91
-    onHideMascotDialog = () => {
92
-        this.setState({mascotDialogVisible: false});
93
-        AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.proxiwashShowBanner.key, false);
94
-    };
95
-
96
-    /**
97 86
      * Setup notification channel for android and add listeners to detect notifications fired
98 87
      */
99 88
     componentDidMount() {
@@ -409,7 +398,7 @@ class ProxiwashScreen extends React.Component<Props, State> {
409 398
                         updateData={this.state.machinesWatched.length}/>
410 399
                 </View>
411 400
                 <MascotPopup
412
-                    visible={this.state.mascotDialogVisible}
401
+                    prefKey={AsyncStorageManager.PREFERENCES.proxiwashShowBanner.key}
413 402
                     title={i18n.t("screens.proxiwash.mascotDialog.title")}
414 403
                     message={i18n.t("screens.proxiwash.mascotDialog.message")}
415 404
                     icon={"information"}
@@ -418,7 +407,6 @@ class ProxiwashScreen extends React.Component<Props, State> {
418 407
                         cancel: {
419 408
                             message: i18n.t("screens.proxiwash.mascotDialog.ok"),
420 409
                             icon: "check",
421
-                            onPress: this.onHideMascotDialog,
422 410
                         }
423 411
                     }}
424 412
                     emotion={MASCOT_STYLE.NORMAL}

+ 2
- 21
src/screens/Services/ServicesScreen.js View File

@@ -20,11 +20,6 @@ type Props = {
20 20
     theme: CustomTheme,
21 21
 }
22 22
 
23
-type State = {
24
-    mascotDialogVisible: boolean,
25
-}
26
-
27
-
28 23
 export type listItem = {
29 24
     title: string,
30 25
     description: string,
@@ -33,14 +28,10 @@ export type listItem = {
33 28
 }
34 29
 
35 30
 
36
-class ServicesScreen extends React.Component<Props, State> {
31
+class ServicesScreen extends React.Component<Props> {
37 32
 
38 33
     finalDataset: Array<listItem>
39 34
 
40
-    state = {
41
-        mascotDialogVisible: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.servicesShowBanner.key),
42
-    }
43
-
44 35
     constructor(props) {
45 36
         super(props);
46 37
         const services = new ServicesManager(props.navigation);
@@ -53,16 +44,6 @@ class ServicesScreen extends React.Component<Props, State> {
53 44
         });
54 45
     }
55 46
 
56
-
57
-    /**
58
-     * Callback used when closing the banner.
59
-     * This hides the banner and saves to preferences to prevent it from reopening
60
-     */
61
-    onHideMascotDialog = () => {
62
-        this.setState({mascotDialogVisible: false});
63
-        AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.servicesShowBanner.key, false);
64
-    };
65
-
66 47
     getAboutButton = () =>
67 48
         <MaterialHeaderButtons>
68 49
             <Item title="information" iconName="information" onPress={this.onAboutPress}/>
@@ -146,7 +127,7 @@ class ServicesScreen extends React.Component<Props, State> {
146 127
                     hasTab={true}
147 128
                 />
148 129
                 <MascotPopup
149
-                    visible={this.state.mascotDialogVisible}
130
+                    prefKey={AsyncStorageManager.PREFERENCES.servicesShowBanner.key}
150 131
                     title={i18n.t("screens.services.mascotDialog.title")}
151 132
                     message={i18n.t("screens.services.mascotDialog.message")}
152 133
                     icon={"cloud-question"}

Loading…
Cancel
Save