import React, { useEffect, useState } from 'react'; import { useRoute } from '@react-navigation/native'; import { ActivityIndicator, Keyboard, KeyboardAvoidingView, LayoutAnimation, Platform, StyleSheet, TextInput, TouchableWithoutFeedback, View, } from 'react-native'; import { Icon } from 'react-native-elements'; import Share from 'react-native-share'; import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback'; import { BlueDoneAndDismissKeyboardInputAccessory, BlueFormLabel, BlueSpacing10, BlueSpacing20, BlueSpacing40 } from '../../BlueComponents'; import presentAlert from '../../components/Alert'; import { FButton, FContainer } from '../../components/FloatButtons'; import SafeArea from '../../components/SafeArea'; import { useTheme } from '../../components/themes'; import loc from '../../loc'; import { useStorage } from '../../hooks/context/useStorage'; const SignVerify = () => { const { colors } = useTheme(); const { wallets, sleep } = useStorage(); const { params } = useRoute(); const [isKeyboardVisible, setIsKeyboardVisible] = useState(false); const [address, setAddress] = useState(params.address ?? ''); const [message, setMessage] = useState(params.message ?? ''); const [signature, setSignature] = useState(''); const [loading, setLoading] = useState(false); const [messageHasFocus, setMessageHasFocus] = useState(false); const [isShareVisible, setIsShareVisible] = useState(false); const wallet = wallets.find(w => w.getID() === params.walletID); const isToolbarVisibleForAndroid = Platform.OS === 'android' && messageHasFocus && isKeyboardVisible; useEffect(() => { Keyboard.addListener(Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow', () => setIsKeyboardVisible(true)); Keyboard.addListener(Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide', () => setIsKeyboardVisible(false)); return () => { Keyboard.removeAllListeners(Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow'); Keyboard.removeAllListeners(Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide'); }; }, []); const stylesHooks = StyleSheet.create({ root: { backgroundColor: colors.elevated, }, text: { borderColor: colors.formBorder, borderBottomColor: colors.formBorder, backgroundColor: colors.inputBackgroundColor, color: colors.foregroundColor, }, }); const handleShare = () => { const baseUri = 'https://bluewallet.github.io/VerifySignature'; const uri = `${baseUri}?a=${address}&m=${encodeURIComponent(message)}&s=${encodeURIComponent(signature)}`; Share.open({ message: uri }).catch(error => console.log(error)); }; const handleSign = async () => { setLoading(true); await sleep(10); // wait for loading indicator to appear let newSignature; try { newSignature = wallet.signMessage(message, address); setSignature(newSignature); setIsShareVisible(true); } catch (e) { triggerHapticFeedback(HapticFeedbackTypes.NotificationError); presentAlert({ title: loc.errors.error, message: e.message }); } setLoading(false); }; const handleVerify = async () => { setLoading(true); await sleep(10); // wait for loading indicator to appear try { const res = wallet.verifyMessage(message, address, signature); presentAlert({ title: res ? loc._.success : loc.errors.error, message: res ? loc.addresses.sign_signature_correct : loc.addresses.sign_signature_incorrect, }); if (res) { triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess); } } catch (e) { triggerHapticFeedback(HapticFeedbackTypes.NotificationError); presentAlert({ title: loc.errors.error, message: e.message }); } setLoading(false); }; const handleFocus = value => { LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); setMessageHasFocus(value); }; if (loading) return ( ); return ( {!isKeyboardVisible && ( <> {loc.addresses.sign_help} )} setAddress(t.replace('\n', ''))} testID="Signature" style={[styles.text, stylesHooks.text]} autoCorrect={false} autoCapitalize="none" spellCheck={false} editable={!loading} /> setSignature(t.replace('\n', ''))} testID="Signature" style={[styles.text, stylesHooks.text]} autoCorrect={false} autoCapitalize="none" spellCheck={false} editable={!loading} /> handleFocus(true)} onBlur={() => handleFocus(false)} /> {isShareVisible && !isKeyboardVisible && ( <> } /> )} {!isKeyboardVisible && ( <> )} {Platform.select({ ios: ( setMessage('')} onPasteTapped={text => { setMessage(text); Keyboard.dismiss(); }} /> ), android: isToolbarVisibleForAndroid && ( { setMessage(''); Keyboard.dismiss(); }} onPasteTapped={text => { setMessage(text); Keyboard.dismiss(); }} /> ), })} ); }; export default SignVerify; const styles = StyleSheet.create({ root: { flex: 1, }, text: { paddingHorizontal: 8, paddingVertical: 8, marginTop: 5, marginHorizontal: 20, borderWidth: 1, borderBottomWidth: 0.5, borderRadius: 4, textAlignVertical: 'top', }, textMessage: { minHeight: 50, }, flex: { flex: 1, }, loading: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, justifyContent: 'center', alignItems: 'center', }, });