// @flow import * as React from 'react'; import {Avatar, Button, Card, Paragraph, Portal, withTheme} from 'react-native-paper'; import Mascot from "./Mascot"; 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 = { theme: CustomTheme, icon: string, title: string, message: string, buttons: { action: { message: string, icon: string | null, color: string | null, onPress?: () => void, }, cancel: { message: string, icon: string | null, color: string | null, onPress?: () => void, } }, emotion: number, visible?: boolean, prefKey?: string, } type State = { 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; constructor(props: Props) { super(props); this.windowWidth = Dimensions.get('window').width; 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({ shouldRenderDialog: false, }) } shouldComponentUpdate(nextProps: Props, nextState: State): boolean { if (nextProps.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; } componentDidMount(): * { BackHandler.addEventListener( 'hardwareBackPress', this.onBackButtonPressAndroid ) } onBackButtonPressAndroid = () => { if (this.state.dialogVisible) { const cancel = this.props.buttons.cancel; const action = this.props.buttons.action; if (cancel != null) this.onDismiss(cancel.onPress); else this.onDismiss(action.onPress); return true; } else { return false; } }; getSpeechBubble() { return ( : null} /> {this.props.message} {this.getButtons()} ); } getMascot() { return ( ); } getButtons() { const action = this.props.buttons.action; const cancel = this.props.buttons.cancel; return ( {action != null ? : null} {cancel != null ? : null} ); } getBackground() { return ( this.onDismiss(this.props.buttons.cancel.onPress)}> ); } 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.shouldRenderDialog) { return ( {this.getBackground()} {this.getMascot()} {this.getSpeechBubble()} ); } else return null; } } export default withTheme(MascotPopup);