/*
* Copyright (c) 2019 - 2020 Arnaud Vergnet.
*
* This file is part of Campus INSAT.
*
* Campus INSAT is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Campus INSAT is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Campus INSAT. If not, see .
*/
import React, { useEffect, useRef, useState } from 'react';
import { Portal } from 'react-native-paper';
import * as Animatable from 'react-native-animatable';
import {
BackHandler,
Dimensions,
StyleSheet,
TouchableWithoutFeedback,
View,
} from 'react-native';
import Mascot from './Mascot';
import GENERAL_STYLES from '../../constants/Styles';
import MascotSpeechBubble, {
MascotSpeechBubbleProps,
} from './MascotSpeechBubble';
import { useMountEffect } from '../../utils/customHooks';
import { useRoute } from '@react-navigation/core';
import { useShouldShowMascot } from '../../context/preferencesContext';
type PropsType = MascotSpeechBubbleProps & {
emotion: number;
visible?: boolean;
};
const styles = StyleSheet.create({
background: {
position: 'absolute',
backgroundColor: 'rgba(0,0,0,0.7)',
width: '100%',
height: '100%',
},
container: {
marginTop: -80,
width: '100%',
},
});
const MASCOT_SIZE = Dimensions.get('window').height / 6;
const BUBBLE_HEIGHT = Dimensions.get('window').height / 3;
/**
* Component used to display a popup with the mascot.
*/
function MascotPopup(props: PropsType) {
const route = useRoute();
const { shouldShow, setShouldShow } = useShouldShowMascot(route.name);
const isVisible = () => {
if (props.visible !== undefined) {
return props.visible;
} else {
return shouldShow;
}
};
const [shouldRenderDialog, setShouldRenderDialog] = useState(isVisible());
const [dialogVisible, setDialogVisible] = useState(isVisible());
const lastVisibleProps = useRef(props.visible);
const lastVisibleState = useRef(dialogVisible);
useMountEffect(() => {
BackHandler.addEventListener('hardwareBackPress', onBackButtonPressAndroid);
});
useEffect(() => {
if (props.visible && !dialogVisible) {
setShouldRenderDialog(true);
setDialogVisible(true);
} else if (
lastVisibleProps.current !== props.visible ||
(!dialogVisible && dialogVisible !== lastVisibleState.current)
) {
setDialogVisible(false);
setTimeout(onAnimationEnd, 400);
}
lastVisibleProps.current = props.visible;
lastVisibleState.current = dialogVisible;
}, [props.visible, dialogVisible]);
const onAnimationEnd = () => {
setShouldRenderDialog(false);
};
const onBackButtonPressAndroid = (): boolean => {
if (dialogVisible) {
const { cancel } = props.buttons;
const { action } = props.buttons;
if (cancel) {
onDismiss(cancel.onPress);
} else if (action) {
onDismiss(action.onPress);
} else {
onDismiss();
}
return true;
}
return false;
};
const getSpeechBubble = () => {
return (
);
};
const getMascot = () => {
return (
);
};
const getBackground = () => {
return (
{
onDismiss(props.buttons.cancel?.onPress);
}}
>
);
};
const onDismiss = (callback?: () => void) => {
setShouldShow(false);
setDialogVisible(false);
if (callback) {
callback();
}
};
if (shouldRenderDialog) {
return (
{getBackground()}
{getMascot()}
{getSpeechBubble()}
);
}
return null;
}
export default MascotPopup;