import React, { useRef, useState } from 'react'; import { StyleSheet, View, Text, TouchableOpacity, Image, TouchableWithoutFeedback, NativeSyntheticEvent, NativeScrollEvent, } from 'react-native'; import { fontStyles } from '../../../styles/common'; import Icon from 'react-native-vector-icons/FontAwesome'; import { strings } from '../../../../locales/i18n'; import Device from '../../../util/device'; import AsyncStorage from '@react-native-community/async-storage'; import { CURRENT_APP_VERSION, WHATS_NEW_APP_VERSION_SEEN, } from '../../../constants/storage'; import StyledButton from '../StyledButton'; import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; import ReusableModal, { ReusableModalRef } from '../ReusableModal'; import { whatsNewList } from './'; import { Colors } from '../../../util/theme/models'; import { WHATS_NEW_MODAL_CONTAINER_ID, WHATS_NEW_MODAL_CLOSE_BUTTON_ID, } from '../../../constants/test-ids'; import { ScrollView } from 'react-native-gesture-handler'; const modalMargin = 24; const modalPadding = 24; const screenWidth = Device.getDeviceWidth(); const screenHeight = Device.getDeviceHeight(); const slideItemWidth = screenWidth - modalMargin * 2; const maxSlideItemHeight = screenHeight - 200; const slideImageWidth = slideItemWidth - modalPadding * 2; const imageAspectRatio = 128 / 264; const slideImageHeight = slideImageWidth * imageAspectRatio; const createStyles = (colors: Colors) => StyleSheet.create({ slideContent: { maxHeight: maxSlideItemHeight, }, slideItemContainer: { flex: 1, width: slideItemWidth, paddingHorizontal: modalPadding, paddingBottom: 16, }, progessContainer: { flexDirection: 'row', alignSelf: 'center', marginTop: 16, marginBottom: 8, }, slideCircle: { width: 8, height: 8, borderRadius: 8 / 2, backgroundColor: colors.icon.default, opacity: 0.4, marginHorizontal: 8, }, slideSolidCircle: { opacity: 1, }, button: { marginTop: 8, }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', marginBottom: 20, paddingHorizontal: modalPadding, }, headerCenterAux: { flex: 1, }, headerClose: { flex: 1, alignItems: 'flex-end', }, headerText: { ...fontStyles.bold, fontSize: 18, color: colors.text.default, }, slideImageContainer: { flexDirection: 'row', borderRadius: 10, marginBottom: 24, }, slideImage: { flex: 1, borderRadius: 10, width: slideImageWidth, height: slideImageHeight, }, slideTitle: { ...fontStyles.bold, fontSize: 16, marginBottom: 12, color: colors.text.default, }, slideDescription: { ...fontStyles.normal, fontSize: 14, lineHeight: 20, color: colors.text.default, marginBottom: 24, }, screen: { justifyContent: 'center', alignItems: 'center' }, modal: { backgroundColor: colors.background.default, borderRadius: 10, marginHorizontal: modalMargin, }, bodyContainer: { paddingVertical: 32, }, horizontalScrollView: { flexGrow: 0 }, }); interface WhatsNewModalProps { navigation: any; } const WhatsNewModal = (props: WhatsNewModalProps) => { const modalRef = useRef(null); const slideIds = [0, 1]; const [currentSlide, setCurrentSlide] = useState(slideIds[0]); const { colors } = useAppThemeFromContext() || mockTheme; const styles = createStyles(colors); const recordSeenModal = async () => { const version = await AsyncStorage.getItem(CURRENT_APP_VERSION); await AsyncStorage.setItem(WHATS_NEW_APP_VERSION_SEEN, version as string); }; const dismissModal = (callback?: () => void) => modalRef.current?.dismissModal(callback); const callButton = (onPress: any) => { dismissModal(() => onPress(props)); }; const renderSlideElement = (elementInfo: any) => { switch (elementInfo.type) { case 'title': return {elementInfo.title}; case 'description': return ( {elementInfo.description} ); case 'image': return ( ); case 'button': return ( callButton(elementInfo.onPress)} > {elementInfo.buttonText} ); } return null; }; const renderSlide = (slideInfo: any, index: number) => { const key = `slide-info-${index}`; return ( {slideInfo.map((elementInfo: any, elIndex: number) => { const elKey = `${key}-${elIndex}`; return {renderSlideElement(elementInfo)}; })} ); }; const onScrollEnd = (e: NativeSyntheticEvent) => { const xOffset = e.nativeEvent.contentOffset.x; const slideIndex = Math.round(xOffset / screenWidth); if (currentSlide === slideIndex) { return; } setCurrentSlide(slideIndex); }; const renderHeader = () => ( {strings('whats_new.title')} dismissModal()} hitSlop={{ top: 10, left: 10, bottom: 10, right: 10 }} > ); const renderProgressIndicators = () => ( {slideIds.map((id) => ( ))} ); return ( {renderHeader()} {whatsNewList.slides.map(renderSlide)} {renderProgressIndicators()} ); }; export default WhatsNewModal;