import { NativeStackScreenProps } from '@react-navigation/native-stack' import React, { useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { ActivityIndicator, Platform, ScrollView, StyleSheet, Text, View } from 'react-native' import DeviceInfo from 'react-native-device-info' import { e164NumberSelector, nameSelector } from 'src/account/selectors' import { sendSupportRequest } from 'src/account/zendesk' import { showMessage } from 'src/alert/actions' import { phoneNumberVerifiedSelector, sessionIdSelector } from 'src/app/selectors' import Button, { BtnTypes } from 'src/components/Button' import KeyboardSpacer from 'src/components/KeyboardSpacer' import Switch from 'src/components/Switch' import TextInput from 'src/components/TextInput' import { APP_NAME, DEFAULT_TESTNET } from 'src/config' import { navigateBack } from 'src/navigator/NavigationService' import { Screens } from 'src/navigator/Screens' import { StackParamList } from 'src/navigator/types' import { userLocationDataSelector } from 'src/networkInfo/selectors' import { hooksPreviewApiUrlSelector } from 'src/positions/selectors' import { useDispatch, useSelector } from 'src/redux/hooks' import colors from 'src/styles/colors' import { typeScale } from 'src/styles/fonts' import Logger from 'src/utils/Logger' import { anonymizedPhone } from 'src/utils/phoneNumbers' import { currentAccountSelector } from 'src/web3/selectors' type Props = NativeStackScreenProps // Language agnostic loose regex for email validation const tester = /^[-!#$%&'*+/0-9=?A-Z^_a-z`{|}~\u0E00-\u0E7F](\.?[-!#$%&'*+/0-9=?A-Z^_a-z`{|}~\u0E00-\u0E7F])*@[A-Za-z0-9\u0E00-\u0E7F](-*\.?[A-Za-z0-9\u0E00-\u0E7F])*\.[A-Za-z\u0E00-\u0E7F](-?[A-Za-z0-9\u0E00-\u0E7F])+$/ // Validate email function - https://github.com/manishsaraan/email-validator export function validateEmail(email: string) { if (!email) return false if (email.length > 360) return false const emailParts = email.split('@') if (emailParts.length !== 2) return false const account = emailParts[0] const address = emailParts[1] if (account.length > 64) return false else if (address.length > 255) return false const domainParts = address.split('.') if (!domainParts[1] || domainParts[1].length < 2) return false if ( domainParts.some((part) => { return part.length > 63 }) ) { return false } return tester.test(email) } function SupportContact({ route }: Props) { const { t } = useTranslation() const cachedName = useSelector(nameSelector) const [message, setMessage] = useState('') const [email, setEmail] = useState('') const [name, setName] = useState(cachedName ?? '') const [attachLogs, setAttachLogs] = useState(true) const [inProgress, setInProgress] = useState(false) const e164PhoneNumber = useSelector(e164NumberSelector) const currentAccount = useSelector(currentAccountSelector) const sessionId = useSelector(sessionIdSelector) const numberVerifiedCentralized = useSelector(phoneNumberVerifiedSelector) const { countryCodeAlpha2: country, region } = useSelector(userLocationDataSelector) const hooksPreviewApiUrl = useSelector(hooksPreviewApiUrlSelector) const dispatch = useDispatch() const prefilledText = route.params?.prefilledText useEffect(() => { if (prefilledText) { setMessage(prefilledText) } }, [prefilledText]) const navigateBackAndToast = () => { navigateBack() dispatch(showMessage(t('contactSuccess'))) } const onPressSendEmail = useCallback(async () => { setInProgress(true) const userProperties = { appName: APP_NAME, version: DeviceInfo.getVersion(), systemVersion: DeviceInfo.getSystemVersion(), buildNumber: DeviceInfo.getBuildNumber(), apiLevel: DeviceInfo.getApiLevelSync(), os: Platform.OS, country, region, deviceId: DeviceInfo.getDeviceId(), deviceBrand: DeviceInfo.getBrand(), deviceModel: DeviceInfo.getModel(), address: currentAccount, sessionId, numberVerifiedCentralized, hooksPreviewEnabled: !!hooksPreviewApiUrl, network: DEFAULT_TESTNET, } const userId = e164PhoneNumber ? anonymizedPhone(e164PhoneNumber) : t('unknown') const attachments = attachLogs ? await Logger.getLogsToAttach() : [] try { await sendSupportRequest({ message, userProperties, logFiles: attachments, userEmail: email, userName: name, subject: t('supportEmailSubject', { appName: APP_NAME, user: userId }), }) // Used to prevent flickering of the activity indicator on quick uploads // Also navigateBackAndToast is a bit slow, so the timeout helps ensure that the loadingSpinner stays until the user is redirected setTimeout(() => setInProgress(false), 1000) navigateBackAndToast() } catch (error) { Logger.error('SupportContact', 'Error while sending logs to support', error) } }, [message, attachLogs, e164PhoneNumber, email, name]) return ( {t('contact')} {t('message')} {t('Name')} {t('Email')} {t('attachLogs')} {inProgress && ( )} {t('supportLegalCheckbox')}