2020-06-01 14:54:23 +02:00
|
|
|
/* eslint react/prop-types: "off", react-native/no-inline-styles: "off" */
|
2020-08-11 02:11:11 +02:00
|
|
|
/* global alert */
|
2020-06-26 21:27:13 +02:00
|
|
|
import React, { Component, useState } from 'react';
|
2018-06-25 00:22:46 +02:00
|
|
|
import Ionicons from 'react-native-vector-icons/Ionicons';
|
2018-12-25 15:16:23 +01:00
|
|
|
import PropTypes from 'prop-types';
|
2020-05-03 20:17:49 +02:00
|
|
|
import { Icon, Input, Text, Header, ListItem } from 'react-native-elements';
|
2018-12-12 04:33:28 +01:00
|
|
|
import {
|
|
|
|
TouchableOpacity,
|
|
|
|
TouchableWithoutFeedback,
|
|
|
|
Animated,
|
2019-12-25 04:35:47 +01:00
|
|
|
Alert,
|
2018-12-12 04:33:28 +01:00
|
|
|
ActivityIndicator,
|
|
|
|
View,
|
2019-08-06 00:25:36 +02:00
|
|
|
KeyboardAvoidingView,
|
2019-01-21 16:57:02 +01:00
|
|
|
UIManager,
|
2018-12-12 04:33:28 +01:00
|
|
|
StyleSheet,
|
|
|
|
Dimensions,
|
|
|
|
Image,
|
2019-02-09 21:46:43 +01:00
|
|
|
Keyboard,
|
2018-12-12 04:33:28 +01:00
|
|
|
SafeAreaView,
|
2019-01-31 07:52:21 +01:00
|
|
|
InputAccessoryView,
|
2018-12-12 04:33:28 +01:00
|
|
|
Platform,
|
2020-05-03 20:17:49 +02:00
|
|
|
FlatList,
|
2018-12-23 05:13:58 +01:00
|
|
|
TextInput,
|
2020-08-11 01:21:02 +02:00
|
|
|
PixelRatio,
|
2018-12-12 04:33:28 +01:00
|
|
|
} from 'react-native';
|
2020-06-09 23:02:25 +02:00
|
|
|
import Clipboard from '@react-native-community/clipboard';
|
2018-12-11 23:52:46 +01:00
|
|
|
import LinearGradient from 'react-native-linear-gradient';
|
2020-08-11 02:11:11 +02:00
|
|
|
import ActionSheet from './screen/ActionSheet';
|
2019-12-27 03:21:07 +01:00
|
|
|
import { LightningCustodianWallet, PlaceholderWallet } from './class';
|
2018-06-25 00:22:46 +02:00
|
|
|
import Carousel from 'react-native-snap-carousel';
|
2018-12-25 15:16:23 +01:00
|
|
|
import { BitcoinUnit } from './models/bitcoinUnits';
|
2020-06-19 02:24:26 +02:00
|
|
|
import * as NavigationService from './NavigationService';
|
2020-05-24 12:27:08 +02:00
|
|
|
import WalletGradient from './class/wallet-gradient';
|
2019-08-04 07:01:29 +02:00
|
|
|
import ToolTip from 'react-native-tooltip';
|
2019-08-03 23:29:15 +02:00
|
|
|
import { BlurView } from '@react-native-community/blur';
|
2020-08-11 02:11:11 +02:00
|
|
|
import ImagePicker from 'react-native-image-picker';
|
2019-08-04 07:01:29 +02:00
|
|
|
import showPopupMenu from 'react-native-popup-menu-android';
|
2020-09-14 12:49:08 +02:00
|
|
|
import NetworkTransactionFees, { NetworkTransactionFee, NetworkTransactionFeeType } from './models/networkTransactionFees';
|
2019-09-25 05:42:21 +02:00
|
|
|
import Biometric from './class/biometrics';
|
2020-08-11 02:11:11 +02:00
|
|
|
import { getSystemName } from 'react-native-device-info';
|
2020-06-24 13:56:35 +02:00
|
|
|
import { encodeUR } from 'bc-ur/dist';
|
|
|
|
import QRCode from 'react-native-qrcode-svg';
|
2020-09-14 12:49:08 +02:00
|
|
|
import AsyncStorage from '@react-native-community/async-storage';
|
2020-07-15 19:32:59 +02:00
|
|
|
import { useTheme } from '@react-navigation/native';
|
|
|
|
import { BlueCurrentTheme } from './components/themes';
|
2020-07-20 15:38:46 +02:00
|
|
|
import loc, { formatBalance, formatBalanceWithoutSuffix, formatBalancePlain, removeTrailingZeros, transactionTimeToReadable } from './loc';
|
2020-07-23 20:06:13 +02:00
|
|
|
import Lnurl from './class/lnurl';
|
2020-09-06 08:35:04 +02:00
|
|
|
import ScanQRCode from './screen/send/ScanQRCode';
|
2018-05-22 19:10:53 +02:00
|
|
|
/** @type {AppStorage} */
|
2020-06-01 14:54:23 +02:00
|
|
|
const BlueApp = require('./BlueApp');
|
2018-05-12 22:27:34 +02:00
|
|
|
const { height, width } = Dimensions.get('window');
|
|
|
|
const aspectRatio = height / width;
|
2019-05-02 22:33:03 +02:00
|
|
|
const BigNumber = require('bignumber.js');
|
2020-08-11 02:11:11 +02:00
|
|
|
const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
|
2020-06-09 16:08:18 +02:00
|
|
|
const currency = require('./blue_modules/currency');
|
2018-05-12 22:27:34 +02:00
|
|
|
let isIpad;
|
|
|
|
if (aspectRatio > 1.6) {
|
|
|
|
isIpad = false;
|
|
|
|
} else {
|
|
|
|
isIpad = true;
|
|
|
|
}
|
2018-01-30 23:42:38 +01:00
|
|
|
|
|
|
|
export class BlueButton extends Component {
|
2018-03-17 21:39:21 +01:00
|
|
|
render() {
|
2020-07-15 19:32:59 +02:00
|
|
|
let backgroundColor = this.props.backgroundColor ? this.props.backgroundColor : BlueCurrentTheme.colors.mainColor;
|
|
|
|
let fontColor = BlueCurrentTheme.colors.buttonTextColor;
|
2020-06-01 14:54:23 +02:00
|
|
|
if (this.props.disabled === true) {
|
2020-07-15 19:32:59 +02:00
|
|
|
backgroundColor = BlueCurrentTheme.colors.buttonDisabledBackgroundColor;
|
|
|
|
fontColor = BlueCurrentTheme.colors.buttonDisabledTextColor;
|
|
|
|
}
|
|
|
|
let buttonWidth = this.props.width ? this.props.width : width / 1.5;
|
|
|
|
if ('noMinWidth' in this.props) {
|
|
|
|
buttonWidth = 0;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<TouchableOpacity
|
|
|
|
style={{
|
|
|
|
flex: 1,
|
|
|
|
borderWidth: 0.7,
|
|
|
|
borderColor: 'transparent',
|
|
|
|
backgroundColor: backgroundColor,
|
|
|
|
minHeight: 45,
|
|
|
|
height: 45,
|
|
|
|
maxHeight: 45,
|
|
|
|
borderRadius: 25,
|
|
|
|
minWidth: buttonWidth,
|
|
|
|
justifyContent: 'center',
|
|
|
|
alignItems: 'center',
|
|
|
|
}}
|
|
|
|
{...this.props}
|
|
|
|
>
|
|
|
|
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
|
|
|
|
{this.props.icon && <Icon name={this.props.icon.name} type={this.props.icon.type} color={this.props.icon.color} />}
|
|
|
|
{this.props.title && <Text style={{ marginHorizontal: 8, fontSize: 16, color: fontColor }}>{this.props.title}</Text>}
|
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-11 00:38:07 +02:00
|
|
|
export const BlueButtonHook = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
let backgroundColor = props.backgroundColor ? props.backgroundColor : colors.mainColor;
|
|
|
|
let fontColor = colors.buttonTextColor;
|
|
|
|
if (props.disabled === true) {
|
|
|
|
backgroundColor = colors.buttonDisabledBackgroundColor;
|
|
|
|
fontColor = colors.buttonDisabledTextColor;
|
|
|
|
}
|
|
|
|
let buttonWidth = props.width ? props.width : width / 1.5;
|
|
|
|
if ('noMinWidth' in props) {
|
|
|
|
buttonWidth = 0;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<TouchableOpacity
|
|
|
|
style={{
|
|
|
|
flex: 1,
|
|
|
|
borderWidth: 0.7,
|
|
|
|
borderColor: 'transparent',
|
|
|
|
backgroundColor: backgroundColor,
|
|
|
|
minHeight: 45,
|
|
|
|
height: 45,
|
|
|
|
maxHeight: 45,
|
|
|
|
borderRadius: 25,
|
|
|
|
minWidth: buttonWidth,
|
|
|
|
justifyContent: 'center',
|
|
|
|
alignItems: 'center',
|
|
|
|
}}
|
|
|
|
{...props}
|
|
|
|
>
|
|
|
|
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
|
|
|
|
{props.icon && <Icon name={props.icon.name} type={props.icon.type} color={props.icon.color} />}
|
|
|
|
{props.title && <Text style={{ marginHorizontal: 8, fontSize: 16, color: fontColor }}>{props.title}</Text>}
|
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2020-07-15 19:32:59 +02:00
|
|
|
export class SecondButton extends Component {
|
|
|
|
render() {
|
|
|
|
let backgroundColor = this.props.backgroundColor ? this.props.backgroundColor : BlueCurrentTheme.colors.buttonBlueBackgroundColor;
|
|
|
|
let fontColor = BlueCurrentTheme.colors.buttonTextColor;
|
|
|
|
if (this.props.disabled === true) {
|
|
|
|
backgroundColor = BlueCurrentTheme.colors.buttonDisabledBackgroundColor;
|
|
|
|
fontColor = BlueCurrentTheme.colors.buttonDisabledTextColor;
|
2019-01-30 01:50:50 +01:00
|
|
|
}
|
2019-12-15 07:10:22 +01:00
|
|
|
let buttonWidth = this.props.width ? this.props.width : width / 1.5;
|
2020-06-01 14:54:23 +02:00
|
|
|
if ('noMinWidth' in this.props) {
|
2019-03-02 13:13:12 +01:00
|
|
|
buttonWidth = 0;
|
|
|
|
}
|
2018-01-30 23:42:38 +01:00
|
|
|
return (
|
2019-01-24 20:31:30 +01:00
|
|
|
<TouchableOpacity
|
2018-03-17 21:39:21 +01:00
|
|
|
style={{
|
2019-01-24 20:31:30 +01:00
|
|
|
flex: 1,
|
2018-03-17 21:39:21 +01:00
|
|
|
borderWidth: 0.7,
|
2018-06-30 15:36:13 +02:00
|
|
|
borderColor: 'transparent',
|
2019-01-30 01:50:50 +01:00
|
|
|
backgroundColor: backgroundColor,
|
2019-01-24 20:31:30 +01:00
|
|
|
minHeight: 45,
|
|
|
|
height: 45,
|
2019-01-25 19:56:43 +01:00
|
|
|
maxHeight: 45,
|
2019-01-24 20:31:30 +01:00
|
|
|
borderRadius: 25,
|
2019-03-02 13:13:12 +01:00
|
|
|
minWidth: buttonWidth,
|
2019-01-24 20:31:30 +01:00
|
|
|
justifyContent: 'center',
|
|
|
|
alignItems: 'center',
|
2018-03-17 21:39:21 +01:00
|
|
|
}}
|
2019-01-24 19:44:33 +01:00
|
|
|
{...this.props}
|
2019-01-24 20:31:30 +01:00
|
|
|
>
|
|
|
|
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
|
|
|
|
{this.props.icon && <Icon name={this.props.icon.name} type={this.props.icon.type} color={this.props.icon.color} />}
|
2019-01-30 01:50:50 +01:00
|
|
|
{this.props.title && <Text style={{ marginHorizontal: 8, fontSize: 16, color: fontColor }}>{this.props.title}</Text>}
|
2019-01-24 20:31:30 +01:00
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
2018-07-14 20:54:27 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-11 00:38:07 +02:00
|
|
|
export const BitcoinButton = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
return (
|
|
|
|
<TouchableOpacity testID={props.testID} onPress={props.onPress}>
|
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
borderColor: colors.hdborderColor,
|
|
|
|
borderWidth: 1,
|
|
|
|
borderRadius: 5,
|
|
|
|
backgroundColor: (props.active && colors.hdbackgroundColor) || colors.brandingColor,
|
|
|
|
minWidth: props.style.width,
|
|
|
|
minHeight: props.style.height,
|
|
|
|
height: props.style.height,
|
|
|
|
flex: 1,
|
2018-07-14 20:54:27 +02:00
|
|
|
}}
|
|
|
|
>
|
2020-08-11 00:38:07 +02:00
|
|
|
<View style={{ marginTop: 16, marginLeft: 16, marginBottom: 16 }}>
|
|
|
|
<Text style={{ color: colors.hdborderColor, fontWeight: 'bold' }}>{loc.wallets.add_bitcoin}</Text>
|
2018-07-14 20:54:27 +02:00
|
|
|
</View>
|
2020-08-11 00:38:07 +02:00
|
|
|
<Image
|
|
|
|
style={{ width: 34, height: 34, marginRight: 8, marginBottom: 8, justifyContent: 'flex-end', alignSelf: 'flex-end' }}
|
|
|
|
source={require('./img/addWallet/bitcoin.png')}
|
|
|
|
/>
|
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
};
|
2018-07-14 20:54:27 +02:00
|
|
|
|
2020-08-11 00:38:07 +02:00
|
|
|
export const LightningButton = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
return (
|
|
|
|
<TouchableOpacity onPress={props.onPress}>
|
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
borderColor: colors.lnborderColor,
|
|
|
|
borderWidth: 1,
|
|
|
|
borderRadius: 5,
|
|
|
|
backgroundColor: (props.active && colors.lnbackgroundColor) || colors.brandingColor,
|
|
|
|
minWidth: props.style.width,
|
|
|
|
minHeight: props.style.height,
|
|
|
|
height: props.style.height,
|
|
|
|
flex: 1,
|
2018-07-14 20:54:27 +02:00
|
|
|
}}
|
|
|
|
>
|
2020-08-11 00:38:07 +02:00
|
|
|
<View style={{ marginTop: 16, marginLeft: 16, marginBottom: 16 }}>
|
|
|
|
<Text style={{ color: colors.lnborderColor, fontWeight: 'bold' }}>{loc.wallets.add_lightning}</Text>
|
2018-07-14 20:54:27 +02:00
|
|
|
</View>
|
2020-08-11 00:38:07 +02:00
|
|
|
<Image
|
|
|
|
style={{ width: 34, height: 34, marginRight: 8, marginBottom: 8, justifyContent: 'flex-end', alignSelf: 'flex-end' }}
|
|
|
|
source={require('./img/addWallet/lightning.png')}
|
|
|
|
/>
|
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
};
|
2018-07-14 20:54:27 +02:00
|
|
|
|
2019-08-04 07:01:29 +02:00
|
|
|
export class BlueWalletNavigationHeader extends Component {
|
|
|
|
static propTypes = {
|
|
|
|
wallet: PropTypes.shape().isRequired,
|
2019-08-04 08:42:05 +02:00
|
|
|
onWalletUnitChange: PropTypes.func,
|
2019-08-04 07:01:29 +02:00
|
|
|
};
|
|
|
|
|
2019-12-14 07:52:14 +01:00
|
|
|
static getDerivedStateFromProps(props, state) {
|
|
|
|
return { wallet: props.wallet, onWalletUnitChange: props.onWalletUnitChange, allowOnchainAddress: state.allowOnchainAddress };
|
2019-08-04 07:01:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2019-12-14 07:52:14 +01:00
|
|
|
this.state = {
|
|
|
|
wallet: props.wallet,
|
|
|
|
walletPreviousPreferredUnit: props.wallet.getPreferredBalanceUnit(),
|
|
|
|
showManageFundsButton: false,
|
|
|
|
};
|
2019-08-04 07:01:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
handleCopyPress = _item => {
|
2020-07-20 15:38:46 +02:00
|
|
|
Clipboard.setString(formatBalance(this.state.wallet.getBalance(), this.state.wallet.getPreferredBalanceUnit()).toString());
|
2019-08-04 07:01:29 +02:00
|
|
|
};
|
|
|
|
|
2019-12-14 07:52:14 +01:00
|
|
|
componentDidMount() {
|
|
|
|
if (this.state.wallet.type === LightningCustodianWallet.type) {
|
|
|
|
this.state.wallet
|
|
|
|
.allowOnchainAddress()
|
|
|
|
.then(value => this.setState({ allowOnchainAddress: value }))
|
|
|
|
.catch(e => console.log('This Lndhub wallet does not have an onchain address API.'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-04 07:01:29 +02:00
|
|
|
handleBalanceVisibility = async _item => {
|
|
|
|
const wallet = this.state.wallet;
|
2019-09-25 05:42:21 +02:00
|
|
|
|
|
|
|
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
|
|
|
|
|
|
|
if (isBiometricsEnabled && wallet.hideBalance) {
|
|
|
|
if (!(await Biometric.unlockWithBiometrics())) {
|
|
|
|
return this.props.navigation.goBack();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-04 07:01:29 +02:00
|
|
|
wallet.hideBalance = !wallet.hideBalance;
|
|
|
|
this.setState({ wallet });
|
|
|
|
await BlueApp.saveToDisk();
|
|
|
|
};
|
|
|
|
|
|
|
|
showAndroidTooltip = () => {
|
|
|
|
showPopupMenu(this.toolTipMenuOptions(), this.handleToolTipSelection, this.walletBalanceText);
|
|
|
|
};
|
|
|
|
|
|
|
|
handleToolTipSelection = item => {
|
2020-07-20 15:38:46 +02:00
|
|
|
if (item === loc.transactions.details_copy || item.id === loc.transactions.details.copy) {
|
2019-08-04 07:01:29 +02:00
|
|
|
this.handleCopyPress();
|
|
|
|
} else if (item === 'balancePrivacy' || item.id === 'balancePrivacy') {
|
|
|
|
this.handleBalanceVisibility();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
toolTipMenuOptions() {
|
|
|
|
return Platform.select({
|
|
|
|
// NOT WORKING ATM.
|
|
|
|
// ios: [
|
|
|
|
// { text: this.state.wallet.hideBalance ? 'Show Balance' : 'Hide Balance', onPress: this.handleBalanceVisibility },
|
2020-07-20 15:38:46 +02:00
|
|
|
// { text: loc.transactions.details_copy, onPress: this.handleCopyPress },
|
2019-08-04 07:01:29 +02:00
|
|
|
// ],
|
|
|
|
android: this.state.wallet.hideBalance
|
|
|
|
? [{ id: 'balancePrivacy', label: this.state.wallet.hideBalance ? 'Show Balance' : 'Hide Balance' }]
|
|
|
|
: [
|
|
|
|
{ id: 'balancePrivacy', label: this.state.wallet.hideBalance ? 'Show Balance' : 'Hide Balance' },
|
2020-07-20 15:38:46 +02:00
|
|
|
{ id: loc.transactions.details_copy, label: loc.transactions.details.copy },
|
2019-08-04 07:01:29 +02:00
|
|
|
],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
changeWalletBalanceUnit() {
|
|
|
|
let walletPreviousPreferredUnit = this.state.wallet.getPreferredBalanceUnit();
|
|
|
|
const wallet = this.state.wallet;
|
|
|
|
if (walletPreviousPreferredUnit === BitcoinUnit.BTC) {
|
|
|
|
wallet.preferredBalanceUnit = BitcoinUnit.SATS;
|
|
|
|
walletPreviousPreferredUnit = BitcoinUnit.BTC;
|
|
|
|
} else if (walletPreviousPreferredUnit === BitcoinUnit.SATS) {
|
|
|
|
wallet.preferredBalanceUnit = BitcoinUnit.LOCAL_CURRENCY;
|
|
|
|
walletPreviousPreferredUnit = BitcoinUnit.SATS;
|
|
|
|
} else if (walletPreviousPreferredUnit === BitcoinUnit.LOCAL_CURRENCY) {
|
|
|
|
wallet.preferredBalanceUnit = BitcoinUnit.BTC;
|
|
|
|
walletPreviousPreferredUnit = BitcoinUnit.BTC;
|
|
|
|
} else {
|
|
|
|
wallet.preferredBalanceUnit = BitcoinUnit.BTC;
|
|
|
|
walletPreviousPreferredUnit = BitcoinUnit.BTC;
|
|
|
|
}
|
|
|
|
|
2019-08-31 08:54:11 +02:00
|
|
|
this.setState({ wallet, walletPreviousPreferredUnit: walletPreviousPreferredUnit }, () => {
|
|
|
|
this.props.onWalletUnitChange(wallet);
|
2019-08-04 08:42:05 +02:00
|
|
|
});
|
2019-08-04 07:01:29 +02:00
|
|
|
}
|
|
|
|
|
2019-09-29 22:01:27 +02:00
|
|
|
manageFundsPressed = () => {
|
|
|
|
this.props.onManageFundsPressed();
|
|
|
|
};
|
|
|
|
|
2019-08-04 07:01:29 +02:00
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<LinearGradient
|
|
|
|
colors={WalletGradient.gradientsFor(this.state.wallet.type)}
|
|
|
|
style={{ padding: 15, minHeight: 140, justifyContent: 'center' }}
|
|
|
|
>
|
|
|
|
<Image
|
|
|
|
source={
|
2019-08-04 08:42:05 +02:00
|
|
|
(LightningCustodianWallet.type === this.state.wallet.type && require('./img/lnd-shape.png')) || require('./img/btc-shape.png')
|
2019-08-04 07:01:29 +02:00
|
|
|
}
|
|
|
|
style={{
|
|
|
|
width: 99,
|
|
|
|
height: 94,
|
|
|
|
position: 'absolute',
|
|
|
|
bottom: 0,
|
|
|
|
right: 0,
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
|
|
|
|
<Text
|
|
|
|
numberOfLines={1}
|
|
|
|
style={{
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
fontSize: 19,
|
|
|
|
color: '#fff',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{this.state.wallet.getLabel()}
|
|
|
|
</Text>
|
|
|
|
{Platform.OS === 'ios' && (
|
|
|
|
<ToolTip
|
|
|
|
ref={tooltip => (this.tooltip = tooltip)}
|
|
|
|
actions={
|
|
|
|
this.state.wallet.hideBalance
|
|
|
|
? [{ text: this.state.wallet.hideBalance ? 'Show Balance' : 'Hide Balance', onPress: this.handleBalanceVisibility }]
|
|
|
|
: [
|
|
|
|
{ text: this.state.wallet.hideBalance ? 'Show Balance' : 'Hide Balance', onPress: this.handleBalanceVisibility },
|
2020-07-20 15:38:46 +02:00
|
|
|
{ text: loc.transactions.details_copy, onPress: this.handleCopyPress },
|
2019-08-04 07:01:29 +02:00
|
|
|
]
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
<TouchableOpacity
|
|
|
|
style={styles.balance}
|
|
|
|
onPress={() => this.changeWalletBalanceUnit()}
|
|
|
|
ref={ref => (this.walletBalanceText = ref)}
|
|
|
|
onLongPress={() => (Platform.OS === 'ios' ? this.tooltip.showMenu() : this.showAndroidTooltip())}
|
|
|
|
>
|
|
|
|
{this.state.wallet.hideBalance ? (
|
|
|
|
<BluePrivateBalance />
|
|
|
|
) : (
|
|
|
|
<Text
|
2020-06-01 14:54:23 +02:00
|
|
|
testID="WalletBalance"
|
2019-08-04 07:01:29 +02:00
|
|
|
numberOfLines={1}
|
|
|
|
adjustsFontSizeToFit
|
|
|
|
style={{
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
fontWeight: 'bold',
|
|
|
|
fontSize: 36,
|
|
|
|
color: '#fff',
|
|
|
|
}}
|
|
|
|
>
|
2020-07-20 15:38:46 +02:00
|
|
|
{formatBalance(this.state.wallet.getBalance(), this.state.wallet.getPreferredBalanceUnit(), true).toString()}
|
2019-08-04 07:01:29 +02:00
|
|
|
</Text>
|
|
|
|
)}
|
|
|
|
</TouchableOpacity>
|
2019-12-14 07:52:14 +01:00
|
|
|
{this.state.wallet.type === LightningCustodianWallet.type && this.state.allowOnchainAddress && (
|
2019-09-29 22:01:27 +02:00
|
|
|
<TouchableOpacity onPress={this.manageFundsPressed}>
|
2019-08-04 07:01:29 +02:00
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
marginTop: 14,
|
|
|
|
marginBottom: 10,
|
|
|
|
backgroundColor: 'rgba(255,255,255,0.2)',
|
|
|
|
borderRadius: 9,
|
|
|
|
minWidth: 119,
|
|
|
|
minHeight: 39,
|
|
|
|
width: 119,
|
|
|
|
height: 39,
|
|
|
|
justifyContent: 'center',
|
|
|
|
alignItems: 'center',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<Text
|
|
|
|
style={{
|
|
|
|
fontWeight: '500',
|
|
|
|
fontSize: 14,
|
|
|
|
color: '#FFFFFF',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{loc.lnd.title}
|
|
|
|
</Text>
|
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
|
|
|
)}
|
|
|
|
</LinearGradient>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-11 00:38:07 +02:00
|
|
|
export const BlueButtonLinkHook = props => {
|
2020-07-15 19:32:59 +02:00
|
|
|
const { colors } = useTheme();
|
|
|
|
return (
|
|
|
|
<TouchableOpacity
|
|
|
|
style={{
|
|
|
|
minHeight: 60,
|
|
|
|
minWidth: 100,
|
|
|
|
height: 60,
|
|
|
|
justifyContent: 'center',
|
|
|
|
}}
|
2020-08-11 00:38:07 +02:00
|
|
|
onPress={props.onPress}
|
|
|
|
{...props}
|
2020-07-15 19:32:59 +02:00
|
|
|
>
|
2020-08-11 00:38:07 +02:00
|
|
|
<Text style={{ color: colors.foregroundColor, textAlign: 'center', fontSize: 16 }}>{props.title}</Text>
|
2020-07-15 19:32:59 +02:00
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2018-07-14 20:54:27 +02:00
|
|
|
export class BlueButtonLink extends Component {
|
|
|
|
render() {
|
|
|
|
return (
|
2019-01-31 01:56:34 +01:00
|
|
|
<TouchableOpacity
|
2018-07-14 20:54:27 +02:00
|
|
|
style={{
|
2019-01-31 01:56:34 +01:00
|
|
|
minHeight: 60,
|
|
|
|
minWidth: 100,
|
|
|
|
height: 60,
|
|
|
|
justifyContent: 'center',
|
2018-07-14 20:54:27 +02:00
|
|
|
}}
|
2019-01-31 01:56:34 +01:00
|
|
|
{...this.props}
|
|
|
|
>
|
2020-07-15 19:32:59 +02:00
|
|
|
<Text style={{ color: BlueCurrentTheme.colors.foregroundColor, textAlign: 'center', fontSize: 16 }}>{this.props.title}</Text>
|
2019-01-31 01:56:34 +01:00
|
|
|
</TouchableOpacity>
|
2018-03-17 21:39:21 +01:00
|
|
|
);
|
2018-01-30 23:42:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-25 04:35:47 +01:00
|
|
|
export const BlueAlertWalletExportReminder = ({ onSuccess = () => {}, onFailure }) => {
|
|
|
|
Alert.alert(
|
2020-07-23 15:09:48 +02:00
|
|
|
loc.wallets.details_title,
|
|
|
|
loc.pleasebackup.ask,
|
2019-12-25 04:35:47 +01:00
|
|
|
[
|
2020-07-23 15:09:48 +02:00
|
|
|
{ text: loc.pleasebackup.ask_yes, onPress: onSuccess, style: 'cancel' },
|
|
|
|
{ text: loc.pleasebackup.ask_no, onPress: onFailure },
|
2019-12-25 04:35:47 +01:00
|
|
|
],
|
|
|
|
{ cancelable: false },
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2020-05-28 10:44:15 +02:00
|
|
|
export const BlueNavigationStyle = (navigation, withNavigationCloseButton = false, customCloseButtonFunction = undefined) => {
|
|
|
|
let headerRight;
|
2020-07-15 19:32:59 +02:00
|
|
|
const { colors, closeImage } = useTheme();
|
2020-05-28 10:44:15 +02:00
|
|
|
if (withNavigationCloseButton) {
|
|
|
|
headerRight = () => (
|
2020-05-27 13:12:17 +02:00
|
|
|
<TouchableOpacity
|
2020-05-28 10:44:15 +02:00
|
|
|
style={{ width: 40, height: 40, padding: 14 }}
|
|
|
|
onPress={
|
|
|
|
customCloseButtonFunction === undefined
|
|
|
|
? () => {
|
|
|
|
Keyboard.dismiss();
|
|
|
|
navigation.goBack(null);
|
|
|
|
}
|
|
|
|
: customCloseButtonFunction
|
|
|
|
}
|
|
|
|
>
|
2020-07-15 19:32:59 +02:00
|
|
|
<Image style={{ alignSelf: 'center' }} source={closeImage} />
|
2020-05-28 10:44:15 +02:00
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
headerRight = null;
|
|
|
|
}
|
2018-10-29 23:11:48 +01:00
|
|
|
|
2020-05-28 10:44:15 +02:00
|
|
|
return {
|
|
|
|
headerStyle: {
|
|
|
|
borderBottomWidth: 0,
|
|
|
|
elevation: 0,
|
2020-06-24 05:17:27 +02:00
|
|
|
shadowOpacity: 0,
|
2020-05-28 10:44:15 +02:00
|
|
|
shadowOffset: { height: 0, width: 0 },
|
|
|
|
},
|
|
|
|
headerTitleStyle: {
|
|
|
|
fontWeight: '600',
|
2020-07-15 19:32:59 +02:00
|
|
|
color: colors.foregroundColor,
|
2020-05-28 10:44:15 +02:00
|
|
|
},
|
|
|
|
headerRight,
|
|
|
|
headerBackTitleVisible: false,
|
2020-07-15 19:32:59 +02:00
|
|
|
headerTintColor: colors.foregroundColor,
|
2020-05-28 10:44:15 +02:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
export const BlueCreateTxNavigationStyle = (navigation, withAdvancedOptionsMenuButton = false, advancedOptionsMenuButtonAction) => {
|
|
|
|
let headerRight;
|
|
|
|
if (withAdvancedOptionsMenuButton) {
|
|
|
|
headerRight = () => (
|
2020-09-15 18:11:18 +02:00
|
|
|
<TouchableOpacity
|
|
|
|
style={{ minWidth: 40, height: 40, justifyContent: 'center' }}
|
|
|
|
onPress={advancedOptionsMenuButtonAction}
|
|
|
|
testID="advancedOptionsMenuButton"
|
|
|
|
>
|
2020-07-15 19:32:59 +02:00
|
|
|
<Icon size={22} name="kebab-horizontal" type="octicon" color={BlueCurrentTheme.colors.foregroundColor} />
|
2020-05-28 10:44:15 +02:00
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
headerRight = null;
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
headerStyle: {
|
|
|
|
borderBottomWidth: 0,
|
|
|
|
elevation: 0,
|
2020-05-28 15:57:01 +02:00
|
|
|
shadowOffset: { height: 0, width: 0 },
|
2020-05-28 10:44:15 +02:00
|
|
|
},
|
|
|
|
headerTitleStyle: {
|
|
|
|
fontWeight: '600',
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.foregroundColor,
|
2020-05-28 10:44:15 +02:00
|
|
|
},
|
2020-07-15 19:32:59 +02:00
|
|
|
headerTintColor: BlueCurrentTheme.colors.foregroundColor,
|
2020-05-28 10:44:15 +02:00
|
|
|
headerLeft: () => (
|
|
|
|
<TouchableOpacity
|
2020-07-15 19:32:59 +02:00
|
|
|
style={{ minWwidth: 40, height: 40, justifyContent: 'center', paddingHorizontal: 14 }}
|
2020-05-28 10:44:15 +02:00
|
|
|
onPress={() => {
|
|
|
|
Keyboard.dismiss();
|
|
|
|
navigation.goBack(null);
|
|
|
|
}}
|
|
|
|
>
|
2020-07-15 19:32:59 +02:00
|
|
|
<Image style={{}} source={BlueCurrentTheme.closeImage} />
|
2020-05-28 10:44:15 +02:00
|
|
|
</TouchableOpacity>
|
|
|
|
),
|
|
|
|
headerRight,
|
|
|
|
headerBackTitle: null,
|
|
|
|
};
|
|
|
|
};
|
2019-09-03 05:28:52 +02:00
|
|
|
|
2019-08-03 23:29:15 +02:00
|
|
|
export const BluePrivateBalance = () => {
|
|
|
|
return Platform.select({
|
|
|
|
ios: (
|
|
|
|
<View style={{ flexDirection: 'row' }}>
|
|
|
|
<BlurView style={styles.balanceBlur} blurType="light" blurAmount={25} />
|
|
|
|
<Icon name="eye-slash" type="font-awesome" color="#FFFFFF" />
|
|
|
|
</View>
|
|
|
|
),
|
|
|
|
android: (
|
|
|
|
<View style={{ flexDirection: 'row' }}>
|
|
|
|
<View style={{ backgroundColor: '#FFFFFF', opacity: 0.5, height: 30, width: 100, marginRight: 8 }} />
|
|
|
|
<Icon name="eye-slash" type="font-awesome" color="#FFFFFF" />
|
|
|
|
</View>
|
|
|
|
),
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2019-09-27 16:49:56 +02:00
|
|
|
export const BlueCopyToClipboardButton = ({ stringToCopy, displayText = false }) => {
|
2018-09-29 06:58:09 +02:00
|
|
|
return (
|
2020-08-16 04:43:17 +02:00
|
|
|
<TouchableOpacity onPress={() => Clipboard.setString(stringToCopy)}>
|
2020-07-20 15:38:46 +02:00
|
|
|
<Text style={{ fontSize: 13, fontWeight: '400', color: '#68bbe1' }}>{displayText || loc.transactions.details_copy}</Text>
|
2018-09-29 06:58:09 +02:00
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2019-01-21 14:55:39 +01:00
|
|
|
export class BlueCopyTextToClipboard extends Component {
|
|
|
|
static propTypes = {
|
|
|
|
text: PropTypes.string,
|
|
|
|
};
|
|
|
|
|
|
|
|
static defaultProps = {
|
|
|
|
text: '',
|
|
|
|
};
|
|
|
|
|
2019-02-02 04:45:18 +01:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2019-01-31 07:52:21 +01:00
|
|
|
if (Platform.OS === 'android') {
|
|
|
|
UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
|
|
|
|
}
|
2019-02-02 04:45:18 +01:00
|
|
|
this.state = { hasTappedText: false, address: props.text };
|
2019-01-21 16:57:02 +01:00
|
|
|
}
|
|
|
|
|
2019-05-02 22:33:03 +02:00
|
|
|
static getDerivedStateFromProps(props, state) {
|
|
|
|
if (state.hasTappedText) {
|
|
|
|
return { hasTappedText: state.hasTappedText, address: state.address };
|
|
|
|
} else {
|
|
|
|
return { hasTappedText: state.hasTappedText, address: props.text };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-21 14:55:39 +01:00
|
|
|
copyToClipboard = () => {
|
2019-02-02 04:45:18 +01:00
|
|
|
this.setState({ hasTappedText: true }, () => {
|
2019-01-21 14:55:39 +01:00
|
|
|
Clipboard.setString(this.props.text);
|
2020-07-20 15:38:46 +02:00
|
|
|
this.setState({ address: loc.wallets.xpub_copiedToClipboard }, () => {
|
2019-02-02 04:45:18 +01:00
|
|
|
setTimeout(() => {
|
|
|
|
this.setState({ hasTappedText: false, address: this.props.text });
|
|
|
|
}, 1000);
|
|
|
|
});
|
2019-01-21 14:55:39 +01:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<View style={{ justifyContent: 'center', alignItems: 'center', paddingHorizontal: 16 }}>
|
|
|
|
<TouchableOpacity onPress={this.copyToClipboard} disabled={this.state.hasTappedText}>
|
2019-02-02 04:45:18 +01:00
|
|
|
<Animated.Text style={styleCopyTextToClipboard.address} numberOfLines={0}>
|
|
|
|
{this.state.address}
|
|
|
|
</Animated.Text>
|
2019-01-21 14:55:39 +01:00
|
|
|
</TouchableOpacity>
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const styleCopyTextToClipboard = StyleSheet.create({
|
|
|
|
address: {
|
|
|
|
marginVertical: 32,
|
|
|
|
fontSize: 15,
|
2019-04-01 10:21:53 +02:00
|
|
|
color: '#9aa0aa',
|
2019-01-21 14:55:39 +01:00
|
|
|
textAlign: 'center',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2018-01-30 23:42:38 +01:00
|
|
|
export class SafeBlueArea extends Component {
|
2018-03-17 21:39:21 +01:00
|
|
|
render() {
|
2018-01-30 23:42:38 +01:00
|
|
|
return (
|
|
|
|
<SafeAreaView
|
2018-03-17 21:39:21 +01:00
|
|
|
forceInset={{ horizontal: 'always' }}
|
2020-07-15 19:32:59 +02:00
|
|
|
style={{ flex: 1, backgroundColor: BlueCurrentTheme.colors.background }}
|
|
|
|
{...this.props}
|
2018-01-30 23:42:38 +01:00
|
|
|
/>
|
2018-03-17 21:39:21 +01:00
|
|
|
);
|
2018-01-30 23:42:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class BlueCard extends Component {
|
2018-03-17 21:39:21 +01:00
|
|
|
render() {
|
2018-09-22 13:26:45 +02:00
|
|
|
return <View {...this.props} style={{ padding: 20 }} />;
|
2018-01-30 23:42:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class BlueText extends Component {
|
2018-03-17 21:39:21 +01:00
|
|
|
render() {
|
2018-09-01 01:28:19 +02:00
|
|
|
return (
|
|
|
|
<Text
|
2019-01-24 20:48:40 +01:00
|
|
|
style={{
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.foregroundColor,
|
2019-01-24 20:48:40 +01:00
|
|
|
...this.props.style,
|
|
|
|
}}
|
2018-12-11 23:52:46 +01:00
|
|
|
{...this.props}
|
2018-09-01 01:28:19 +02:00
|
|
|
/>
|
|
|
|
);
|
2018-01-30 23:42:38 +01:00
|
|
|
}
|
|
|
|
}
|
2020-07-15 19:32:59 +02:00
|
|
|
|
|
|
|
export const BlueTextHooks = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
return (
|
|
|
|
<Text
|
|
|
|
style={{
|
|
|
|
color: colors.foregroundColor,
|
|
|
|
...props.style,
|
|
|
|
}}
|
|
|
|
{...props}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
};
|
2018-07-14 20:54:27 +02:00
|
|
|
export class BlueTextCentered extends Component {
|
|
|
|
render() {
|
2020-07-15 19:32:59 +02:00
|
|
|
return <Text {...this.props} style={{ color: BlueCurrentTheme.colors.foregroundColor, textAlign: 'center' }} />;
|
2018-07-14 20:54:27 +02:00
|
|
|
}
|
|
|
|
}
|
2018-01-30 23:42:38 +01:00
|
|
|
|
2020-08-11 00:38:07 +02:00
|
|
|
export const BlueTextCenteredHooks = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
return <Text {...props} style={{ color: colors.foregroundColor, textAlign: 'center' }} />;
|
|
|
|
};
|
|
|
|
|
2020-06-26 21:27:13 +02:00
|
|
|
export const BlueListItem = React.memo(props => (
|
|
|
|
<ListItem
|
|
|
|
testID={props.testID}
|
|
|
|
bottomDivider
|
|
|
|
containerStyle={{
|
|
|
|
backgroundColor: 'transparent',
|
2020-07-15 19:32:59 +02:00
|
|
|
borderBottomColor: BlueCurrentTheme.colors.lightBorder,
|
2020-06-26 21:27:13 +02:00
|
|
|
paddingTop: 16,
|
|
|
|
paddingBottom: 16,
|
|
|
|
}}
|
|
|
|
titleStyle={{
|
2020-07-15 19:32:59 +02:00
|
|
|
color: props.disabled ? BlueCurrentTheme.colors.buttonDisabledTextColor : BlueCurrentTheme.colors.foregroundColor,
|
2020-06-26 21:27:13 +02:00
|
|
|
fontSize: 16,
|
|
|
|
fontWeight: '500',
|
|
|
|
}}
|
2020-07-15 19:32:59 +02:00
|
|
|
subtitleStyle={{ flexWrap: 'wrap', color: BlueCurrentTheme.colors.alternativeTextColor, fontWeight: '400', fontSize: 14 }}
|
2020-06-26 21:27:13 +02:00
|
|
|
subtitleNumberOfLines={1}
|
|
|
|
titleNumberOfLines={0}
|
|
|
|
Component={TouchableOpacity}
|
|
|
|
{...props}
|
|
|
|
/>
|
|
|
|
));
|
2018-01-30 23:42:38 +01:00
|
|
|
|
2020-07-15 19:32:59 +02:00
|
|
|
export const BlueListItemHooks = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
return (
|
|
|
|
<ListItem
|
|
|
|
testID={props.testID}
|
|
|
|
bottomDivider
|
|
|
|
containerStyle={{
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
borderBottomColor: colors.lightBorder,
|
|
|
|
paddingTop: 16,
|
|
|
|
paddingBottom: 16,
|
|
|
|
}}
|
|
|
|
titleStyle={{
|
|
|
|
color: props.disabled ? colors.buttonDisabledTextColor : colors.foregroundColor,
|
|
|
|
fontSize: 16,
|
|
|
|
fontWeight: '500',
|
|
|
|
}}
|
|
|
|
rightTitleStyle={{ flexWrap: 'wrap', color: colors.alternativeTextColor, fontWeight: '400', fontSize: 14 }}
|
|
|
|
subtitleStyle={{ flexWrap: 'wrap', color: colors.alternativeTextColor, fontWeight: '400', fontSize: 14 }}
|
|
|
|
subtitleNumberOfLines={1}
|
|
|
|
titleNumberOfLines={0}
|
|
|
|
Component={TouchableOpacity}
|
|
|
|
{...props}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2020-08-11 00:38:07 +02:00
|
|
|
export const BlueFormLabel = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
|
|
|
|
return <Text {...props} style={{ color: colors.foregroundColor, fontWeight: '400', marginLeft: 20 }} />;
|
|
|
|
};
|
2018-01-30 23:42:38 +01:00
|
|
|
|
|
|
|
export class BlueFormInput extends Component {
|
2018-03-17 21:39:21 +01:00
|
|
|
render() {
|
2018-05-06 19:14:22 +02:00
|
|
|
return (
|
2020-05-03 20:17:49 +02:00
|
|
|
<Input
|
2018-05-06 19:14:22 +02:00
|
|
|
{...this.props}
|
2020-07-15 19:32:59 +02:00
|
|
|
inputStyle={{ color: BlueCurrentTheme.colors.foregroundColor, maxWidth: width - 105 }}
|
2018-07-22 16:49:59 +02:00
|
|
|
containerStyle={{
|
|
|
|
marginTop: 5,
|
2020-07-15 19:32:59 +02:00
|
|
|
borderColor: BlueCurrentTheme.colors.inputBorderColor,
|
|
|
|
borderBottomColor: BlueCurrentTheme.colors.inputBorderColor,
|
2018-07-22 16:49:59 +02:00
|
|
|
borderWidth: 0.5,
|
|
|
|
borderBottomWidth: 0.5,
|
2020-07-15 19:32:59 +02:00
|
|
|
backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
|
2018-07-22 16:49:59 +02:00
|
|
|
}}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class BlueFormMultiInput extends Component {
|
2019-02-28 01:45:44 +01:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
selection: { start: 0, end: 0 },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-07-22 16:49:59 +02:00
|
|
|
render() {
|
|
|
|
return (
|
2018-12-23 05:13:58 +01:00
|
|
|
<TextInput
|
2018-07-22 16:49:59 +02:00
|
|
|
multiline
|
2018-11-01 20:44:39 +01:00
|
|
|
underlineColorAndroid="transparent"
|
2018-07-22 16:49:59 +02:00
|
|
|
numberOfLines={4}
|
2018-12-23 05:13:58 +01:00
|
|
|
style={{
|
2020-07-15 19:32:59 +02:00
|
|
|
paddingHorizontal: 8,
|
|
|
|
paddingVertical: 16,
|
2020-04-27 09:11:33 +02:00
|
|
|
flex: 1,
|
2018-07-14 20:54:27 +02:00
|
|
|
marginTop: 5,
|
2018-12-23 05:13:58 +01:00
|
|
|
marginHorizontal: 20,
|
2020-07-15 19:32:59 +02:00
|
|
|
borderColor: BlueCurrentTheme.colors.formBorder,
|
|
|
|
borderBottomColor: BlueCurrentTheme.colors.formBorder,
|
|
|
|
borderWidth: 1,
|
2018-05-22 19:12:16 +02:00
|
|
|
borderBottomWidth: 0.5,
|
2020-07-15 19:32:59 +02:00
|
|
|
borderRadius: 4,
|
|
|
|
backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
|
|
|
|
color: BlueCurrentTheme.colors.foregroundColor,
|
2020-08-16 14:41:56 +02:00
|
|
|
textAlignVertical: 'top',
|
2018-05-22 19:12:16 +02:00
|
|
|
}}
|
2018-12-23 05:13:58 +01:00
|
|
|
autoCorrect={false}
|
|
|
|
autoCapitalize="none"
|
|
|
|
spellCheck={false}
|
2018-12-22 17:51:07 +01:00
|
|
|
{...this.props}
|
2019-02-28 01:45:44 +01:00
|
|
|
selectTextOnFocus={false}
|
|
|
|
keyboardType={Platform.OS === 'android' ? 'visible-password' : 'default'}
|
2018-05-06 19:14:22 +02:00
|
|
|
/>
|
|
|
|
);
|
2018-05-06 19:12:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-30 23:42:38 +01:00
|
|
|
export class BlueHeader extends Component {
|
2018-03-17 21:39:21 +01:00
|
|
|
render() {
|
2018-01-30 23:42:38 +01:00
|
|
|
return (
|
|
|
|
<Header
|
|
|
|
{...this.props}
|
2018-06-25 00:22:46 +02:00
|
|
|
backgroundColor="transparent"
|
|
|
|
outerContainerStyles={{
|
|
|
|
borderBottomColor: 'transparent',
|
|
|
|
borderBottomWidth: 0,
|
|
|
|
}}
|
2018-06-28 03:43:28 +02:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class BlueHeaderDefaultSub extends Component {
|
|
|
|
render() {
|
|
|
|
return (
|
2020-07-15 19:32:59 +02:00
|
|
|
<SafeAreaView style={{ backgroundColor: BlueCurrentTheme.colors.brandingColor }}>
|
2018-09-19 03:59:16 +02:00
|
|
|
<Header
|
2020-07-15 19:32:59 +02:00
|
|
|
backgroundColor={BlueCurrentTheme.colors.background}
|
2020-05-03 20:17:49 +02:00
|
|
|
leftContainerStyle={{ minWidth: '100%' }}
|
2018-09-19 03:59:16 +02:00
|
|
|
outerContainerStyles={{
|
|
|
|
borderBottomColor: 'transparent',
|
|
|
|
borderBottomWidth: 0,
|
|
|
|
}}
|
|
|
|
leftComponent={
|
|
|
|
<Text
|
2018-10-04 03:49:29 +02:00
|
|
|
adjustsFontSizeToFit
|
2018-09-19 03:59:16 +02:00
|
|
|
style={{
|
|
|
|
fontWeight: 'bold',
|
2019-11-10 14:09:30 +01:00
|
|
|
fontSize: 30,
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.foregroundColor,
|
2018-09-19 03:59:16 +02:00
|
|
|
}}
|
|
|
|
>
|
2020-06-01 14:54:23 +02:00
|
|
|
{this.props.leftText}
|
2018-09-19 03:59:16 +02:00
|
|
|
</Text>
|
|
|
|
}
|
|
|
|
rightComponent={
|
|
|
|
<TouchableOpacity
|
|
|
|
onPress={() => {
|
|
|
|
if (this.props.onClose) this.props.onClose();
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<View style={stylesBlueIcon.box}>
|
|
|
|
<View style={stylesBlueIcon.ballTransparrent}>
|
2018-11-01 20:44:39 +01:00
|
|
|
<Image source={require('./img/close.png')} />
|
2018-09-19 03:59:16 +02:00
|
|
|
</View>
|
2018-06-28 03:43:28 +02:00
|
|
|
</View>
|
2018-09-19 03:59:16 +02:00
|
|
|
</TouchableOpacity>
|
|
|
|
}
|
2018-09-30 10:31:09 +02:00
|
|
|
{...this.props}
|
2018-09-19 03:59:16 +02:00
|
|
|
/>
|
|
|
|
</SafeAreaView>
|
2018-06-28 03:43:28 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-15 19:32:59 +02:00
|
|
|
export const BlueHeaderDefaultSubHooks = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
|
|
|
|
return (
|
|
|
|
<SafeAreaView>
|
|
|
|
<Header
|
|
|
|
backgroundColor={colors.background}
|
|
|
|
leftContainerStyle={{ minWidth: '100%' }}
|
|
|
|
outerContainerStyles={{
|
|
|
|
borderBottomColor: 'transparent',
|
|
|
|
borderBottomWidth: 0,
|
|
|
|
}}
|
|
|
|
leftComponent={
|
|
|
|
<Text
|
|
|
|
adjustsFontSizeToFit
|
|
|
|
style={{
|
|
|
|
fontWeight: 'bold',
|
|
|
|
fontSize: 30,
|
|
|
|
color: colors.foregroundColor,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{props.leftText}
|
|
|
|
</Text>
|
|
|
|
}
|
|
|
|
{...props}
|
|
|
|
/>
|
|
|
|
</SafeAreaView>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2020-09-08 18:06:41 +02:00
|
|
|
export const BlueHeaderDefaultMainHooks = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
return (
|
|
|
|
<Header
|
|
|
|
{...props}
|
|
|
|
leftComponent={{
|
|
|
|
text: props.leftText,
|
|
|
|
style: {
|
|
|
|
fontWeight: 'bold',
|
|
|
|
fontSize: 34,
|
|
|
|
color: colors.foregroundColor,
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
leftContainerStyle={{
|
|
|
|
minWidth: '70%',
|
|
|
|
height: 80,
|
|
|
|
}}
|
|
|
|
bottomDivider={false}
|
|
|
|
topDivider={false}
|
|
|
|
containerStyle={{
|
|
|
|
height: 44,
|
|
|
|
flexDirection: 'row',
|
|
|
|
backgroundColor: colors.elevatated,
|
|
|
|
borderTopColor: colors.elevatated,
|
|
|
|
borderBottomColor: colors.elevatated,
|
|
|
|
borderBottomWidth: 0,
|
|
|
|
}}
|
|
|
|
rightComponent={
|
|
|
|
props.onNewWalletPress && (
|
|
|
|
<TouchableOpacity
|
|
|
|
onPress={props.onNewWalletPress}
|
|
|
|
style={{
|
|
|
|
height: 100,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<BluePlusIcon />
|
|
|
|
</TouchableOpacity>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2018-06-28 03:43:28 +02:00
|
|
|
export class BlueHeaderDefaultMain extends Component {
|
|
|
|
render() {
|
|
|
|
return (
|
2020-07-15 19:32:59 +02:00
|
|
|
<SafeAreaView style={{ paddingVertical: 8, paddingHorizontal: 4, backgroundColor: BlueCurrentTheme.colors.background }}>
|
2018-09-30 11:56:32 +02:00
|
|
|
<Header
|
|
|
|
{...this.props}
|
2020-05-06 01:54:40 +02:00
|
|
|
leftComponent={{
|
2020-05-06 11:53:46 +02:00
|
|
|
text: this.props.leftText,
|
2020-05-06 01:54:40 +02:00
|
|
|
style: {
|
|
|
|
fontWeight: 'bold',
|
|
|
|
fontSize: 34,
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.foregroundColor,
|
2020-05-06 01:54:40 +02:00
|
|
|
},
|
|
|
|
}}
|
|
|
|
leftContainerStyle={{
|
|
|
|
minWidth: '70%',
|
2020-05-21 13:24:12 +02:00
|
|
|
height: 80,
|
2020-05-06 01:54:40 +02:00
|
|
|
}}
|
|
|
|
bottomDivider={false}
|
2020-07-15 19:32:59 +02:00
|
|
|
topDivider={false}
|
2020-05-06 01:54:40 +02:00
|
|
|
containerStyle={{
|
2020-05-21 13:24:12 +02:00
|
|
|
height: 44,
|
2020-05-06 11:53:46 +02:00
|
|
|
flexDirection: 'row',
|
2020-07-15 19:32:59 +02:00
|
|
|
backgroundColor: BlueCurrentTheme.colors.background,
|
|
|
|
borderTopColor: BlueCurrentTheme.colors.background,
|
|
|
|
borderBottomColor: BlueCurrentTheme.colors.background,
|
2020-09-08 18:06:41 +02:00
|
|
|
borderBottomWidth: 0,
|
2020-05-06 01:54:40 +02:00
|
|
|
}}
|
2018-09-30 11:56:32 +02:00
|
|
|
rightComponent={
|
2019-12-27 03:21:07 +01:00
|
|
|
this.props.onNewWalletPress && (
|
|
|
|
<TouchableOpacity
|
|
|
|
onPress={this.props.onNewWalletPress}
|
|
|
|
style={{
|
2020-05-21 13:24:12 +02:00
|
|
|
height: 100,
|
2019-12-27 03:21:07 +01:00
|
|
|
}}
|
|
|
|
>
|
|
|
|
<BluePlusIcon />
|
|
|
|
</TouchableOpacity>
|
|
|
|
)
|
2018-09-30 11:56:32 +02:00
|
|
|
}
|
|
|
|
/>
|
2018-09-19 03:59:16 +02:00
|
|
|
</SafeAreaView>
|
2018-03-17 21:39:21 +01:00
|
|
|
);
|
2018-01-30 23:42:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class BlueSpacing extends Component {
|
2018-03-17 21:39:21 +01:00
|
|
|
render() {
|
2020-07-15 19:32:59 +02:00
|
|
|
return <View {...this.props} style={{ height: 60 }} />;
|
2018-01-30 23:42:38 +01:00
|
|
|
}
|
|
|
|
}
|
2018-06-29 00:17:14 +02:00
|
|
|
|
2018-05-12 22:27:34 +02:00
|
|
|
export class BlueSpacing40 extends Component {
|
|
|
|
render() {
|
2020-07-15 19:32:59 +02:00
|
|
|
return <View {...this.props} style={{ height: 50 }} />;
|
2018-05-12 22:27:34 +02:00
|
|
|
}
|
|
|
|
}
|
2018-01-30 23:42:38 +01:00
|
|
|
|
2018-06-29 00:17:14 +02:00
|
|
|
export class BlueSpacingVariable extends Component {
|
|
|
|
render() {
|
|
|
|
if (isIpad) {
|
|
|
|
return <BlueSpacing40 {...this.props} />;
|
|
|
|
} else {
|
|
|
|
return <BlueSpacing {...this.props} />;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class is {
|
|
|
|
static ipad() {
|
|
|
|
return isIpad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-30 23:42:38 +01:00
|
|
|
export class BlueSpacing20 extends Component {
|
2018-06-25 00:22:46 +02:00
|
|
|
render() {
|
|
|
|
return <View {...this.props} style={{ height: 20, opacity: 0 }} />;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-22 14:08:31 +02:00
|
|
|
export class BlueSpacing10 extends Component {
|
|
|
|
render() {
|
|
|
|
return <View {...this.props} style={{ height: 10, opacity: 0 }} />;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-25 00:22:46 +02:00
|
|
|
export class BlueList extends Component {
|
2018-03-17 21:39:21 +01:00
|
|
|
render() {
|
2020-05-03 20:17:49 +02:00
|
|
|
return <FlatList {...this.props} />;
|
2018-01-30 23:42:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-31 07:52:21 +01:00
|
|
|
export class BlueUseAllFundsButton extends Component {
|
|
|
|
static InputAccessoryViewID = 'useMaxInputAccessoryViewID';
|
|
|
|
static propTypes = {
|
|
|
|
wallet: PropTypes.shape().isRequired,
|
|
|
|
onUseAllPressed: PropTypes.func.isRequired,
|
|
|
|
};
|
|
|
|
|
2020-06-09 16:08:18 +02:00
|
|
|
static defaultProps = {
|
|
|
|
unit: BitcoinUnit.BTC,
|
|
|
|
};
|
|
|
|
|
2019-01-31 07:52:21 +01:00
|
|
|
render() {
|
2019-08-06 00:25:36 +02:00
|
|
|
const inputView = (
|
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
flex: 1,
|
|
|
|
flexDirection: 'row',
|
|
|
|
maxHeight: 44,
|
|
|
|
justifyContent: 'space-between',
|
|
|
|
alignItems: 'center',
|
2020-07-15 19:32:59 +02:00
|
|
|
backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
|
2019-08-06 00:25:36 +02:00
|
|
|
}}
|
|
|
|
>
|
2019-08-06 20:47:16 +02:00
|
|
|
<View style={{ flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'flex-start' }}>
|
2019-08-07 03:42:41 +02:00
|
|
|
<Text
|
|
|
|
style={{
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.alternativeTextColor,
|
2019-08-07 03:42:41 +02:00
|
|
|
fontSize: 16,
|
|
|
|
marginLeft: 8,
|
|
|
|
marginRight: 0,
|
|
|
|
paddingRight: 0,
|
|
|
|
paddingLeft: 0,
|
|
|
|
paddingTop: 12,
|
|
|
|
paddingBottom: 12,
|
|
|
|
}}
|
|
|
|
>
|
2020-07-23 15:09:48 +02:00
|
|
|
{loc.send.input_total}
|
2019-01-31 07:52:21 +01:00
|
|
|
</Text>
|
2019-08-07 16:29:28 +02:00
|
|
|
{this.props.wallet.allowSendMax() && this.props.wallet.getBalance() > 0 ? (
|
2019-08-07 03:42:41 +02:00
|
|
|
<BlueButtonLink
|
|
|
|
onPress={this.props.onUseAllPressed}
|
2019-08-07 07:45:27 +02:00
|
|
|
style={{ marginLeft: 8, paddingRight: 0, paddingLeft: 0, paddingTop: 12, paddingBottom: 12 }}
|
2020-07-20 15:38:46 +02:00
|
|
|
title={`${formatBalanceWithoutSuffix(this.props.wallet.getBalance(), BitcoinUnit.BTC, true).toString()} ${BitcoinUnit.BTC}`}
|
2019-08-07 03:42:41 +02:00
|
|
|
/>
|
2019-08-07 07:45:27 +02:00
|
|
|
) : (
|
|
|
|
<Text
|
|
|
|
style={{
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.alternativeTextColor,
|
2019-08-07 07:45:27 +02:00
|
|
|
fontSize: 16,
|
|
|
|
marginLeft: 8,
|
|
|
|
marginRight: 0,
|
|
|
|
paddingRight: 0,
|
|
|
|
paddingLeft: 0,
|
|
|
|
paddingTop: 12,
|
|
|
|
paddingBottom: 12,
|
|
|
|
}}
|
|
|
|
>
|
2020-07-20 15:38:46 +02:00
|
|
|
{formatBalanceWithoutSuffix(this.props.wallet.getBalance(), BitcoinUnit.BTC, true).toString()} {BitcoinUnit.BTC}
|
2019-08-07 07:45:27 +02:00
|
|
|
</Text>
|
2019-08-06 00:25:36 +02:00
|
|
|
)}
|
2019-01-31 07:52:21 +01:00
|
|
|
</View>
|
2019-08-06 00:25:36 +02:00
|
|
|
<View style={{ flexDirection: 'row', justifyContent: 'flex-end', alignItems: 'flex-end' }}>
|
2019-08-07 03:42:41 +02:00
|
|
|
<BlueButtonLink
|
|
|
|
style={{ paddingRight: 8, paddingLeft: 0, paddingTop: 12, paddingBottom: 12 }}
|
2020-07-23 15:09:48 +02:00
|
|
|
title={loc.send.input_done}
|
2019-09-03 05:28:52 +02:00
|
|
|
onPress={() => Keyboard.dismiss()}
|
2019-08-07 03:42:41 +02:00
|
|
|
/>
|
2019-08-06 00:25:36 +02:00
|
|
|
</View>
|
|
|
|
</View>
|
2019-01-31 07:52:21 +01:00
|
|
|
);
|
2019-08-06 00:25:36 +02:00
|
|
|
if (Platform.OS === 'ios') {
|
|
|
|
return <InputAccessoryView nativeID={BlueUseAllFundsButton.InputAccessoryViewID}>{inputView}</InputAccessoryView>;
|
|
|
|
} else {
|
|
|
|
return <KeyboardAvoidingView style={{ height: 44 }}>{inputView}</KeyboardAvoidingView>;
|
|
|
|
}
|
2019-01-31 07:52:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-17 10:23:12 +01:00
|
|
|
export class BlueDismissKeyboardInputAccessory extends Component {
|
|
|
|
static InputAccessoryViewID = 'BlueDismissKeyboardInputAccessory';
|
|
|
|
|
|
|
|
render() {
|
2019-02-21 01:32:17 +01:00
|
|
|
return Platform.OS !== 'ios' ? null : (
|
2019-02-17 10:23:12 +01:00
|
|
|
<InputAccessoryView nativeID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}>
|
|
|
|
<View
|
|
|
|
style={{
|
2020-07-15 19:32:59 +02:00
|
|
|
backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
|
2019-02-17 10:23:12 +01:00
|
|
|
height: 44,
|
|
|
|
flex: 1,
|
|
|
|
flexDirection: 'row',
|
|
|
|
justifyContent: 'flex-end',
|
|
|
|
alignItems: 'center',
|
|
|
|
}}
|
|
|
|
>
|
2020-07-23 15:09:48 +02:00
|
|
|
<BlueButtonLink title={loc.send.input_done} onPress={() => Keyboard.dismiss()} />
|
2019-02-17 10:23:12 +01:00
|
|
|
</View>
|
|
|
|
</InputAccessoryView>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-29 06:18:32 +02:00
|
|
|
export class BlueDoneAndDismissKeyboardInputAccessory extends Component {
|
|
|
|
static InputAccessoryViewID = 'BlueDoneAndDismissKeyboardInputAccessory';
|
|
|
|
|
|
|
|
onPasteTapped = async () => {
|
|
|
|
const clipboard = await Clipboard.getString();
|
|
|
|
this.props.onPasteTapped(clipboard);
|
|
|
|
};
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const inputView = (
|
|
|
|
<View
|
|
|
|
style={{
|
2020-07-15 19:32:59 +02:00
|
|
|
backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
|
2019-08-29 06:18:32 +02:00
|
|
|
flexDirection: 'row',
|
|
|
|
justifyContent: 'flex-end',
|
|
|
|
alignItems: 'center',
|
2020-04-27 09:11:33 +02:00
|
|
|
maxHeight: 44,
|
2019-08-29 06:18:32 +02:00
|
|
|
}}
|
|
|
|
>
|
2020-07-23 15:09:48 +02:00
|
|
|
<BlueButtonLink title={loc.send.input_clear} onPress={this.props.onClearTapped} />
|
|
|
|
<BlueButtonLink title={loc.send.input_paste} onPress={this.onPasteTapped} />
|
|
|
|
<BlueButtonLink title={loc.send.input_done} onPress={() => Keyboard.dismiss()} />
|
2019-08-29 06:18:32 +02:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
|
|
|
|
if (Platform.OS === 'ios') {
|
2019-08-30 02:42:49 +02:00
|
|
|
return <InputAccessoryView nativeID={BlueDoneAndDismissKeyboardInputAccessory.InputAccessoryViewID}>{inputView}</InputAccessoryView>;
|
2019-08-29 06:18:32 +02:00
|
|
|
} else {
|
2020-04-27 09:11:33 +02:00
|
|
|
return <KeyboardAvoidingView>{inputView}</KeyboardAvoidingView>;
|
2019-08-29 06:18:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-25 00:22:46 +02:00
|
|
|
export class BlueLoading extends Component {
|
2018-03-17 21:39:21 +01:00
|
|
|
render() {
|
2018-06-25 00:22:46 +02:00
|
|
|
return (
|
2020-07-16 02:18:35 +02:00
|
|
|
<View style={{ flex: 1, paddingTop: 200 }} {...this.props}>
|
2020-07-15 19:32:59 +02:00
|
|
|
<ActivityIndicator />
|
|
|
|
</View>
|
2018-06-25 00:22:46 +02:00
|
|
|
);
|
2018-01-30 23:42:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-15 19:32:59 +02:00
|
|
|
export const BlueLoadingHook = () => {
|
|
|
|
return (
|
2020-07-16 02:18:35 +02:00
|
|
|
<View style={{ flex: 1, paddingTop: 200 }}>
|
2020-07-15 19:32:59 +02:00
|
|
|
<ActivityIndicator />
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2018-06-25 00:22:46 +02:00
|
|
|
const stylesBlueIcon = StyleSheet.create({
|
|
|
|
container: {
|
|
|
|
flex: 1,
|
|
|
|
},
|
|
|
|
box1: {
|
|
|
|
position: 'relative',
|
|
|
|
top: 15,
|
|
|
|
},
|
2018-06-28 03:43:28 +02:00
|
|
|
box: {
|
2018-09-19 03:59:16 +02:00
|
|
|
alignSelf: 'flex-end',
|
|
|
|
paddingHorizontal: 14,
|
|
|
|
paddingTop: 8,
|
2018-06-28 03:43:28 +02:00
|
|
|
},
|
2019-01-31 07:52:21 +01:00
|
|
|
boxIncoming: {
|
2018-06-25 00:22:46 +02:00
|
|
|
position: 'relative',
|
|
|
|
},
|
|
|
|
ball: {
|
|
|
|
width: 30,
|
|
|
|
height: 30,
|
|
|
|
borderRadius: 15,
|
|
|
|
},
|
2019-01-31 07:52:21 +01:00
|
|
|
ballIncoming: {
|
2018-06-25 00:22:46 +02:00
|
|
|
width: 30,
|
|
|
|
height: 30,
|
|
|
|
borderRadius: 15,
|
2018-12-31 23:29:36 +01:00
|
|
|
transform: [{ rotate: '-45deg' }],
|
2020-05-03 20:17:49 +02:00
|
|
|
justifyContent: 'center',
|
2018-12-31 23:29:36 +01:00
|
|
|
},
|
2019-01-31 07:52:21 +01:00
|
|
|
ballIncomingWithoutRotate: {
|
2018-12-31 23:29:36 +01:00
|
|
|
width: 30,
|
|
|
|
height: 30,
|
|
|
|
borderRadius: 15,
|
2018-06-25 00:22:46 +02:00
|
|
|
},
|
|
|
|
ballReceive: {
|
|
|
|
width: 30,
|
|
|
|
height: 30,
|
|
|
|
borderBottomLeftRadius: 15,
|
|
|
|
transform: [{ rotate: '-45deg' }],
|
|
|
|
},
|
|
|
|
ballOutgoing: {
|
|
|
|
width: 30,
|
|
|
|
height: 30,
|
|
|
|
borderRadius: 15,
|
2018-12-31 23:29:36 +01:00
|
|
|
transform: [{ rotate: '225deg' }],
|
2020-05-03 20:17:49 +02:00
|
|
|
justifyContent: 'center',
|
2018-06-25 00:22:46 +02:00
|
|
|
},
|
2018-12-28 22:43:38 +01:00
|
|
|
ballOutgoingWithoutRotate: {
|
|
|
|
width: 30,
|
|
|
|
height: 30,
|
|
|
|
borderRadius: 15,
|
|
|
|
},
|
2020-03-29 17:33:37 +02:00
|
|
|
ballOutgoingExpired: {
|
|
|
|
width: 30,
|
|
|
|
height: 30,
|
|
|
|
borderRadius: 15,
|
2020-05-03 20:17:49 +02:00
|
|
|
justifyContent: 'center',
|
2020-03-29 17:33:37 +02:00
|
|
|
},
|
2018-06-25 00:22:46 +02:00
|
|
|
ballTransparrent: {
|
|
|
|
width: 30,
|
|
|
|
height: 30,
|
|
|
|
borderRadius: 15,
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
},
|
|
|
|
ballDimmed: {
|
|
|
|
width: 30,
|
|
|
|
height: 30,
|
|
|
|
borderRadius: 15,
|
|
|
|
backgroundColor: 'gray',
|
|
|
|
},
|
|
|
|
});
|
2020-09-09 01:36:35 +02:00
|
|
|
|
|
|
|
export const BluePlusIcon = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
const stylesBlueIconHooks = StyleSheet.create({
|
|
|
|
ball: {
|
|
|
|
backgroundColor: colors.buttonBackgroundColor,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return (
|
|
|
|
<View {...props} style={stylesBlueIcon.container}>
|
|
|
|
<View style={stylesBlueIcon.box1}>
|
|
|
|
<View style={[stylesBlueIcon.ball, stylesBlueIconHooks.ball]}>
|
|
|
|
<Ionicons
|
|
|
|
{...props}
|
|
|
|
name="ios-add"
|
|
|
|
size={26}
|
|
|
|
style={{
|
|
|
|
color: colors.foregroundColor,
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
left: 8,
|
|
|
|
top: 1,
|
|
|
|
}}
|
|
|
|
/>
|
2018-06-25 00:22:46 +02:00
|
|
|
</View>
|
|
|
|
</View>
|
2020-09-09 01:36:35 +02:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
};
|
2018-01-30 23:42:38 +01:00
|
|
|
|
2020-09-09 01:36:35 +02:00
|
|
|
export const BlueTransactionIncomingIcon = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
const stylesBlueIconHooks = StyleSheet.create({
|
|
|
|
ballIncoming: {
|
|
|
|
backgroundColor: colors.ballReceive,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return (
|
|
|
|
<View {...props}>
|
|
|
|
<View style={stylesBlueIcon.boxIncoming}>
|
|
|
|
<View style={[stylesBlueIcon.ballIncoming, stylesBlueIconHooks.ballIncoming]}>
|
|
|
|
<Icon {...props} name="arrow-down" size={16} type="font-awesome" color={colors.incomingForegroundColor} />
|
2018-01-30 23:42:38 +01:00
|
|
|
</View>
|
2018-06-25 00:22:46 +02:00
|
|
|
</View>
|
2020-09-09 01:36:35 +02:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
};
|
2018-06-25 00:22:46 +02:00
|
|
|
|
2020-09-09 01:36:35 +02:00
|
|
|
export const BlueTransactionPendingIcon = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
|
|
|
|
const stylesBlueIconHooks = StyleSheet.create({
|
|
|
|
ball: {
|
|
|
|
backgroundColor: colors.buttonBackgroundColor,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return (
|
|
|
|
<View {...props}>
|
|
|
|
<View style={stylesBlueIcon.boxIncoming}>
|
|
|
|
<View style={[stylesBlueIcon.ball, stylesBlueIconHooks.ball]}>
|
|
|
|
<Icon
|
|
|
|
{...props}
|
|
|
|
name="kebab-horizontal"
|
|
|
|
size={16}
|
|
|
|
type="octicon"
|
|
|
|
color={colors.foregroundColor}
|
|
|
|
iconStyle={{ left: 0, top: 7 }}
|
|
|
|
/>
|
2018-06-25 00:22:46 +02:00
|
|
|
</View>
|
|
|
|
</View>
|
2020-09-09 01:36:35 +02:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
};
|
2018-06-25 00:22:46 +02:00
|
|
|
|
2020-09-09 01:36:35 +02:00
|
|
|
export const BlueTransactionExpiredIcon = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
const stylesBlueIconHooks = StyleSheet.create({
|
|
|
|
ballOutgoingExpired: {
|
|
|
|
backgroundColor: colors.ballOutgoingExpired,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return (
|
|
|
|
<View {...props}>
|
|
|
|
<View style={stylesBlueIcon.boxIncoming}>
|
|
|
|
<View style={[stylesBlueIcon.ballOutgoingExpired, stylesBlueIconHooks.ballOutgoingExpired]}>
|
|
|
|
<Icon {...props} name="clock" size={16} type="octicon" color="#9AA0AA" iconStyle={{ left: 0, top: 0 }} />
|
2018-12-28 22:43:38 +01:00
|
|
|
</View>
|
|
|
|
</View>
|
2020-09-09 01:36:35 +02:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
};
|
2018-12-28 22:43:38 +01:00
|
|
|
|
2020-09-09 01:36:35 +02:00
|
|
|
export const BlueTransactionOnchainIcon = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
const stylesBlueIconHooks = StyleSheet.create({
|
|
|
|
ballIncoming: {
|
|
|
|
backgroundColor: colors.ballReceive,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return (
|
|
|
|
<View {...props}>
|
|
|
|
<View style={stylesBlueIcon.boxIncoming}>
|
|
|
|
<View style={[stylesBlueIcon.ballIncoming, stylesBlueIconHooks.ballIncoming]}>
|
|
|
|
<Icon
|
|
|
|
{...props}
|
|
|
|
name="link"
|
|
|
|
size={16}
|
|
|
|
type="font-awesome"
|
|
|
|
color={colors.incomingForegroundColor}
|
|
|
|
iconStyle={{ left: 0, top: 0, transform: [{ rotate: '-45deg' }] }}
|
|
|
|
/>
|
2018-09-01 01:28:19 +02:00
|
|
|
</View>
|
|
|
|
</View>
|
2020-09-09 01:36:35 +02:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
};
|
2018-09-01 01:28:19 +02:00
|
|
|
|
2020-09-09 01:36:35 +02:00
|
|
|
export const BlueTransactionOffchainIcon = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
const stylesBlueIconHooks = StyleSheet.create({
|
|
|
|
ballOutgoingWithoutRotate: {
|
|
|
|
backgroundColor: colors.ballOutgoing,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return (
|
|
|
|
<View {...props}>
|
|
|
|
<View style={stylesBlueIcon.boxIncoming}>
|
|
|
|
<View style={[stylesBlueIcon.ballOutgoingWithoutRotate, stylesBlueIconHooks.ballOutgoingWithoutRotate]}>
|
|
|
|
<Icon
|
|
|
|
{...props}
|
|
|
|
name="bolt"
|
|
|
|
size={16}
|
|
|
|
type="font-awesome"
|
|
|
|
color={colors.outgoingForegroundColor}
|
|
|
|
iconStyle={{ left: 0, marginTop: 6 }}
|
|
|
|
/>
|
2018-09-05 00:18:24 +02:00
|
|
|
</View>
|
|
|
|
</View>
|
2020-09-09 01:36:35 +02:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
};
|
2018-09-05 00:18:24 +02:00
|
|
|
|
2020-09-09 01:36:35 +02:00
|
|
|
export const BlueTransactionOffchainIncomingIcon = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
const stylesBlueIconHooks = StyleSheet.create({
|
|
|
|
ballIncomingWithoutRotate: {
|
|
|
|
backgroundColor: colors.ballReceive,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return (
|
|
|
|
<View {...props}>
|
|
|
|
<View style={stylesBlueIcon.boxIncoming}>
|
|
|
|
<View style={[stylesBlueIcon.ballIncomingWithoutRotate, stylesBlueIconHooks.ballIncomingWithoutRotate]}>
|
|
|
|
<Icon
|
|
|
|
{...props}
|
|
|
|
name="bolt"
|
|
|
|
size={16}
|
|
|
|
type="font-awesome"
|
|
|
|
color={colors.incomingForegroundColor}
|
|
|
|
iconStyle={{ left: 0, marginTop: 6 }}
|
|
|
|
/>
|
2018-09-05 00:18:24 +02:00
|
|
|
</View>
|
|
|
|
</View>
|
2020-09-09 01:36:35 +02:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
};
|
2018-09-05 00:18:24 +02:00
|
|
|
|
2020-09-09 01:36:35 +02:00
|
|
|
export const BlueTransactionOutgoingIcon = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
const stylesBlueIconHooks = StyleSheet.create({
|
|
|
|
ballOutgoing: {
|
|
|
|
backgroundColor: colors.ballOutgoing,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return (
|
|
|
|
<View {...props}>
|
|
|
|
<View style={stylesBlueIcon.boxIncoming}>
|
|
|
|
<View style={[stylesBlueIcon.ballOutgoing, stylesBlueIconHooks.ballOutgoing]}>
|
|
|
|
<Icon {...props} name="arrow-down" size={16} type="font-awesome" color={colors.outgoingForegroundColor} />
|
2018-06-25 00:22:46 +02:00
|
|
|
</View>
|
|
|
|
</View>
|
2020-09-09 01:36:35 +02:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
};
|
2018-06-25 00:22:46 +02:00
|
|
|
|
2020-08-21 00:50:38 +02:00
|
|
|
const sendReceiveScanButtonFontSize =
|
|
|
|
PixelRatio.roundToNearestPixel(Dimensions.get('window').width / 26) > 22
|
|
|
|
? 22
|
|
|
|
: PixelRatio.roundToNearestPixel(Dimensions.get('window').width / 26);
|
2020-09-09 01:36:35 +02:00
|
|
|
export const BlueReceiveButtonIcon = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
|
|
|
|
return (
|
|
|
|
<TouchableOpacity {...props} style={{ flex: 1 }}>
|
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
flex: 1,
|
|
|
|
backgroundColor: colors.buttonBackgroundColor,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
|
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
left: 5,
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
transform: [{ rotate: '-45deg' }],
|
|
|
|
alignItems: 'center',
|
|
|
|
marginRight: 8,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<Icon
|
|
|
|
{...props}
|
|
|
|
name="arrow-down"
|
|
|
|
size={sendReceiveScanButtonFontSize}
|
|
|
|
type="font-awesome"
|
|
|
|
color={colors.buttonAlternativeTextColor}
|
|
|
|
/>
|
2018-06-25 00:22:46 +02:00
|
|
|
</View>
|
2020-09-09 01:36:35 +02:00
|
|
|
<Text
|
|
|
|
style={{
|
|
|
|
color: colors.buttonAlternativeTextColor,
|
|
|
|
fontWeight: '500',
|
|
|
|
fontSize: sendReceiveScanButtonFontSize,
|
|
|
|
left: 5,
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{loc.receive.header}
|
|
|
|
</Text>
|
2018-06-25 00:22:46 +02:00
|
|
|
</View>
|
2020-09-09 01:36:35 +02:00
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
};
|
2018-06-25 00:22:46 +02:00
|
|
|
|
2020-05-20 20:04:28 +02:00
|
|
|
export class BlueScanButton extends Component {
|
|
|
|
render() {
|
|
|
|
return (
|
2020-08-11 01:21:02 +02:00
|
|
|
<TouchableOpacity {...this.props} style={{ flex: 1 }}>
|
2020-05-20 20:04:28 +02:00
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
flex: 1,
|
|
|
|
minWidth: 130,
|
2020-07-15 19:32:59 +02:00
|
|
|
backgroundColor: BlueCurrentTheme.colors.buttonBackgroundColor,
|
2020-05-20 20:04:28 +02:00
|
|
|
}}
|
|
|
|
>
|
|
|
|
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
|
|
|
|
<View
|
|
|
|
style={{
|
2020-05-21 13:24:12 +02:00
|
|
|
minWidth: 24,
|
2020-05-20 20:04:28 +02:00
|
|
|
minHeight: 30,
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
alignItems: 'center',
|
|
|
|
marginBottom: -15,
|
2020-05-21 13:24:12 +02:00
|
|
|
marginLeft: -8,
|
2020-05-20 20:04:28 +02:00
|
|
|
}}
|
|
|
|
>
|
2020-08-11 01:21:02 +02:00
|
|
|
<Image resizeMode="stretch" source={BlueCurrentTheme.scanImage} />
|
2020-05-20 20:04:28 +02:00
|
|
|
</View>
|
|
|
|
<Text
|
|
|
|
style={{
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.buttonAlternativeTextColor,
|
2020-08-11 01:21:02 +02:00
|
|
|
fontSize: sendReceiveScanButtonFontSize,
|
2020-05-21 13:24:12 +02:00
|
|
|
fontWeight: '600',
|
2020-05-20 20:04:28 +02:00
|
|
|
left: 5,
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
}}
|
|
|
|
>
|
2020-07-20 15:38:46 +02:00
|
|
|
{loc.send.details_scan}
|
2020-05-20 20:04:28 +02:00
|
|
|
</Text>
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-25 00:22:46 +02:00
|
|
|
export class BlueSendButtonIcon extends Component {
|
|
|
|
render() {
|
|
|
|
return (
|
2020-08-25 13:38:02 +02:00
|
|
|
<TouchableOpacity {...this.props} testID="SendButton" style={{ flex: 1 }}>
|
2019-01-05 03:14:23 +01:00
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
flex: 1,
|
2020-07-15 19:32:59 +02:00
|
|
|
backgroundColor: BlueCurrentTheme.colors.buttonBackgroundColor,
|
2019-01-05 03:46:10 +01:00
|
|
|
alignItems: 'center',
|
2019-01-05 03:14:23 +01:00
|
|
|
}}
|
|
|
|
>
|
2019-01-05 03:46:10 +01:00
|
|
|
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }}>
|
2018-06-25 00:22:46 +02:00
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
left: 5,
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
transform: [{ rotate: '225deg' }],
|
2020-08-11 01:21:02 +02:00
|
|
|
marginRight: 8,
|
2018-06-25 00:22:46 +02:00
|
|
|
}}
|
|
|
|
>
|
2020-07-15 19:32:59 +02:00
|
|
|
<Icon
|
|
|
|
{...this.props}
|
|
|
|
name="arrow-down"
|
2020-08-11 01:21:02 +02:00
|
|
|
size={sendReceiveScanButtonFontSize}
|
2020-07-15 19:32:59 +02:00
|
|
|
type="font-awesome"
|
|
|
|
color={BlueCurrentTheme.colors.buttonAlternativeTextColor}
|
|
|
|
/>
|
2018-06-25 00:22:46 +02:00
|
|
|
</View>
|
|
|
|
<Text
|
|
|
|
style={{
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.buttonAlternativeTextColor,
|
2020-08-11 01:21:02 +02:00
|
|
|
fontSize: sendReceiveScanButtonFontSize,
|
2018-06-25 00:22:46 +02:00
|
|
|
fontWeight: '500',
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
}}
|
|
|
|
>
|
2019-01-05 03:14:23 +01:00
|
|
|
{loc.send.header}
|
2018-06-25 00:22:46 +02:00
|
|
|
</Text>
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-01 01:28:19 +02:00
|
|
|
export class ManageFundsBigButton extends Component {
|
|
|
|
render() {
|
|
|
|
return (
|
2018-10-02 05:40:23 +02:00
|
|
|
<TouchableOpacity {...this.props}>
|
2019-01-05 03:14:23 +01:00
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
flex: 1,
|
|
|
|
width: 168,
|
2020-07-15 19:32:59 +02:00
|
|
|
backgroundColor: BlueCurrentTheme.colors.buttonBackgroundColor,
|
2019-01-05 03:14:23 +01:00
|
|
|
}}
|
|
|
|
>
|
|
|
|
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
|
2018-09-01 01:28:19 +02:00
|
|
|
<View
|
|
|
|
style={{
|
2019-01-05 03:14:23 +01:00
|
|
|
minWidth: 30,
|
|
|
|
minHeight: 30,
|
|
|
|
right: 5,
|
2018-09-01 01:28:19 +02:00
|
|
|
backgroundColor: 'transparent',
|
|
|
|
transform: [{ rotate: '90deg' }],
|
|
|
|
}}
|
|
|
|
>
|
2020-07-15 19:32:59 +02:00
|
|
|
<Icon {...this.props} name="link" size={16} type="font-awesome" color={BlueCurrentTheme.colors.buttonAlternativeTextColor} />
|
2018-09-01 01:28:19 +02:00
|
|
|
</View>
|
|
|
|
<Text
|
|
|
|
style={{
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.buttonAlternativeTextColor,
|
2018-09-01 01:28:19 +02:00
|
|
|
fontSize: (isIpad && 10) || 16,
|
|
|
|
fontWeight: '500',
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
}}
|
|
|
|
>
|
2018-10-04 00:32:42 +02:00
|
|
|
{loc.lnd.title}
|
2018-09-01 01:28:19 +02:00
|
|
|
</Text>
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-09 01:36:35 +02:00
|
|
|
export const NewWalletPanel = props => {
|
|
|
|
const { colors } = useTheme();
|
|
|
|
return (
|
|
|
|
<TouchableOpacity testID="CreateAWallet" {...props} onPress={props.onPress} style={{ marginVertical: 17, paddingRight: 10 }}>
|
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
paddingHorizontal: 24,
|
|
|
|
paddingVertical: 16,
|
|
|
|
borderRadius: 10,
|
|
|
|
minHeight: Platform.OS === 'ios' ? 164 : 181,
|
|
|
|
justifyContent: 'center',
|
|
|
|
alignItems: 'flex-start',
|
|
|
|
backgroundColor: WalletGradient.createWallet,
|
|
|
|
}}
|
2020-09-08 18:06:41 +02:00
|
|
|
>
|
2020-09-09 01:36:35 +02:00
|
|
|
<Text
|
2018-06-25 00:22:46 +02:00
|
|
|
style={{
|
2020-09-09 01:36:35 +02:00
|
|
|
fontWeight: '600',
|
|
|
|
fontSize: 24,
|
|
|
|
color: colors.foregroundColor,
|
|
|
|
marginBottom: 4,
|
2018-06-25 00:22:46 +02:00
|
|
|
}}
|
|
|
|
>
|
2020-09-09 01:36:35 +02:00
|
|
|
{loc.wallets.list_create_a_wallet}
|
|
|
|
</Text>
|
|
|
|
<Text
|
|
|
|
style={{
|
|
|
|
fontSize: 13,
|
|
|
|
color: colors.alternativeTextColor,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{loc.wallets.list_create_a_wallet1}
|
|
|
|
</Text>
|
|
|
|
<Text
|
|
|
|
style={{
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
fontSize: 13,
|
|
|
|
color: colors.alternativeTextColor,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{loc.wallets.list_create_a_wallet2}
|
|
|
|
</Text>
|
|
|
|
<View style={{ marginTop: 12, backgroundColor: '#007AFF', paddingHorizontal: 32, paddingVertical: 12, borderRadius: 8 }}>
|
|
|
|
<Text style={{ color: colors.brandingColor, fontWeight: '500' }}>{loc.wallets.list_create_a_button}</Text>
|
2020-05-28 10:44:15 +02:00
|
|
|
</View>
|
2020-09-09 01:36:35 +02:00
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
|
|
|
};
|
2018-06-25 00:22:46 +02:00
|
|
|
|
2020-06-26 21:27:13 +02:00
|
|
|
export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = BitcoinUnit.BTC, timeElapsed }) => {
|
2019-12-28 17:22:43 +01:00
|
|
|
const [subtitleNumberOfLines, setSubtitleNumberOfLines] = useState(1);
|
2020-09-09 01:36:35 +02:00
|
|
|
const { colors } = useTheme();
|
2019-01-30 03:13:45 +01:00
|
|
|
|
2019-10-10 02:22:10 +02:00
|
|
|
const txMemo = () => {
|
2020-06-01 14:54:23 +02:00
|
|
|
if (BlueApp.tx_metadata[item.hash] && BlueApp.tx_metadata[item.hash].memo) {
|
|
|
|
return BlueApp.tx_metadata[item.hash].memo;
|
2019-01-30 03:13:45 +01:00
|
|
|
}
|
|
|
|
return '';
|
|
|
|
};
|
|
|
|
|
2019-10-10 02:22:10 +02:00
|
|
|
const rowTitle = () => {
|
2019-01-30 03:13:45 +01:00
|
|
|
if (item.type === 'user_invoice' || item.type === 'payment_request') {
|
|
|
|
if (isNaN(item.value)) {
|
|
|
|
item.value = '0';
|
|
|
|
}
|
|
|
|
const currentDate = new Date();
|
|
|
|
const now = (currentDate.getTime() / 1000) | 0;
|
|
|
|
const invoiceExpiration = item.timestamp + item.expire_time;
|
|
|
|
|
|
|
|
if (invoiceExpiration > now) {
|
2020-07-20 15:38:46 +02:00
|
|
|
return formatBalanceWithoutSuffix(item.value && item.value, itemPriceUnit, true).toString();
|
2019-01-30 03:13:45 +01:00
|
|
|
} else if (invoiceExpiration < now) {
|
|
|
|
if (item.ispaid) {
|
2020-07-20 15:38:46 +02:00
|
|
|
return formatBalanceWithoutSuffix(item.value && item.value, itemPriceUnit, true).toString();
|
2019-01-30 03:13:45 +01:00
|
|
|
} else {
|
|
|
|
return loc.lnd.expired;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2020-07-20 15:38:46 +02:00
|
|
|
return formatBalanceWithoutSuffix(item.value && item.value, itemPriceUnit, true).toString();
|
2019-01-30 03:13:45 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-10-10 02:22:10 +02:00
|
|
|
const rowTitleStyle = () => {
|
2020-09-09 01:36:35 +02:00
|
|
|
let color = colors.successColor;
|
2019-01-30 03:13:45 +01:00
|
|
|
|
|
|
|
if (item.type === 'user_invoice' || item.type === 'payment_request') {
|
|
|
|
const currentDate = new Date();
|
|
|
|
const now = (currentDate.getTime() / 1000) | 0;
|
|
|
|
const invoiceExpiration = item.timestamp + item.expire_time;
|
|
|
|
|
|
|
|
if (invoiceExpiration > now) {
|
2020-09-09 01:36:35 +02:00
|
|
|
color = colors.successColor;
|
2019-01-30 03:13:45 +01:00
|
|
|
} else if (invoiceExpiration < now) {
|
|
|
|
if (item.ispaid) {
|
2020-09-09 01:36:35 +02:00
|
|
|
color = colors.successColor;
|
2019-01-30 03:13:45 +01:00
|
|
|
} else {
|
2020-03-29 17:33:37 +02:00
|
|
|
color = '#9AA0AA';
|
2019-01-30 03:13:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (item.value / 100000000 < 0) {
|
2020-09-09 01:36:35 +02:00
|
|
|
color = colors.foregroundColor;
|
2019-01-30 03:13:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
fontWeight: '600',
|
2020-05-14 20:44:23 +02:00
|
|
|
fontSize: 14,
|
2019-01-30 03:13:45 +01:00
|
|
|
color: color,
|
2020-05-14 20:44:23 +02:00
|
|
|
textAlign: 'right',
|
|
|
|
width: 96,
|
2019-01-30 03:13:45 +01:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2019-10-10 02:22:10 +02:00
|
|
|
const avatar = () => {
|
2019-01-30 03:13:45 +01:00
|
|
|
// is it lightning refill tx?
|
2019-10-10 02:22:10 +02:00
|
|
|
if (item.category === 'receive' && item.confirmations < 3) {
|
2019-01-30 03:13:45 +01:00
|
|
|
return (
|
|
|
|
<View style={{ width: 25 }}>
|
|
|
|
<BlueTransactionPendingIcon />
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-10-10 02:22:10 +02:00
|
|
|
if (item.type && item.type === 'bitcoind_tx') {
|
2019-01-30 03:13:45 +01:00
|
|
|
return (
|
|
|
|
<View style={{ width: 25 }}>
|
|
|
|
<BlueTransactionOnchainIcon />
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
}
|
2019-10-10 02:22:10 +02:00
|
|
|
if (item.type === 'paid_invoice') {
|
2019-01-30 03:13:45 +01:00
|
|
|
// is it lightning offchain payment?
|
|
|
|
return (
|
|
|
|
<View style={{ width: 25 }}>
|
|
|
|
<BlueTransactionOffchainIcon />
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-10-10 02:22:10 +02:00
|
|
|
if (item.type === 'user_invoice' || item.type === 'payment_request') {
|
|
|
|
if (!item.ispaid) {
|
2019-01-30 03:13:45 +01:00
|
|
|
const currentDate = new Date();
|
|
|
|
const now = (currentDate.getTime() / 1000) | 0;
|
2019-10-10 02:22:10 +02:00
|
|
|
const invoiceExpiration = item.timestamp + item.expire_time;
|
2019-01-30 03:13:45 +01:00
|
|
|
if (invoiceExpiration < now) {
|
|
|
|
return (
|
|
|
|
<View style={{ width: 25 }}>
|
|
|
|
<BlueTransactionExpiredIcon />
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return (
|
|
|
|
<View style={{ width: 25 }}>
|
|
|
|
<BlueTransactionOffchainIncomingIcon />
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-10 02:22:10 +02:00
|
|
|
if (!item.confirmations) {
|
2019-01-30 03:13:45 +01:00
|
|
|
return (
|
|
|
|
<View style={{ width: 25 }}>
|
|
|
|
<BlueTransactionPendingIcon />
|
|
|
|
</View>
|
|
|
|
);
|
2019-10-10 02:22:10 +02:00
|
|
|
} else if (item.value < 0) {
|
2019-01-30 03:13:45 +01:00
|
|
|
return (
|
|
|
|
<View style={{ width: 25 }}>
|
|
|
|
<BlueTransactionOutgoingIcon />
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return (
|
|
|
|
<View style={{ width: 25 }}>
|
2019-01-31 07:52:21 +01:00
|
|
|
<BlueTransactionIncomingIcon />
|
2019-01-30 03:13:45 +01:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-10-10 02:22:10 +02:00
|
|
|
const subtitle = () => {
|
2020-07-20 15:38:46 +02:00
|
|
|
return (item.confirmations < 7 ? loc.transactions.list_conf + ': ' + item.confirmations + ' ' : '') + txMemo() + (item.memo || '');
|
2019-01-30 03:13:45 +01:00
|
|
|
};
|
|
|
|
|
2020-07-23 20:06:13 +02:00
|
|
|
const onPress = async () => {
|
2019-10-10 02:22:10 +02:00
|
|
|
if (item.hash) {
|
|
|
|
NavigationService.navigate('TransactionStatus', { hash: item.hash });
|
|
|
|
} else if (item.type === 'user_invoice' || item.type === 'payment_request' || item.type === 'paid_invoice') {
|
2019-01-30 22:53:29 +01:00
|
|
|
const lightningWallet = BlueApp.getWallets().filter(wallet => {
|
2019-01-30 03:13:45 +01:00
|
|
|
if (typeof wallet === 'object') {
|
2020-06-01 14:54:23 +02:00
|
|
|
if ('secret' in wallet) {
|
2019-10-10 02:22:10 +02:00
|
|
|
return wallet.getSecret() === item.fromWallet;
|
2019-01-30 03:13:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2019-01-31 01:56:34 +01:00
|
|
|
if (lightningWallet.length === 1) {
|
2020-07-23 20:06:13 +02:00
|
|
|
// is it a successful lnurl-pay?
|
|
|
|
const LN = new Lnurl(false, AsyncStorage);
|
|
|
|
let paymentHash = item.payment_hash;
|
|
|
|
if (typeof paymentHash === 'object') {
|
|
|
|
paymentHash = Buffer.from(paymentHash.data).toString('hex');
|
|
|
|
}
|
|
|
|
const loaded = await LN.loadSuccessfulPayment(paymentHash);
|
|
|
|
if (loaded) {
|
|
|
|
NavigationService.navigate('ScanLndInvoiceRoot', {
|
|
|
|
screen: 'LnurlPaySuccess',
|
|
|
|
params: {
|
|
|
|
paymentHash: paymentHash,
|
|
|
|
justPaid: false,
|
|
|
|
fromWalletID: lightningWallet[0].getID(),
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-01-31 01:56:34 +01:00
|
|
|
NavigationService.navigate('LNDViewInvoice', {
|
2019-10-10 02:22:10 +02:00
|
|
|
invoice: item,
|
2019-01-31 01:56:34 +01:00
|
|
|
fromWallet: lightningWallet[0],
|
|
|
|
isModal: false,
|
|
|
|
});
|
|
|
|
}
|
2019-01-30 03:13:45 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-10-10 02:22:10 +02:00
|
|
|
const onLongPress = () => {
|
|
|
|
if (subtitleNumberOfLines === 1) {
|
|
|
|
setSubtitleNumberOfLines(0);
|
2019-09-19 04:57:03 +02:00
|
|
|
}
|
|
|
|
};
|
2019-08-31 08:54:11 +02:00
|
|
|
|
2019-10-10 02:22:10 +02:00
|
|
|
return (
|
2020-06-26 21:27:13 +02:00
|
|
|
<View style={{ marginHorizontal: 4 }}>
|
|
|
|
<BlueListItem
|
|
|
|
leftAvatar={avatar()}
|
2020-07-20 15:38:46 +02:00
|
|
|
title={transactionTimeToReadable(item.received)}
|
2020-06-26 21:27:13 +02:00
|
|
|
titleNumberOfLines={subtitleNumberOfLines}
|
|
|
|
subtitle={subtitle()}
|
|
|
|
subtitleProps={{ numberOfLines: subtitleNumberOfLines }}
|
|
|
|
onPress={onPress}
|
|
|
|
onLongPress={onLongPress}
|
|
|
|
chevron={false}
|
|
|
|
Component={TouchableOpacity}
|
|
|
|
rightTitle={rowTitle()}
|
|
|
|
rightTitleStyle={rowTitleStyle()}
|
|
|
|
/>
|
|
|
|
</View>
|
2019-10-10 02:22:10 +02:00
|
|
|
);
|
2020-06-19 18:31:59 +02:00
|
|
|
});
|
2019-01-30 03:13:45 +01:00
|
|
|
|
2020-09-08 18:06:41 +02:00
|
|
|
const WalletCarouselItem = ({ item, index, onPress, handleLongPress, isSelectedWallet }) => {
|
2020-06-01 14:54:23 +02:00
|
|
|
const scaleValue = new Animated.Value(1.0);
|
2018-06-25 00:22:46 +02:00
|
|
|
|
2020-05-28 10:44:15 +02:00
|
|
|
const onPressedIn = () => {
|
2020-06-01 14:54:23 +02:00
|
|
|
const props = { duration: 50 };
|
2020-06-18 17:49:36 +02:00
|
|
|
props.useNativeDriver = true;
|
2019-12-14 09:02:40 +01:00
|
|
|
|
2020-05-28 10:44:15 +02:00
|
|
|
props.toValue = 0.9;
|
|
|
|
Animated.spring(scaleValue, props).start();
|
|
|
|
};
|
|
|
|
const onPressedOut = () => {
|
2020-06-01 14:54:23 +02:00
|
|
|
const props = { duration: 50 };
|
2020-06-18 17:49:36 +02:00
|
|
|
|
|
|
|
props.useNativeDriver = true;
|
2018-12-12 04:33:28 +01:00
|
|
|
|
2020-05-28 10:44:15 +02:00
|
|
|
props.toValue = 1.0;
|
|
|
|
Animated.spring(scaleValue, props).start();
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!item) {
|
|
|
|
return (
|
|
|
|
<NewWalletPanel
|
|
|
|
onPress={() => {
|
2020-06-09 16:08:18 +02:00
|
|
|
onPressedOut();
|
2020-05-28 10:44:15 +02:00
|
|
|
onPress(index);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item.type === PlaceholderWallet.type) {
|
|
|
|
return (
|
|
|
|
<Animated.View
|
|
|
|
style={{ paddingRight: 10, marginVertical: 17, transform: [{ scale: scaleValue }] }}
|
|
|
|
shadowOpacity={40 / 100}
|
|
|
|
shadowOffset={{ width: 0, height: 0 }}
|
|
|
|
shadowRadius={5}
|
|
|
|
>
|
|
|
|
<TouchableWithoutFeedback
|
|
|
|
onPressIn={item.getIsFailure() ? onPressedIn : null}
|
|
|
|
onPressOut={item.getIsFailure() ? onPressedOut : null}
|
2018-06-25 00:22:46 +02:00
|
|
|
onPress={() => {
|
2020-05-28 10:44:15 +02:00
|
|
|
if (item.getIsFailure()) {
|
2020-06-09 16:08:18 +02:00
|
|
|
onPressedOut();
|
2020-05-28 10:44:15 +02:00
|
|
|
onPress(index);
|
2020-06-09 16:08:18 +02:00
|
|
|
onPressedOut();
|
2020-05-28 10:44:15 +02:00
|
|
|
}
|
2018-06-25 00:22:46 +02:00
|
|
|
}}
|
2018-09-29 00:17:26 +02:00
|
|
|
>
|
2020-05-28 10:44:15 +02:00
|
|
|
<LinearGradient
|
2020-07-15 19:32:59 +02:00
|
|
|
shadowColor={BlueCurrentTheme.colors.shadowColor}
|
2020-05-28 10:44:15 +02:00
|
|
|
colors={WalletGradient.gradientsFor(item.type)}
|
|
|
|
style={{
|
|
|
|
padding: 15,
|
|
|
|
borderRadius: 10,
|
|
|
|
minHeight: 164,
|
|
|
|
elevation: 5,
|
2018-11-10 00:44:34 +01:00
|
|
|
}}
|
2018-06-25 00:22:46 +02:00
|
|
|
>
|
2020-05-28 10:44:15 +02:00
|
|
|
<Image
|
|
|
|
source={require('./img/btc-shape.png')}
|
2018-11-02 14:53:35 +01:00
|
|
|
style={{
|
2020-05-28 10:44:15 +02:00
|
|
|
width: 99,
|
|
|
|
height: 94,
|
|
|
|
position: 'absolute',
|
|
|
|
bottom: 0,
|
|
|
|
right: 0,
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
<Text style={{ backgroundColor: 'transparent' }} />
|
|
|
|
<Text
|
|
|
|
numberOfLines={1}
|
|
|
|
style={{
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
fontSize: 19,
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.inverseForegroundColor,
|
2018-11-02 14:53:35 +01:00
|
|
|
}}
|
|
|
|
>
|
2020-05-28 10:44:15 +02:00
|
|
|
{item.getLabel()}
|
|
|
|
</Text>
|
|
|
|
{item.getIsFailure() ? (
|
2019-08-03 23:29:15 +02:00
|
|
|
<Text
|
2020-05-28 10:44:15 +02:00
|
|
|
numberOfLines={0}
|
2019-08-03 23:29:15 +02:00
|
|
|
style={{
|
|
|
|
backgroundColor: 'transparent',
|
2019-12-27 03:21:07 +01:00
|
|
|
fontSize: 19,
|
2020-05-28 10:44:15 +02:00
|
|
|
marginTop: 40,
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.inverseForegroundColor,
|
2019-08-03 23:29:15 +02:00
|
|
|
}}
|
|
|
|
>
|
2020-07-23 15:09:48 +02:00
|
|
|
{loc.wallets.list_import_error}
|
2019-08-03 23:29:15 +02:00
|
|
|
</Text>
|
2020-05-28 10:44:15 +02:00
|
|
|
) : (
|
|
|
|
<ActivityIndicator style={{ marginTop: 40 }} />
|
|
|
|
)}
|
|
|
|
</LinearGradient>
|
|
|
|
</TouchableWithoutFeedback>
|
|
|
|
</Animated.View>
|
|
|
|
);
|
|
|
|
} else {
|
2020-09-08 18:06:41 +02:00
|
|
|
let opacity = 1.0;
|
|
|
|
|
|
|
|
if (isSelectedWallet === false) {
|
|
|
|
opacity = 0.5;
|
|
|
|
}
|
2020-05-28 10:44:15 +02:00
|
|
|
return (
|
|
|
|
<Animated.View
|
2020-09-08 18:06:41 +02:00
|
|
|
style={{ paddingRight: 10, marginVertical: 17, transform: [{ scale: scaleValue }], opacity }}
|
2020-05-28 10:44:15 +02:00
|
|
|
shadowOpacity={40 / 100}
|
|
|
|
shadowOffset={{ width: 0, height: 0 }}
|
|
|
|
shadowRadius={5}
|
|
|
|
>
|
|
|
|
<TouchableWithoutFeedback
|
|
|
|
testID={item.getLabel()}
|
|
|
|
onPressIn={onPressedIn}
|
|
|
|
onPressOut={onPressedOut}
|
|
|
|
onLongPress={handleLongPress}
|
|
|
|
onPress={() => {
|
2020-06-09 16:08:18 +02:00
|
|
|
onPressedOut();
|
2020-05-28 10:44:15 +02:00
|
|
|
onPress(index);
|
2020-06-09 16:08:18 +02:00
|
|
|
onPressedOut();
|
2020-05-28 10:44:15 +02:00
|
|
|
}}
|
2019-12-27 03:21:07 +01:00
|
|
|
>
|
2020-05-28 10:44:15 +02:00
|
|
|
<LinearGradient
|
2020-07-15 19:32:59 +02:00
|
|
|
shadowColor={BlueCurrentTheme.colors.shadowColor}
|
2020-05-28 10:44:15 +02:00
|
|
|
colors={WalletGradient.gradientsFor(item.type)}
|
|
|
|
style={{
|
|
|
|
padding: 15,
|
|
|
|
borderRadius: 10,
|
|
|
|
minHeight: 164,
|
|
|
|
elevation: 5,
|
2019-12-27 03:21:07 +01:00
|
|
|
}}
|
|
|
|
>
|
2020-05-28 10:44:15 +02:00
|
|
|
<Image
|
|
|
|
source={(LightningCustodianWallet.type === item.type && require('./img/lnd-shape.png')) || require('./img/btc-shape.png')}
|
2018-11-02 14:53:35 +01:00
|
|
|
style={{
|
2020-05-28 10:44:15 +02:00
|
|
|
width: 99,
|
|
|
|
height: 94,
|
|
|
|
position: 'absolute',
|
|
|
|
bottom: 0,
|
|
|
|
right: 0,
|
2018-11-02 14:53:35 +01:00
|
|
|
}}
|
2020-05-28 10:44:15 +02:00
|
|
|
/>
|
2019-12-27 03:21:07 +01:00
|
|
|
|
2020-05-28 10:44:15 +02:00
|
|
|
<Text style={{ backgroundColor: 'transparent' }} />
|
|
|
|
<Text
|
|
|
|
numberOfLines={1}
|
|
|
|
style={{
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
fontSize: 19,
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.inverseForegroundColor,
|
2020-05-28 10:44:15 +02:00
|
|
|
}}
|
|
|
|
>
|
|
|
|
{item.getLabel()}
|
|
|
|
</Text>
|
|
|
|
{item.hideBalance ? (
|
|
|
|
<BluePrivateBalance />
|
|
|
|
) : (
|
2019-12-27 03:21:07 +01:00
|
|
|
<Text
|
|
|
|
numberOfLines={1}
|
2020-05-28 10:44:15 +02:00
|
|
|
adjustsFontSizeToFit
|
2019-12-27 03:21:07 +01:00
|
|
|
style={{
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
fontWeight: 'bold',
|
2020-05-28 10:44:15 +02:00
|
|
|
fontSize: 36,
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.inverseForegroundColor,
|
2019-12-27 03:21:07 +01:00
|
|
|
}}
|
|
|
|
>
|
2020-07-20 15:38:46 +02:00
|
|
|
{formatBalance(Number(item.getBalance()), item.getPreferredBalanceUnit(), true)}
|
2019-12-27 03:21:07 +01:00
|
|
|
</Text>
|
2020-05-28 10:44:15 +02:00
|
|
|
)}
|
|
|
|
<Text style={{ backgroundColor: 'transparent' }} />
|
|
|
|
<Text
|
|
|
|
numberOfLines={1}
|
|
|
|
style={{
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
fontSize: 13,
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.inverseForegroundColor,
|
2020-05-28 10:44:15 +02:00
|
|
|
}}
|
|
|
|
>
|
2020-07-20 15:38:46 +02:00
|
|
|
{loc.wallets.list_latest_transaction}
|
2020-05-28 10:44:15 +02:00
|
|
|
</Text>
|
|
|
|
<Text
|
|
|
|
numberOfLines={1}
|
|
|
|
style={{
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
fontWeight: 'bold',
|
|
|
|
fontSize: 16,
|
2020-07-15 19:32:59 +02:00
|
|
|
color: BlueCurrentTheme.colors.inverseForegroundColor,
|
2020-05-28 10:44:15 +02:00
|
|
|
}}
|
|
|
|
>
|
2020-07-20 15:38:46 +02:00
|
|
|
{transactionTimeToReadable(item.getLatestTransactionTime())}
|
2020-05-28 10:44:15 +02:00
|
|
|
</Text>
|
|
|
|
</LinearGradient>
|
|
|
|
</TouchableWithoutFeedback>
|
|
|
|
</Animated.View>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const sliderWidth = width * 1;
|
|
|
|
const itemWidth = width * 0.82 > 375 ? 375 : width * 0.82;
|
|
|
|
const sliderHeight = 190;
|
|
|
|
|
|
|
|
export class WalletsCarousel extends Component {
|
|
|
|
walletsCarousel = React.createRef();
|
|
|
|
|
|
|
|
state = { isLoading: true };
|
|
|
|
|
|
|
|
_renderItem = ({ item, index }) => {
|
2020-09-08 18:06:41 +02:00
|
|
|
return (
|
|
|
|
<WalletCarouselItem
|
|
|
|
isSelectedWallet={this.props.vertical && this.props.selectedWallet && item ? this.props.selectedWallet === item.getID() : undefined}
|
|
|
|
item={item}
|
|
|
|
index={index}
|
|
|
|
handleLongPress={this.props.handleLongPress}
|
|
|
|
onPress={this.props.onPress}
|
|
|
|
/>
|
|
|
|
);
|
2020-05-17 03:41:38 +02:00
|
|
|
};
|
2018-06-25 00:22:46 +02:00
|
|
|
|
2019-12-14 09:02:40 +01:00
|
|
|
snapToItem = item => {
|
|
|
|
this.walletsCarousel.current.snapToItem(item);
|
|
|
|
};
|
|
|
|
|
2020-05-28 10:44:15 +02:00
|
|
|
onLayout = () => {
|
|
|
|
this.setState({ isLoading: false });
|
|
|
|
};
|
|
|
|
|
2018-06-25 00:22:46 +02:00
|
|
|
render() {
|
|
|
|
return (
|
2020-05-28 10:44:15 +02:00
|
|
|
<>
|
|
|
|
{this.state.isLoading && (
|
|
|
|
<View
|
|
|
|
style={{ paddingVertical: sliderHeight / 2, paddingHorizontal: sliderWidth / 2, position: 'absolute', alignItems: 'center' }}
|
|
|
|
>
|
|
|
|
<ActivityIndicator />
|
|
|
|
</View>
|
|
|
|
)}
|
|
|
|
<Carousel
|
|
|
|
ref={this.walletsCarousel}
|
|
|
|
renderItem={this._renderItem}
|
|
|
|
sliderWidth={sliderWidth}
|
|
|
|
sliderHeight={sliderHeight}
|
|
|
|
itemWidth={itemWidth}
|
|
|
|
inactiveSlideScale={1}
|
|
|
|
inactiveSlideOpacity={0.7}
|
2020-08-16 19:51:36 +02:00
|
|
|
activeSlideAlignment="start"
|
2020-09-08 18:06:41 +02:00
|
|
|
initialNumToRender={10}
|
2020-05-28 10:44:15 +02:00
|
|
|
onLayout={this.onLayout}
|
2020-08-16 19:51:36 +02:00
|
|
|
contentContainerCustomStyle={{ left: 20 }}
|
2020-09-08 18:06:41 +02:00
|
|
|
{...this.props}
|
2020-05-28 10:44:15 +02:00
|
|
|
/>
|
|
|
|
</>
|
2018-03-17 21:39:21 +01:00
|
|
|
);
|
2018-01-30 23:42:38 +01:00
|
|
|
}
|
|
|
|
}
|
2020-08-11 02:11:11 +02:00
|
|
|
const isDesktop = getSystemName() === 'Mac OS X';
|
2019-01-24 08:36:01 +01:00
|
|
|
export class BlueAddressInput extends Component {
|
|
|
|
static propTypes = {
|
|
|
|
isLoading: PropTypes.bool,
|
|
|
|
onChangeText: PropTypes.func,
|
2019-12-28 01:53:34 +01:00
|
|
|
onBarScanned: PropTypes.func.isRequired,
|
|
|
|
launchedBy: PropTypes.string.isRequired,
|
2019-01-24 08:36:01 +01:00
|
|
|
address: PropTypes.string,
|
2019-02-17 08:50:23 +01:00
|
|
|
placeholder: PropTypes.string,
|
2019-01-24 08:36:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static defaultProps = {
|
|
|
|
isLoading: false,
|
|
|
|
address: '',
|
2020-07-20 15:38:46 +02:00
|
|
|
placeholder: loc.send.details_address,
|
2019-01-24 08:36:01 +01:00
|
|
|
};
|
|
|
|
|
2020-08-11 02:11:11 +02:00
|
|
|
choosePhoto = () => {
|
|
|
|
ImagePicker.launchImageLibrary(
|
|
|
|
{
|
|
|
|
title: null,
|
|
|
|
mediaType: 'photo',
|
|
|
|
takePhotoButtonTitle: null,
|
|
|
|
},
|
|
|
|
response => {
|
|
|
|
if (response.uri) {
|
|
|
|
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
|
|
|
LocalQRCode.decode(uri, (error, result) => {
|
|
|
|
if (!error) {
|
|
|
|
this.props.onBarScanned(result);
|
|
|
|
} else {
|
|
|
|
alert(loc.send.qr_error_no_qrcode);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
takePhoto = () => {
|
|
|
|
ImagePicker.launchCamera(
|
|
|
|
{
|
|
|
|
title: null,
|
|
|
|
mediaType: 'photo',
|
|
|
|
takePhotoButtonTitle: null,
|
|
|
|
},
|
|
|
|
response => {
|
|
|
|
if (response.uri) {
|
|
|
|
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
|
|
|
LocalQRCode.decode(uri, (error, result) => {
|
|
|
|
if (!error) {
|
|
|
|
this.props.onBarScanned(result);
|
|
|
|
} else {
|
|
|
|
alert(loc.send.qr_error_no_qrcode);
|
|
|
|
}
|
|
|
|
});
|
2020-09-06 08:35:04 +02:00
|
|
|
} else if (response.error) {
|
|
|
|
ScanQRCode.presentCameraNotAuthorizedAlert(response.error);
|
2020-08-11 02:11:11 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
copyFromClipbard = async () => {
|
|
|
|
this.props.onBarScanned(await Clipboard.getString());
|
|
|
|
};
|
|
|
|
|
|
|
|
showActionSheet = async () => {
|
2020-09-06 08:35:04 +02:00
|
|
|
const isClipboardEmpty = (await Clipboard.getString()).trim().length === 0;
|
2020-08-11 02:11:11 +02:00
|
|
|
let copyFromClipboardIndex;
|
|
|
|
if (Platform.OS === 'ios') {
|
|
|
|
const options = [loc._.cancel, loc.wallets.list_long_choose, isDesktop ? loc.wallets.take_photo : loc.wallets.list_long_scan];
|
|
|
|
if (!isClipboardEmpty) {
|
|
|
|
options.push(loc.wallets.list_long_clipboard);
|
|
|
|
copyFromClipboardIndex = options.length - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ActionSheet.showActionSheetWithOptions({ options, cancelButtonIndex: 0 }, buttonIndex => {
|
|
|
|
if (buttonIndex === 1) {
|
|
|
|
this.choosePhoto();
|
|
|
|
} else if (buttonIndex === 2) {
|
|
|
|
this.takePhoto();
|
|
|
|
} else if (buttonIndex === copyFromClipboardIndex) {
|
|
|
|
this.copyFromClipbard();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-01-24 08:36:01 +01:00
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
flexDirection: 'row',
|
2020-07-15 19:32:59 +02:00
|
|
|
borderColor: BlueCurrentTheme.colors.formBorder,
|
|
|
|
borderBottomColor: BlueCurrentTheme.colors.formBorder,
|
2019-01-24 08:36:01 +01:00
|
|
|
borderWidth: 1.0,
|
|
|
|
borderBottomWidth: 0.5,
|
2020-07-15 19:32:59 +02:00
|
|
|
backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
|
2019-01-24 08:36:01 +01:00
|
|
|
minHeight: 44,
|
|
|
|
height: 44,
|
|
|
|
marginHorizontal: 20,
|
|
|
|
alignItems: 'center',
|
|
|
|
marginVertical: 8,
|
|
|
|
borderRadius: 4,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<TextInput
|
2020-06-01 14:54:23 +02:00
|
|
|
testID="AddressInput"
|
2019-01-24 08:36:01 +01:00
|
|
|
onChangeText={text => {
|
|
|
|
this.props.onChangeText(text);
|
|
|
|
}}
|
2019-02-17 08:50:23 +01:00
|
|
|
placeholder={this.props.placeholder}
|
2019-01-24 08:36:01 +01:00
|
|
|
numberOfLines={1}
|
2020-06-09 14:23:21 +02:00
|
|
|
placeholderTextColor="#81868e"
|
2019-01-24 08:36:01 +01:00
|
|
|
value={this.props.address}
|
2020-06-09 14:23:21 +02:00
|
|
|
style={{ flex: 1, marginHorizontal: 8, minHeight: 33, color: '#81868e' }}
|
2019-01-24 08:36:01 +01:00
|
|
|
editable={!this.props.isLoading}
|
2020-01-20 04:33:17 +01:00
|
|
|
onSubmitEditing={Keyboard.dismiss}
|
2019-02-17 10:23:12 +01:00
|
|
|
{...this.props}
|
2019-01-24 08:36:01 +01:00
|
|
|
/>
|
|
|
|
<TouchableOpacity
|
|
|
|
disabled={this.props.isLoading}
|
2019-01-26 06:27:25 +01:00
|
|
|
onPress={() => {
|
2019-02-10 12:39:26 +01:00
|
|
|
Keyboard.dismiss();
|
2020-08-11 02:11:11 +02:00
|
|
|
if (isDesktop) {
|
|
|
|
this.showActionSheet();
|
|
|
|
} else {
|
|
|
|
NavigationService.navigate('ScanQRCodeRoot', {
|
|
|
|
screen: 'ScanQRCode',
|
|
|
|
params: {
|
|
|
|
launchedBy: this.props.launchedBy,
|
|
|
|
onBarScanned: this.props.onBarScanned,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
2019-01-26 06:27:25 +01:00
|
|
|
}}
|
2019-01-24 08:36:01 +01:00
|
|
|
style={{
|
|
|
|
height: 36,
|
|
|
|
flexDirection: 'row',
|
|
|
|
alignItems: 'center',
|
|
|
|
justifyContent: 'space-between',
|
2020-07-15 19:32:59 +02:00
|
|
|
backgroundColor: BlueCurrentTheme.colors.scanLabel,
|
2019-01-24 08:36:01 +01:00
|
|
|
borderRadius: 4,
|
|
|
|
paddingVertical: 4,
|
|
|
|
paddingHorizontal: 8,
|
|
|
|
marginHorizontal: 4,
|
|
|
|
}}
|
|
|
|
>
|
2020-07-15 19:32:59 +02:00
|
|
|
<Image style={{}} source={require('./img/scan-white.png')} />
|
2020-07-20 15:38:46 +02:00
|
|
|
<Text style={{ marginLeft: 4, color: BlueCurrentTheme.colors.inverseForegroundColor }}>{loc.send.details_scan}</Text>
|
2019-01-24 08:36:01 +01:00
|
|
|
</TouchableOpacity>
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-27 06:05:27 +02:00
|
|
|
export class BlueReplaceFeeSuggestions extends Component {
|
|
|
|
static propTypes = {
|
|
|
|
onFeeSelected: PropTypes.func.isRequired,
|
|
|
|
transactionMinimum: PropTypes.number.isRequired,
|
|
|
|
};
|
|
|
|
|
|
|
|
static defaultProps = {
|
|
|
|
transactionMinimum: 1,
|
|
|
|
};
|
|
|
|
|
2020-09-14 12:49:08 +02:00
|
|
|
state = {
|
|
|
|
customFeeValue: '1',
|
|
|
|
};
|
2019-08-27 06:05:27 +02:00
|
|
|
|
|
|
|
async componentDidMount() {
|
2020-09-14 12:49:08 +02:00
|
|
|
try {
|
|
|
|
const cachedNetworkTransactionFees = JSON.parse(await AsyncStorage.getItem(NetworkTransactionFee.StorageKey));
|
|
|
|
|
|
|
|
if (cachedNetworkTransactionFees && 'fastestFee' in cachedNetworkTransactionFees) {
|
2020-09-15 15:17:01 +02:00
|
|
|
this.setState({ networkFees: cachedNetworkTransactionFees }, () => this.onFeeSelected(NetworkTransactionFeeType.FAST));
|
2020-09-14 12:49:08 +02:00
|
|
|
}
|
|
|
|
} catch (_) {}
|
2019-08-27 06:05:27 +02:00
|
|
|
const networkFees = await NetworkTransactionFees.recommendedFees();
|
2020-09-15 15:17:01 +02:00
|
|
|
this.setState({ networkFees }, () => this.onFeeSelected(NetworkTransactionFeeType.FAST));
|
2019-08-27 06:05:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2020-05-18 16:45:31 +02:00
|
|
|
this.setState({ selectedFeeType }, () => this.props.onFeeSelected(this.state.networkFees.mediumFee));
|
2019-08-27 06:05:27 +02:00
|
|
|
} else if (selectedFeeType === NetworkTransactionFeeType.SLOW) {
|
2020-05-18 16:45:31 +02:00
|
|
|
this.setState({ selectedFeeType }, () => this.props.onFeeSelected(this.state.networkFees.slowFee));
|
2019-08-27 06:05:27 +02:00
|
|
|
} else if (selectedFeeType === NetworkTransactionFeeType.CUSTOM) {
|
2020-09-14 12:49:08 +02:00
|
|
|
this.props.onFeeSelected(Number(this.state.customFeeValue));
|
2019-08-27 06:05:27 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
onCustomFeeTextChange = customFee => {
|
2020-09-14 12:49:08 +02:00
|
|
|
const customFeeValue = customFee.replace(/[^0-9]/g, '');
|
|
|
|
this.setState({ customFeeValue, selectedFeeType: NetworkTransactionFeeType.CUSTOM }, () => {
|
2019-08-27 06:05:27 +02:00
|
|
|
this.onFeeSelected(NetworkTransactionFeeType.CUSTOM);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
render() {
|
2020-09-14 12:49:08 +02:00
|
|
|
const { networkFees, selectedFeeType } = this.state;
|
|
|
|
|
2019-08-27 06:05:27 +02:00
|
|
|
return (
|
2020-05-15 11:26:37 +02:00
|
|
|
<View>
|
2020-09-14 12:49:08 +02:00
|
|
|
{networkFees &&
|
|
|
|
[
|
|
|
|
{
|
|
|
|
label: loc.send.fee_fast,
|
|
|
|
time: loc.send.fee_10m,
|
|
|
|
type: NetworkTransactionFeeType.FAST,
|
|
|
|
rate: networkFees.fastestFee,
|
|
|
|
active: selectedFeeType === NetworkTransactionFeeType.FAST,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 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) => (
|
|
|
|
<TouchableOpacity
|
|
|
|
key={label}
|
|
|
|
onPress={() => this.onFeeSelected(type)}
|
|
|
|
style={[
|
|
|
|
{ paddingHorizontal: 16, paddingVertical: 8, marginBottom: 10 },
|
|
|
|
active && { borderRadius: 8, backgroundColor: BlueCurrentTheme.colors.incomingBackgroundColor },
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
<View style={{ justifyContent: 'space-between', flexDirection: 'row', alignItems: 'center' }}>
|
|
|
|
<Text style={{ fontSize: 22, color: BlueCurrentTheme.colors.successColor, fontWeight: '600' }}>{label}</Text>
|
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
backgroundColor: BlueCurrentTheme.colors.successColor,
|
|
|
|
borderRadius: 5,
|
|
|
|
paddingHorizontal: 6,
|
|
|
|
paddingVertical: 3,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<Text style={{ color: BlueCurrentTheme.colors.background }}>~{time}</Text>
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
<View style={{ justifyContent: 'flex-end', flexDirection: 'row', alignItems: 'center' }}>
|
|
|
|
<Text style={{ color: BlueCurrentTheme.colors.successColor }}>{rate} sat/byte</Text>
|
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
|
|
|
))}
|
|
|
|
<TouchableOpacity
|
|
|
|
onPress={() => this.customTextInput.focus()}
|
|
|
|
style={[
|
|
|
|
{ paddingHorizontal: 16, paddingVertical: 8, marginBottom: 10 },
|
|
|
|
selectedFeeType === NetworkTransactionFeeType.CUSTOM && {
|
|
|
|
borderRadius: 8,
|
|
|
|
backgroundColor: BlueCurrentTheme.colors.incomingBackgroundColor,
|
|
|
|
},
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
<View style={{ justifyContent: 'space-between', flexDirection: 'row', alignItems: 'center' }}>
|
|
|
|
<Text style={{ fontSize: 22, color: BlueCurrentTheme.colors.successColor, fontWeight: '600' }}>{loc.send.fee_custom}</Text>
|
|
|
|
</View>
|
|
|
|
<View style={{ justifyContent: 'space-between', flexDirection: 'row', alignItems: 'center', marginTop: 5 }}>
|
|
|
|
<TextInput
|
|
|
|
onChangeText={this.onCustomFeeTextChange}
|
|
|
|
keyboardType="numeric"
|
|
|
|
value={this.state.customFeeValue}
|
|
|
|
ref={ref => (this.customTextInput = ref)}
|
|
|
|
maxLength={9}
|
2020-05-15 11:26:37 +02:00
|
|
|
style={{
|
2020-09-14 12:49:08 +02:00
|
|
|
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,
|
2020-09-15 16:05:25 +02:00
|
|
|
paddingLeft: 5,
|
2020-05-15 11:26:37 +02:00
|
|
|
}}
|
2020-09-14 12:49:08 +02:00
|
|
|
onFocus={() => this.onCustomFeeTextChange(this.state.customFeeValue)}
|
|
|
|
defaultValue={`${this.props.transactionMinimum}`}
|
|
|
|
placeholder={loc.send.fee_satbyte}
|
|
|
|
placeholderTextColor="#81868e"
|
|
|
|
inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}
|
|
|
|
/>
|
|
|
|
<Text style={{ color: BlueCurrentTheme.colors.successColor }}>sat/byte</Text>
|
2020-05-15 11:26:37 +02:00
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
2020-07-15 19:32:59 +02:00
|
|
|
<BlueText style={{ color: BlueCurrentTheme.colors.alternativeTextColor }}>
|
2020-09-14 12:49:08 +02:00
|
|
|
{loc.formatString(loc.send.fee_replace_min, { min: this.props.transactionMinimum })}
|
2020-05-15 11:26:37 +02:00
|
|
|
</BlueText>
|
|
|
|
</View>
|
2019-08-27 06:05:27 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-25 15:16:23 +01:00
|
|
|
export class BlueBitcoinAmount extends Component {
|
|
|
|
static propTypes = {
|
|
|
|
isLoading: PropTypes.bool,
|
2020-06-09 16:08:18 +02:00
|
|
|
/**
|
|
|
|
* amount is a sting thats always in current unit denomination, e.g. '0.001' or '9.43' or '10000'
|
|
|
|
*/
|
2019-05-02 22:33:03 +02:00
|
|
|
amount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
2020-06-09 16:08:18 +02:00
|
|
|
/**
|
|
|
|
* callback that returns currently typed amount, in current denomination, e.g. 0.001 or 10000 or $9.34
|
|
|
|
* (btc, sat, fiat)
|
|
|
|
*/
|
2018-12-25 15:16:23 +01:00
|
|
|
onChangeText: PropTypes.func,
|
2020-06-09 16:08:18 +02:00
|
|
|
/**
|
|
|
|
* callback thats fired to notify of currently selected denomination, returns <BitcoinUnit.*>
|
|
|
|
*/
|
|
|
|
onAmountUnitChange: PropTypes.func,
|
2018-12-25 15:16:23 +01:00
|
|
|
disabled: PropTypes.bool,
|
2019-01-06 07:39:39 +01:00
|
|
|
};
|
|
|
|
|
2020-06-09 16:08:18 +02:00
|
|
|
/**
|
|
|
|
* cache of conversions fiat amount => satoshi
|
|
|
|
* @type {{}}
|
|
|
|
*/
|
|
|
|
static conversionCache = {};
|
|
|
|
|
|
|
|
static getCachedSatoshis(amount) {
|
|
|
|
return BlueBitcoinAmount.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY] || false;
|
|
|
|
}
|
|
|
|
|
2020-06-25 17:39:48 +02:00
|
|
|
static setCachedSatoshis(amount, sats) {
|
|
|
|
BlueBitcoinAmount.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY] = sats;
|
|
|
|
}
|
|
|
|
|
2020-06-09 16:08:18 +02:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = { unit: props.unit || BitcoinUnit.BTC, previousUnit: BitcoinUnit.SATS };
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* here we must recalculate old amont value (which was denominated in `previousUnit`) to new denomination `newUnit`
|
|
|
|
* and fill this value in input box, so user can switch between, for example, 0.001 BTC <=> 100000 sats
|
|
|
|
*
|
|
|
|
* @param previousUnit {string} one of {BitcoinUnit.*}
|
|
|
|
* @param newUnit {string} one of {BitcoinUnit.*}
|
|
|
|
*/
|
|
|
|
onAmountUnitChange(previousUnit, newUnit) {
|
|
|
|
const amount = this.props.amount || 0;
|
|
|
|
console.log('was:', amount, previousUnit, '; converting to', newUnit);
|
|
|
|
let sats = 0;
|
|
|
|
switch (previousUnit) {
|
|
|
|
case BitcoinUnit.BTC:
|
|
|
|
sats = new BigNumber(amount).multipliedBy(100000000).toString();
|
|
|
|
break;
|
|
|
|
case BitcoinUnit.SATS:
|
|
|
|
sats = amount;
|
|
|
|
break;
|
|
|
|
case BitcoinUnit.LOCAL_CURRENCY:
|
|
|
|
sats = new BigNumber(currency.fiatToBTC(amount)).multipliedBy(100000000).toString();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (previousUnit === BitcoinUnit.LOCAL_CURRENCY && BlueBitcoinAmount.conversionCache[amount + previousUnit]) {
|
|
|
|
// cache hit! we reuse old value that supposedly doesnt have rounding errors
|
|
|
|
sats = BlueBitcoinAmount.conversionCache[amount + previousUnit];
|
|
|
|
}
|
|
|
|
console.log('so, in sats its', sats);
|
|
|
|
|
2020-07-20 15:38:46 +02:00
|
|
|
const newInputValue = formatBalancePlain(sats, newUnit, false);
|
2020-06-09 16:08:18 +02:00
|
|
|
console.log('and in', newUnit, 'its', newInputValue);
|
|
|
|
|
|
|
|
if (newUnit === BitcoinUnit.LOCAL_CURRENCY && previousUnit === BitcoinUnit.SATS) {
|
|
|
|
// we cache conversion, so when we will need reverse conversion there wont be a rounding error
|
|
|
|
BlueBitcoinAmount.conversionCache[newInputValue + newUnit] = amount;
|
|
|
|
}
|
|
|
|
this.props.onChangeText(newInputValue);
|
|
|
|
if (this.props.onAmountUnitChange) this.props.onAmountUnitChange(newUnit);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* responsible for cycling currently selected denomination, BTC->SAT->LOCAL_CURRENCY->BTC
|
|
|
|
*/
|
|
|
|
changeAmountUnit = () => {
|
|
|
|
let previousUnit = this.state.unit;
|
|
|
|
let newUnit;
|
|
|
|
if (previousUnit === BitcoinUnit.BTC) {
|
|
|
|
newUnit = BitcoinUnit.SATS;
|
|
|
|
} else if (previousUnit === BitcoinUnit.SATS) {
|
|
|
|
newUnit = BitcoinUnit.LOCAL_CURRENCY;
|
|
|
|
} else if (previousUnit === BitcoinUnit.LOCAL_CURRENCY) {
|
|
|
|
newUnit = BitcoinUnit.BTC;
|
|
|
|
} else {
|
|
|
|
newUnit = BitcoinUnit.BTC;
|
|
|
|
previousUnit = BitcoinUnit.SATS;
|
|
|
|
}
|
|
|
|
this.setState({ unit: newUnit, previousUnit }, () => this.onAmountUnitChange(previousUnit, newUnit));
|
|
|
|
};
|
|
|
|
|
|
|
|
maxLength = () => {
|
|
|
|
switch (this.state.unit) {
|
|
|
|
case BitcoinUnit.BTC:
|
|
|
|
return 10;
|
|
|
|
case BitcoinUnit.SATS:
|
|
|
|
return 15;
|
|
|
|
default:
|
|
|
|
return 15;
|
|
|
|
}
|
2018-12-25 15:16:23 +01:00
|
|
|
};
|
|
|
|
|
2020-05-31 20:33:48 +02:00
|
|
|
textInput = React.createRef();
|
|
|
|
|
|
|
|
handleTextInputOnPress = () => {
|
|
|
|
this.textInput.current.focus();
|
|
|
|
};
|
|
|
|
|
2018-12-25 15:16:23 +01:00
|
|
|
render() {
|
2020-06-09 16:08:18 +02:00
|
|
|
const amount = this.props.amount || 0;
|
2020-07-20 15:38:46 +02:00
|
|
|
let secondaryDisplayCurrency = formatBalanceWithoutSuffix(amount, BitcoinUnit.LOCAL_CURRENCY, false);
|
2020-06-09 16:08:18 +02:00
|
|
|
|
|
|
|
// if main display is sat or btc - secondary display is fiat
|
|
|
|
// if main display is fiat - secondary dislay is btc
|
|
|
|
let sat;
|
|
|
|
switch (this.state.unit) {
|
|
|
|
case BitcoinUnit.BTC:
|
|
|
|
sat = new BigNumber(amount).multipliedBy(100000000).toString();
|
2020-07-20 15:38:46 +02:00
|
|
|
secondaryDisplayCurrency = formatBalanceWithoutSuffix(sat, BitcoinUnit.LOCAL_CURRENCY, false);
|
2020-06-09 16:08:18 +02:00
|
|
|
break;
|
|
|
|
case BitcoinUnit.SATS:
|
2020-07-20 15:38:46 +02:00
|
|
|
secondaryDisplayCurrency = formatBalanceWithoutSuffix(amount.toString(), BitcoinUnit.LOCAL_CURRENCY, false);
|
2020-06-09 16:08:18 +02:00
|
|
|
break;
|
|
|
|
case BitcoinUnit.LOCAL_CURRENCY:
|
|
|
|
secondaryDisplayCurrency = currency.fiatToBTC(parseFloat(amount));
|
|
|
|
if (BlueBitcoinAmount.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY]) {
|
|
|
|
// cache hit! we reuse old value that supposedly doesnt have rounding errors
|
|
|
|
const sats = BlueBitcoinAmount.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY];
|
|
|
|
secondaryDisplayCurrency = currency.satoshiToBTC(sats);
|
|
|
|
}
|
|
|
|
break;
|
2019-05-02 22:33:03 +02:00
|
|
|
}
|
2019-08-25 02:50:43 +02:00
|
|
|
|
2020-06-09 16:08:18 +02:00
|
|
|
if (amount === BitcoinUnit.MAX) secondaryDisplayCurrency = ''; // we dont want to display NaN
|
|
|
|
return (
|
|
|
|
<TouchableWithoutFeedback disabled={this.props.pointerEvents === 'none'} onPress={() => this.textInput.focus()}>
|
|
|
|
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
|
|
|
{!this.props.disabled && <View style={{ alignSelf: 'center', marginLeft: 16, padding: 15 }} />}
|
|
|
|
<View style={{ flex: 1 }}>
|
|
|
|
<View
|
|
|
|
style={{ flexDirection: 'row', alignContent: 'space-between', justifyContent: 'center', paddingTop: 16, paddingBottom: 2 }}
|
2019-01-04 04:28:15 +01:00
|
|
|
>
|
2020-06-09 16:08:18 +02:00
|
|
|
{this.state.unit === BitcoinUnit.LOCAL_CURRENCY && (
|
|
|
|
<Text
|
|
|
|
style={{
|
2020-07-15 19:32:59 +02:00
|
|
|
color: this.props.disabled
|
|
|
|
? BlueCurrentTheme.colors.buttonDisabledTextColor
|
|
|
|
: BlueCurrentTheme.colors.alternativeTextColor2,
|
2020-06-09 16:08:18 +02:00
|
|
|
fontSize: 18,
|
|
|
|
marginHorizontal: 4,
|
|
|
|
fontWeight: 'bold',
|
|
|
|
alignSelf: 'center',
|
|
|
|
justifyContent: 'center',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{currency.getCurrencySymbol() + ' '}
|
|
|
|
</Text>
|
|
|
|
)}
|
|
|
|
<TextInput
|
|
|
|
{...this.props}
|
|
|
|
testID="BitcoinAmountInput"
|
|
|
|
keyboardType="numeric"
|
|
|
|
adjustsFontSizeToFit
|
|
|
|
onChangeText={text => {
|
|
|
|
text = text.trim();
|
|
|
|
if (this.state.unit !== BitcoinUnit.LOCAL_CURRENCY) {
|
|
|
|
text = text.replace(',', '.');
|
|
|
|
const split = text.split('.');
|
|
|
|
if (split.length >= 2) {
|
|
|
|
text = `${parseInt(split[0], 10)}.${split[1]}`;
|
|
|
|
} else {
|
|
|
|
text = `${parseInt(split[0], 10)}`;
|
|
|
|
}
|
|
|
|
text = this.state.unit === BitcoinUnit.BTC ? text.replace(/[^0-9.]/g, '') : text.replace(/[^0-9]/g, '');
|
|
|
|
text = text.replace(/(\..*)\./g, '$1');
|
|
|
|
|
|
|
|
if (text.startsWith('.')) {
|
|
|
|
text = '0.';
|
|
|
|
}
|
|
|
|
text = text.replace(/(0{1,}.)\./g, '$1');
|
|
|
|
if (this.state.unit !== BitcoinUnit.BTC) {
|
|
|
|
text = text.replace(/[^0-9.]/g, '');
|
|
|
|
}
|
|
|
|
} else if (this.state.unit === BitcoinUnit.LOCAL_CURRENCY) {
|
|
|
|
text = text.replace(/,/gi, '');
|
|
|
|
if (text.split('.').length > 2) {
|
|
|
|
// too many dots. stupid code to remove all but first dot:
|
|
|
|
let rez = '';
|
|
|
|
let first = true;
|
|
|
|
for (const part of text.split('.')) {
|
|
|
|
rez += part;
|
|
|
|
if (first) {
|
|
|
|
rez += '.';
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
text = rez;
|
|
|
|
}
|
|
|
|
text = text.replace(/[^\d.,-]/g, ''); // remove all but numberd, dots & commas
|
|
|
|
}
|
|
|
|
|
|
|
|
this.props.onChangeText(text);
|
|
|
|
}}
|
|
|
|
onBlur={() => {
|
|
|
|
if (this.props.onBlur) this.props.onBlur();
|
|
|
|
}}
|
|
|
|
onFocus={() => {
|
|
|
|
if (this.props.onFocus) this.props.onFocus();
|
|
|
|
}}
|
|
|
|
placeholder="0"
|
|
|
|
maxLength={this.maxLength()}
|
|
|
|
ref={textInput => (this.textInput = textInput)}
|
|
|
|
editable={!this.props.isLoading && !this.props.disabled}
|
|
|
|
value={parseFloat(amount) > 0 || amount === BitcoinUnit.MAX ? amount : undefined}
|
|
|
|
placeholderTextColor={
|
2020-07-15 19:32:59 +02:00
|
|
|
this.props.disabled ? BlueCurrentTheme.colors.buttonDisabledTextColor : BlueCurrentTheme.colors.alternativeTextColor2
|
2020-06-09 16:08:18 +02:00
|
|
|
}
|
|
|
|
style={{
|
2020-07-15 19:32:59 +02:00
|
|
|
color: this.props.disabled
|
|
|
|
? BlueCurrentTheme.colors.buttonDisabledTextColor
|
|
|
|
: BlueCurrentTheme.colors.alternativeTextColor2,
|
2020-06-09 16:08:18 +02:00
|
|
|
fontWeight: 'bold',
|
|
|
|
fontSize: amount.length > 10 ? 20 : 36,
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
{this.state.unit !== BitcoinUnit.LOCAL_CURRENCY && (
|
|
|
|
<Text
|
|
|
|
style={{
|
2020-07-15 19:32:59 +02:00
|
|
|
color: this.props.disabled
|
|
|
|
? BlueCurrentTheme.colors.buttonDisabledTextColor
|
|
|
|
: BlueCurrentTheme.colors.alternativeTextColor2,
|
2020-06-09 16:08:18 +02:00
|
|
|
fontSize: 15,
|
|
|
|
marginHorizontal: 4,
|
|
|
|
fontWeight: '600',
|
|
|
|
alignSelf: 'center',
|
|
|
|
justifyContent: 'center',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{' ' + this.state.unit}
|
|
|
|
</Text>
|
|
|
|
)}
|
|
|
|
</View>
|
|
|
|
<View style={{ alignItems: 'center', marginBottom: 22 }}>
|
|
|
|
<Text style={{ fontSize: 16, color: '#9BA0A9', fontWeight: '600' }}>
|
|
|
|
{this.state.unit === BitcoinUnit.LOCAL_CURRENCY && amount !== BitcoinUnit.MAX
|
2020-07-20 15:38:46 +02:00
|
|
|
? removeTrailingZeros(secondaryDisplayCurrency)
|
2020-06-09 16:08:18 +02:00
|
|
|
: secondaryDisplayCurrency}
|
|
|
|
{this.state.unit === BitcoinUnit.LOCAL_CURRENCY && amount !== BitcoinUnit.MAX ? ` ${BitcoinUnit.BTC}` : null}
|
|
|
|
</Text>
|
|
|
|
</View>
|
2019-01-04 04:28:15 +01:00
|
|
|
</View>
|
2020-06-09 16:08:18 +02:00
|
|
|
{!this.props.disabled && (
|
|
|
|
<TouchableOpacity
|
2020-09-15 18:11:18 +02:00
|
|
|
testID="changeAmountUnitButton"
|
2020-06-09 16:08:18 +02:00
|
|
|
style={{ alignSelf: 'center', marginRight: 16, paddingLeft: 16, paddingVertical: 16 }}
|
|
|
|
onPress={this.changeAmountUnit}
|
|
|
|
>
|
|
|
|
<Image source={require('./img/round-compare-arrows-24-px.png')} />
|
|
|
|
</TouchableOpacity>
|
|
|
|
)}
|
2018-12-25 15:16:23 +01:00
|
|
|
</View>
|
2019-01-04 03:06:02 +01:00
|
|
|
</TouchableWithoutFeedback>
|
2018-12-25 15:16:23 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2019-08-03 23:29:15 +02:00
|
|
|
const styles = StyleSheet.create({
|
|
|
|
balanceBlur: {
|
|
|
|
height: 30,
|
|
|
|
width: 100,
|
|
|
|
marginRight: 16,
|
|
|
|
},
|
|
|
|
});
|
2020-04-28 18:27:35 +02:00
|
|
|
|
|
|
|
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 (
|
|
|
|
<View style={mergedStyles}>
|
|
|
|
<Icon name="check" size={50} type="font-awesome" color="#0f5cc0" />
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
}
|
2020-06-24 13:56:35 +02:00
|
|
|
|
2020-06-29 14:58:43 +02:00
|
|
|
const tabsStyles = StyleSheet.create({
|
|
|
|
root: {
|
|
|
|
flexDirection: 'row',
|
|
|
|
height: 50,
|
|
|
|
borderColor: '#e3e3e3',
|
|
|
|
borderBottomWidth: 1,
|
|
|
|
},
|
|
|
|
tabRoot: {
|
|
|
|
justifyContent: 'center',
|
|
|
|
alignItems: 'center',
|
|
|
|
borderColor: 'white',
|
|
|
|
borderBottomWidth: 2,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
export const BlueTabs = ({ active, onSwitch, tabs }) => (
|
|
|
|
<View style={tabsStyles.root}>
|
|
|
|
{tabs.map((Tab, i) => (
|
|
|
|
<TouchableOpacity
|
|
|
|
key={i}
|
|
|
|
onPress={() => onSwitch(i)}
|
|
|
|
style={[
|
|
|
|
tabsStyles.tabRoot,
|
|
|
|
active === i && {
|
2020-07-15 19:32:59 +02:00
|
|
|
borderColor: BlueCurrentTheme.colors.buttonAlternativeTextColor,
|
2020-06-29 14:58:43 +02:00
|
|
|
borderBottomWidth: 2,
|
|
|
|
},
|
|
|
|
{ width: width / tabs.length },
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
<Tab active={active === i} />
|
|
|
|
</TouchableOpacity>
|
|
|
|
))}
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
|
2020-06-24 13:56:35 +02:00
|
|
|
export class DynamicQRCode extends Component {
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
const qrCodeHeight = height > width ? width - 40 : width / 3;
|
|
|
|
const qrCodeMaxHeight = 370;
|
|
|
|
this.state = {
|
|
|
|
index: 0,
|
|
|
|
total: 0,
|
|
|
|
qrCodeHeight: Math.min(qrCodeHeight, qrCodeMaxHeight),
|
|
|
|
intervalHandler: null,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
fragments = [];
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
const { value, capacity = 800 } = this.props;
|
|
|
|
this.fragments = encodeUR(value, capacity);
|
|
|
|
this.setState(
|
|
|
|
{
|
|
|
|
total: this.fragments.length,
|
|
|
|
},
|
|
|
|
() => {
|
|
|
|
this.startAutoMove();
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
moveToNextFragment = () => {
|
|
|
|
const { index, total } = this.state;
|
|
|
|
if (index === total - 1) {
|
|
|
|
this.setState({
|
|
|
|
index: 0,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.setState(state => ({
|
|
|
|
index: state.index + 1,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
startAutoMove = () => {
|
|
|
|
if (!this.state.intervalHandler)
|
|
|
|
this.setState(() => ({
|
|
|
|
intervalHandler: setInterval(this.moveToNextFragment, 500),
|
|
|
|
}));
|
|
|
|
};
|
|
|
|
|
|
|
|
stopAutoMove = () => {
|
|
|
|
clearInterval(this.state.intervalHandler);
|
|
|
|
this.setState(() => ({
|
|
|
|
intervalHandler: null,
|
|
|
|
}));
|
|
|
|
};
|
|
|
|
|
|
|
|
moveToPreviousFragment = () => {
|
|
|
|
const { index, total } = this.state;
|
|
|
|
if (index > 0) {
|
|
|
|
this.setState(state => ({
|
|
|
|
index: state.index - 1,
|
|
|
|
}));
|
|
|
|
} else {
|
|
|
|
this.setState(state => ({
|
|
|
|
index: total - 1,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const currentFragment = this.fragments[this.state.index];
|
|
|
|
return currentFragment ? (
|
|
|
|
<View style={animatedQRCodeStyle.container}>
|
|
|
|
<BlueSpacing20 />
|
2020-08-16 04:43:17 +02:00
|
|
|
<View style={animatedQRCodeStyle.qrcodeContainer}>
|
2020-06-24 13:56:35 +02:00
|
|
|
<QRCode
|
|
|
|
value={currentFragment.toUpperCase()}
|
|
|
|
size={this.state.qrCodeHeight}
|
2020-08-03 19:26:16 +02:00
|
|
|
color="#000000"
|
2020-07-15 19:32:59 +02:00
|
|
|
logoBackgroundColor={BlueCurrentTheme.colors.brandingColor}
|
2020-08-03 19:26:16 +02:00
|
|
|
backgroundColor="#FFFFFF"
|
2020-06-24 13:56:35 +02:00
|
|
|
ecl="L"
|
|
|
|
/>
|
|
|
|
</View>
|
|
|
|
<BlueSpacing20 />
|
|
|
|
<View>
|
|
|
|
<Text style={animatedQRCodeStyle.text}>
|
2020-07-23 15:09:48 +02:00
|
|
|
{loc.formatString(loc._.of, { number: this.state.index + 1, total: this.state.total })}
|
2020-06-24 13:56:35 +02:00
|
|
|
</Text>
|
|
|
|
</View>
|
|
|
|
<BlueSpacing20 />
|
|
|
|
<View style={animatedQRCodeStyle.controller}>
|
|
|
|
<TouchableOpacity
|
|
|
|
style={[animatedQRCodeStyle.button, { width: '25%', alignItems: 'flex-start' }]}
|
|
|
|
onPress={this.moveToPreviousFragment}
|
|
|
|
>
|
2020-07-23 15:09:48 +02:00
|
|
|
<Text style={animatedQRCodeStyle.text}>{loc.send.dynamic_prev}</Text>
|
2020-06-24 13:56:35 +02:00
|
|
|
</TouchableOpacity>
|
|
|
|
<TouchableOpacity
|
|
|
|
style={[animatedQRCodeStyle.button, { width: '50%' }]}
|
|
|
|
onPress={this.state.intervalHandler ? this.stopAutoMove : this.startAutoMove}
|
|
|
|
>
|
2020-07-23 15:09:48 +02:00
|
|
|
<Text style={animatedQRCodeStyle.text}>{this.state.intervalHandler ? loc.send.dynamic_stop : loc.send.dynamic_start}</Text>
|
2020-06-24 13:56:35 +02:00
|
|
|
</TouchableOpacity>
|
|
|
|
<TouchableOpacity
|
|
|
|
style={[animatedQRCodeStyle.button, { width: '25%', alignItems: 'flex-end' }]}
|
|
|
|
onPress={this.moveToNextFragment}
|
|
|
|
>
|
2020-07-23 15:09:48 +02:00
|
|
|
<Text style={animatedQRCodeStyle.text}>{loc.send.dynamic_next}</Text>
|
2020-06-24 13:56:35 +02:00
|
|
|
</TouchableOpacity>
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
) : (
|
|
|
|
<View>
|
2020-07-23 15:09:48 +02:00
|
|
|
<Text>{loc.send.dynamic_init}</Text>
|
2020-06-24 13:56:35 +02:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const animatedQRCodeStyle = StyleSheet.create({
|
|
|
|
container: {
|
|
|
|
flex: 1,
|
|
|
|
flexDirection: 'column',
|
|
|
|
alignItems: 'center',
|
|
|
|
},
|
|
|
|
qrcodeContainer: {
|
|
|
|
alignItems: 'center',
|
|
|
|
justifyContent: 'center',
|
2020-08-03 19:26:16 +02:00
|
|
|
borderWidth: 6,
|
|
|
|
borderRadius: 8,
|
|
|
|
borderColor: '#FFFFFF',
|
2020-08-16 04:43:17 +02:00
|
|
|
margin: 6,
|
2020-06-24 13:56:35 +02:00
|
|
|
},
|
|
|
|
controller: {
|
|
|
|
width: '90%',
|
|
|
|
flexDirection: 'row',
|
|
|
|
justifyContent: 'space-between',
|
|
|
|
alignItems: 'center',
|
|
|
|
borderRadius: 25,
|
|
|
|
height: 45,
|
|
|
|
paddingHorizontal: 18,
|
|
|
|
},
|
|
|
|
button: {
|
|
|
|
alignItems: 'center',
|
|
|
|
height: 45,
|
|
|
|
justifyContent: 'center',
|
|
|
|
},
|
|
|
|
text: {
|
2020-07-15 19:32:59 +02:00
|
|
|
fontSize: 14,
|
|
|
|
color: BlueCurrentTheme.colors.foregroundColor,
|
|
|
|
fontWeight: 'bold',
|
2020-06-24 13:56:35 +02:00
|
|
|
},
|
|
|
|
});
|