From 5349e210cb74da179e0ee344f123a5bee87b3cf2 Mon Sep 17 00:00:00 2001 From: Arnaud Vergnet Date: Thu, 23 Jul 2020 14:52:56 +0200 Subject: [PATCH] Allow mascot popup to be controlled directly with a pref key --- src/components/Mascot/MascotPopup.js | 88 ++++++++++++++------- src/screens/Game/screens/GameStartScreen.js | 18 +---- src/screens/Home/HomeScreen.js | 54 +++++-------- src/screens/Planex/PlanexScreen.js | 29 ++----- src/screens/Planning/PlanningScreen.js | 14 +--- src/screens/Proxiwash/ProxiwashScreen.js | 14 +--- src/screens/Services/ServicesScreen.js | 23 +----- 7 files changed, 92 insertions(+), 148 deletions(-) diff --git a/src/components/Mascot/MascotPopup.js b/src/components/Mascot/MascotPopup.js index 47ad5a4..cc80091 100644 --- a/src/components/Mascot/MascotPopup.js +++ b/src/components/Mascot/MascotPopup.js @@ -7,9 +7,9 @@ import * as Animatable from "react-native-animatable"; import {BackHandler, Dimensions, ScrollView, TouchableWithoutFeedback, View} from "react-native"; import type {CustomTheme} from "../../managers/ThemeManager"; import SpeechArrow from "./SpeechArrow"; +import AsyncStorageManager from "../../managers/AsyncStorageManager"; type Props = { - visible: boolean, theme: CustomTheme, icon: string, title: string, @@ -19,34 +19,34 @@ type Props = { message: string, icon: string | null, color: string | null, - onPress: () => void, + onPress?: () => void, }, cancel: { message: string, icon: string | null, color: string | null, - onPress: () => void, + onPress?: () => void, } }, emotion: number, + visible?: boolean, + prefKey?: string, } type State = { - shouldShowDialog: boolean; + shouldRenderDialog: boolean, // Used to stop rendering after hide animation + dialogVisible: boolean, } - +/** + * Component used to display a popup with the mascot. + */ class MascotPopup extends React.Component { mascotSize: number; windowWidth: number; windowHeight: number; - state = { - shouldShowDialog: this.props.visible, - }; - - constructor(props: Props) { super(props); @@ -54,18 +54,40 @@ class MascotPopup extends React.Component { this.windowHeight = Dimensions.get('window').height; this.mascotSize = Dimensions.get('window').height / 6; + + if (this.props.visible != null) { + this.state = { + shouldRenderDialog: this.props.visible, + dialogVisible: this.props.visible, + }; + } else if (this.props.prefKey != null) { + const visible = AsyncStorageManager.getBool(this.props.prefKey); + this.state = { + shouldRenderDialog: visible, + dialogVisible: visible, + }; + } else { + this.state = { + shouldRenderDialog: false, + dialogVisible: false, + }; + } + } onAnimationEnd = () => { this.setState({ - shouldShowDialog: this.props.visible, + shouldRenderDialog: false, }) } - shouldComponentUpdate(nextProps: Props): boolean { + shouldComponentUpdate(nextProps: Props, nextState: State): boolean { if (nextProps.visible) { - this.state.shouldShowDialog = true; - } else if (nextProps.visible !== this.props.visible) { + this.state.shouldRenderDialog = true; + this.state.dialogVisible = true; + } else if (nextProps.visible !== this.props.visible + || (!nextState.dialogVisible && nextState.dialogVisible !== this.state.dialogVisible)) { + this.state.dialogVisible = false; setTimeout(this.onAnimationEnd, 300); } return true; @@ -79,13 +101,13 @@ class MascotPopup extends React.Component { } onBackButtonPressAndroid = () => { - if (this.state.shouldShowDialog) { + if (this.state.dialogVisible) { const cancel = this.props.buttons.cancel; const action = this.props.buttons.action; if (cancel != null) - cancel.onPress(); + this.onDismiss(cancel.onPress); else - action.onPress(); + this.onDismiss(action.onPress); return true; } else { return false; @@ -100,8 +122,8 @@ class MascotPopup extends React.Component { marginRight: "10%", }} useNativeDriver={true} - animation={this.props.visible ? "bounceInLeft" : "bounceOutLeft"} - duration={this.props.visible ? 1000 : 300} + animation={this.state.dialogVisible ? "bounceInLeft" : "bounceOutLeft"} + duration={this.state.dialogVisible ? 1000 : 300} > { return ( { mode={"contained"} icon={action.icon} color={action.color} - onPress={action.onPress} + onPress={() => this.onDismiss(action.onPress)} > {action.message} @@ -195,7 +217,7 @@ class MascotPopup extends React.Component { mode={"contained"} icon={cancel.icon} color={cancel.color} - onPress={cancel.onPress} + onPress={() => this.onDismiss(cancel.onPress)} > {cancel.message} @@ -206,7 +228,7 @@ class MascotPopup extends React.Component { getBackground() { return ( - + this.onDismiss(this.props.buttons.cancel.onPress)}> { height: "100%", }} useNativeDriver={true} - animation={this.props.visible ? "fadeIn" : "fadeOut"} - duration={this.props.visible ? 300 : 300} + animation={this.state.dialogVisible ? "fadeIn" : "fadeOut"} + duration={this.state.dialogVisible ? 300 : 300} /> ); } + onDismiss = (callback?: ()=> void) => { + if (this.props.prefKey != null) { + AsyncStorageManager.set(this.props.prefKey, false); + this.setState({dialogVisible: false}); + } + if (callback != null) + callback(); + } + render() { - if (this.state.shouldShowDialog) { + if (this.state.shouldRenderDialog) { return ( {this.getBackground()} @@ -242,8 +273,7 @@ class MascotPopup extends React.Component { - ) - ; + ); } else return null; diff --git a/src/screens/Game/screens/GameStartScreen.js b/src/screens/Game/screens/GameStartScreen.js index 6033435..c16f093 100644 --- a/src/screens/Game/screens/GameStartScreen.js +++ b/src/screens/Game/screens/GameStartScreen.js @@ -33,11 +33,7 @@ type Props = { theme: CustomTheme, } -type State = { - mascotDialogVisible: boolean, -} - -class GameStartScreen extends React.Component { +class GameStartScreen extends React.Component { gridManager: GridManager; scores: Array; @@ -45,10 +41,6 @@ class GameStartScreen extends React.Component { gameStats: GameStats | null; isHighScore: boolean; - state = { - mascotDialogVisible: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.gameStartShowBanner.key), - } - constructor(props: Props) { super(props); this.gridManager = new GridManager(4, 4, props.theme); @@ -75,11 +67,6 @@ class GameStartScreen extends React.Component { AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.gameScores.key, this.scores); } - hideMascotDialog = () => { - AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.gameStartShowBanner.key, false); - this.setState({mascotDialogVisible: false}) - }; - getPiecesBackground() { let gridList = []; for (let i = 0; i < 18; i++) { @@ -415,7 +402,7 @@ class GameStartScreen extends React.Component { {this.getMainContent()} { cancel: { message: i18n.t("screens.game.mascotDialog.button"), icon: "check", - onPress: this.hideMascotDialog, } }} emotion={MASCOT_STYLE.COOL} diff --git a/src/screens/Home/HomeScreen.js b/src/screens/Home/HomeScreen.js index ec5c390..c8321df 100644 --- a/src/screens/Home/HomeScreen.js +++ b/src/screens/Home/HomeScreen.js @@ -84,7 +84,6 @@ type Props = { type State = { dialogVisible: boolean, - mascotDialogVisible: boolean, } /** @@ -112,9 +111,6 @@ class HomeScreen extends React.Component { }); this.state = { dialogVisible: false, - mascotDialogVisible: AsyncStorageManager.getBool( - AsyncStorageManager.PREFERENCES.homeShowBanner.key) - && !this.isLoggedIn, } } @@ -184,11 +180,6 @@ class HomeScreen extends React.Component { ; }; - hideMascotDialog = () => { - AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.homeShowBanner.key, false); - this.setState({mascotDialogVisible: false}) - }; - showDisconnectDialog = () => this.setState({dialogVisible: true}); hideDisconnectDialog = () => this.setState({dialogVisible: false}); @@ -525,10 +516,7 @@ class HomeScreen extends React.Component { * Callback when pressing the login button on the banner. * This hides the banner and takes the user to the login page. */ - onLogin = () => { - this.hideMascotDialog(); - this.props.navigation.navigate("login", {nextScreen: "profile"}); - } + onLogin = () => this.props.navigation.navigate("login", {nextScreen: "profile"}); render() { return ( @@ -554,26 +542,26 @@ class HomeScreen extends React.Component { renderListHeaderComponent={this.getListHeader} /> - + {!this.isLoggedIn + ? : null} { props.navigation.setOptions({title: currentGroup.name}) } this.state = { - mascotDialogVisible: - AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.planexShowBanner.key) - && AsyncStorageManager.getString(AsyncStorageManager.PREFERENCES.defaultStartScreen.key) - .toLowerCase() !== 'planex', dialogVisible: false, dialogTitle: "", dialogMessage: "", @@ -162,24 +157,11 @@ class PlanexScreen extends React.Component { this.props.navigation.addListener('focus', this.onScreenFocus); } - /** - * Callback used when closing the banner. - * This hides the banner and saves to preferences to prevent it from reopening - */ - onMascotDialogCancel = () => { - this.setState({mascotDialogVisible: false}); - AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.planexShowBanner.key, false); - }; - - /** * Callback used when the user clicks on the navigate to settings button. * This will hide the banner and open the SettingsScreen */ - onGoToSettings = () => { - this.onMascotDialogCancel(); - this.props.navigation.navigate('settings'); - }; + onGoToSettings = () => this.props.navigation.navigate('settings'); onScreenFocus = () => { this.handleNavigationParams(); @@ -357,8 +339,10 @@ class PlanexScreen extends React.Component { ? this.getWebView() : {this.getWebView()}} - { message: i18n.t("screens.planex.mascotDialog.cancel"), icon: "close", color: this.props.theme.colors.warning, - onPress: this.onMascotDialogCancel, } }} emotion={MASCOT_STYLE.INTELLO} - /> + /> : null } { refreshing: false, agendaItems: {}, calendarShowing: false, - mascotDialogVisible: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.eventsShowBanner.key) }; currentDate = getDateOnlyString(getCurrentDateString()); @@ -105,15 +103,6 @@ class PlanningScreen extends React.Component { } }; - /** - * Callback used when closing the banner. - * This hides the banner and saves to preferences to prevent it from reopening - */ - onHideMascotDialog = () => { - this.setState({mascotDialogVisible: false}); - AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.eventsShowBanner.key, false); - }; - /** * Function used to check if a row has changed * @@ -250,7 +239,7 @@ class PlanningScreen extends React.Component { onRef={this.onAgendaRef} /> { cancel: { message: i18n.t("screens.planning.mascotDialog.button"), icon: "check", - onPress: this.onHideMascotDialog, } }} emotion={MASCOT_STYLE.HAPPY} diff --git a/src/screens/Proxiwash/ProxiwashScreen.js b/src/screens/Proxiwash/ProxiwashScreen.js index 3a41cbf..59ec568 100644 --- a/src/screens/Proxiwash/ProxiwashScreen.js +++ b/src/screens/Proxiwash/ProxiwashScreen.js @@ -46,7 +46,6 @@ type State = { refreshing: boolean, modalCurrentDisplayItem: React.Node, machinesWatched: Array, - mascotDialogVisible: boolean, }; @@ -67,7 +66,6 @@ class ProxiwashScreen extends React.Component { refreshing: false, modalCurrentDisplayItem: null, machinesWatched: AsyncStorageManager.getObject(AsyncStorageManager.PREFERENCES.proxiwashWatchedMachines.key), - mascotDialogVisible: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.proxiwashShowBanner.key), }; /** @@ -84,15 +82,6 @@ class ProxiwashScreen extends React.Component { modalStateStrings[ProxiwashConstants.machineStates.UNKNOWN] = i18n.t('screens.proxiwash.modal.unknown'); } - /** - * Callback used when closing the banner. - * This hides the banner and saves to preferences to prevent it from reopening - */ - onHideMascotDialog = () => { - this.setState({mascotDialogVisible: false}); - AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.proxiwashShowBanner.key, false); - }; - /** * Setup notification channel for android and add listeners to detect notifications fired */ @@ -409,7 +398,7 @@ class ProxiwashScreen extends React.Component { updateData={this.state.machinesWatched.length}/> { cancel: { message: i18n.t("screens.proxiwash.mascotDialog.ok"), icon: "check", - onPress: this.onHideMascotDialog, } }} emotion={MASCOT_STYLE.NORMAL} diff --git a/src/screens/Services/ServicesScreen.js b/src/screens/Services/ServicesScreen.js index 6610a31..0f6fa7a 100644 --- a/src/screens/Services/ServicesScreen.js +++ b/src/screens/Services/ServicesScreen.js @@ -20,11 +20,6 @@ type Props = { theme: CustomTheme, } -type State = { - mascotDialogVisible: boolean, -} - - export type listItem = { title: string, description: string, @@ -33,14 +28,10 @@ export type listItem = { } -class ServicesScreen extends React.Component { +class ServicesScreen extends React.Component { finalDataset: Array - state = { - mascotDialogVisible: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.servicesShowBanner.key), - } - constructor(props) { super(props); const services = new ServicesManager(props.navigation); @@ -53,16 +44,6 @@ class ServicesScreen extends React.Component { }); } - - /** - * Callback used when closing the banner. - * This hides the banner and saves to preferences to prevent it from reopening - */ - onHideMascotDialog = () => { - this.setState({mascotDialogVisible: false}); - AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.servicesShowBanner.key, false); - }; - getAboutButton = () => @@ -146,7 +127,7 @@ class ServicesScreen extends React.Component { hasTab={true} />