/* eslint react/prop-types: "off", react-native/no-inline-styles: "off" */ import React, { Component, forwardRef } from 'react'; import PropTypes from 'prop-types'; import { Icon, Text } from 'react-native-elements'; import { ActivityIndicator, Dimensions, InputAccessoryView, Keyboard, KeyboardAvoidingView, Platform, StyleSheet, TextInput, TouchableOpacity, View, I18nManager, } from 'react-native'; import Clipboard from '@react-native-clipboard/clipboard'; import NetworkTransactionFees, { NetworkTransactionFee, NetworkTransactionFeeType } from './models/networkTransactionFees'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { BlueCurrentTheme, useTheme } from './components/themes'; import loc, { formatStringAddTwoWhiteSpaces } from './loc'; const { height, width } = Dimensions.get('window'); const aspectRatio = height / width; let isIpad; if (aspectRatio > 1.6) { isIpad = false; } else { isIpad = true; } /** * TODO: remove this comment once this file gets properly converted to typescript. * * @type {React.FC} */ export const BlueButtonLink = forwardRef((props, ref) => { const { colors } = useTheme(); return ( {props.title} ); }); export const BlueCard = props => { return ; }; export const BlueText = props => { const { colors } = useTheme(); const style = StyleSheet.compose({ color: colors.foregroundColor, writingDirection: I18nManager.isRTL ? 'rtl' : 'ltr' }, props.style); return ; }; export const BlueTextCentered = props => { const { colors } = useTheme(); return ; }; export const BlueFormLabel = props => { const { colors } = useTheme(); return ( ); }; export const BlueFormMultiInput = props => { const { colors } = useTheme(); return ( ); }; export const BlueSpacing = props => { return ; }; export const BlueSpacing40 = props => { return ; }; export class is { static ipad() { return isIpad; } } export const BlueSpacing20 = props => { const { horizontal = false } = props; return ; }; export const BlueSpacing10 = props => { return ; }; export const BlueDismissKeyboardInputAccessory = () => { const { colors } = useTheme(); BlueDismissKeyboardInputAccessory.InputAccessoryViewID = 'BlueDismissKeyboardInputAccessory'; return Platform.OS !== 'ios' ? null : ( ); }; export const BlueDoneAndDismissKeyboardInputAccessory = props => { const { colors } = useTheme(); BlueDoneAndDismissKeyboardInputAccessory.InputAccessoryViewID = 'BlueDoneAndDismissKeyboardInputAccessory'; const onPasteTapped = async () => { const clipboard = await Clipboard.getString(); props.onPasteTapped(clipboard); }; const inputView = ( ); if (Platform.OS === 'ios') { return {inputView}; } else { return {inputView}; } }; export const BlueLoading = props => { return ( ); }; export class BlueReplaceFeeSuggestions extends Component { static propTypes = { onFeeSelected: PropTypes.func.isRequired, transactionMinimum: PropTypes.number.isRequired, }; static defaultProps = { transactionMinimum: 1, }; state = { customFeeValue: '1', }; async componentDidMount() { try { const cachedNetworkTransactionFees = JSON.parse(await AsyncStorage.getItem(NetworkTransactionFee.StorageKey)); if (cachedNetworkTransactionFees && 'fastestFee' in cachedNetworkTransactionFees) { this.setState({ networkFees: cachedNetworkTransactionFees }, () => this.onFeeSelected(NetworkTransactionFeeType.FAST)); } } catch (_) {} const networkFees = await NetworkTransactionFees.recommendedFees(); this.setState({ networkFees }, () => this.onFeeSelected(NetworkTransactionFeeType.FAST)); } onFeeSelected = selectedFeeType => { if (selectedFeeType !== NetworkTransactionFeeType.CUSTOM) { Keyboard.dismiss(); } if (selectedFeeType === NetworkTransactionFeeType.FAST) { this.props.onFeeSelected(this.state.networkFees.fastestFee); this.setState({ selectedFeeType }, () => this.props.onFeeSelected(this.state.networkFees.fastestFee)); } else if (selectedFeeType === NetworkTransactionFeeType.MEDIUM) { this.setState({ selectedFeeType }, () => this.props.onFeeSelected(this.state.networkFees.mediumFee)); } else if (selectedFeeType === NetworkTransactionFeeType.SLOW) { this.setState({ selectedFeeType }, () => this.props.onFeeSelected(this.state.networkFees.slowFee)); } else if (selectedFeeType === NetworkTransactionFeeType.CUSTOM) { this.props.onFeeSelected(Number(this.state.customFeeValue)); } }; onCustomFeeTextChange = customFee => { const customFeeValue = customFee.replace(/[^0-9]/g, ''); this.setState({ customFeeValue, selectedFeeType: NetworkTransactionFeeType.CUSTOM }, () => { this.onFeeSelected(NetworkTransactionFeeType.CUSTOM); }); }; render() { const { networkFees, selectedFeeType } = this.state; return ( {networkFees && [ { label: loc.send.fee_fast, time: loc.send.fee_10m, type: NetworkTransactionFeeType.FAST, rate: networkFees.fastestFee, active: selectedFeeType === NetworkTransactionFeeType.FAST, }, { label: formatStringAddTwoWhiteSpaces(loc.send.fee_medium), time: loc.send.fee_3h, type: NetworkTransactionFeeType.MEDIUM, rate: networkFees.mediumFee, active: selectedFeeType === NetworkTransactionFeeType.MEDIUM, }, { label: loc.send.fee_slow, time: loc.send.fee_1d, type: NetworkTransactionFeeType.SLOW, rate: networkFees.slowFee, active: selectedFeeType === NetworkTransactionFeeType.SLOW, }, ].map(({ label, type, time, rate, active }, index) => ( this.onFeeSelected(type)} style={[ { paddingHorizontal: 16, paddingVertical: 8, marginBottom: 10 }, active && { borderRadius: 8, backgroundColor: BlueCurrentTheme.colors.incomingBackgroundColor }, ]} > {label} ~{time} {rate} sat/byte ))} this.customTextInput.focus()} style={[ { paddingHorizontal: 16, paddingVertical: 8, marginBottom: 10 }, selectedFeeType === NetworkTransactionFeeType.CUSTOM && { borderRadius: 8, backgroundColor: BlueCurrentTheme.colors.incomingBackgroundColor, }, ]} > {formatStringAddTwoWhiteSpaces(loc.send.fee_custom)} (this.customTextInput = ref)} maxLength={9} style={{ backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor, borderBottomColor: BlueCurrentTheme.colors.formBorder, borderBottomWidth: 0.5, borderColor: BlueCurrentTheme.colors.formBorder, borderRadius: 4, borderWidth: 1.0, color: '#81868e', flex: 1, marginRight: 10, minHeight: 33, paddingRight: 5, paddingLeft: 5, }} onFocus={() => this.onCustomFeeTextChange(this.state.customFeeValue)} defaultValue={this.props.transactionMinimum} placeholder={loc.send.fee_satvbyte} placeholderTextColor="#81868e" inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID} /> sat/byte {loc.formatString(loc.send.fee_replace_minvb, { min: this.props.transactionMinimum })} ); } } export function BlueBigCheckmark({ style = {} }) { const defaultStyles = { backgroundColor: '#ccddf9', width: 120, height: 120, borderRadius: 60, alignSelf: 'center', justifyContent: 'center', marginTop: 0, marginBottom: 0, }; const mergedStyles = { ...defaultStyles, ...style }; return ( ); }