ADD: use all UI

This commit is contained in:
Marcos Rodriguez Vélez 2019-01-31 01:52:21 -05:00
parent 3f1165826b
commit e3c8520e9c
4 changed files with 250 additions and 242 deletions

View File

@ -16,6 +16,7 @@ import {
Dimensions,
Image,
SafeAreaView,
InputAccessoryView,
Clipboard,
Platform,
LayoutAnimation,
@ -156,7 +157,7 @@ export class BlueButtonLink extends Component {
}}
{...this.props}
>
<Text style={{ color: '#0c2550', textAlign: 'center', fontSize: 18 }}>{this.props.title}</Text>
<Text style={{ color: '#0c2550', textAlign: 'center', fontSize: 16 }}>{this.props.title}</Text>
</TouchableOpacity>
);
}
@ -205,7 +206,9 @@ export class BlueCopyTextToClipboard extends Component {
constructor() {
super();
if (Platform.OS === 'android') UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
}
}
copyToClipboard = () => {
@ -548,6 +551,27 @@ export class BlueList extends Component {
}
}
export class BlueUseAllFundsButton extends Component {
static InputAccessoryViewID = 'useMaxInputAccessoryViewID';
static propTypes = {
wallet: PropTypes.shape().isRequired,
onUseAllPressed: PropTypes.func.isRequired,
};
render() {
return (
<InputAccessoryView nativeID={BlueUseAllFundsButton.InputAccessoryViewID}>
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
<Text style={{ color: '#9aa0aa', fontSize: 16, marginHorizontal: 8 }}>
Total: {this.props.wallet.getBalance()} {BitcoinUnit.BTC}
</Text>
<BlueButtonLink title="Use All" onPress={this.props.onUseAllPressed} />
</View>
</InputAccessoryView>
);
}
}
export class BlueLoading extends Component {
render() {
return (
@ -573,7 +597,7 @@ const stylesBlueIcon = StyleSheet.create({
paddingHorizontal: 14,
paddingTop: 8,
},
boxIncomming: {
boxIncoming: {
position: 'relative',
},
ball: {
@ -582,14 +606,14 @@ const stylesBlueIcon = StyleSheet.create({
borderRadius: 15,
backgroundColor: '#ccddf9',
},
ballIncomming: {
ballIncoming: {
width: 30,
height: 30,
borderRadius: 15,
backgroundColor: '#d2f8d6',
transform: [{ rotate: '-45deg' }],
},
ballIncommingWithoutRotate: {
ballIncomingWithoutRotate: {
width: 30,
height: 30,
borderRadius: 15,
@ -652,12 +676,12 @@ export class BluePlusIcon extends Component {
}
}
export class BlueTransactionIncommingIcon extends Component {
export class BlueTransactionIncomingIcon extends Component {
render() {
return (
<View {...this.props}>
<View style={stylesBlueIcon.boxIncomming}>
<View style={stylesBlueIcon.ballIncomming}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={stylesBlueIcon.ballIncoming}>
<Icon {...this.props} name="arrow-down" size={16} type="font-awesome" color="#37c0a1" iconStyle={{ left: 0, top: 8 }} />
</View>
</View>
@ -670,7 +694,7 @@ export class BlueTransactionPendingIcon extends Component {
render() {
return (
<View {...this.props}>
<View style={stylesBlueIcon.boxIncomming}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={stylesBlueIcon.ball}>
<Icon
{...this.props}
@ -691,7 +715,7 @@ export class BlueTransactionExpiredIcon extends Component {
render() {
return (
<View {...this.props}>
<View style={stylesBlueIcon.boxIncomming}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={stylesBlueIcon.ballOutgoingWithoutRotate}>
<Icon {...this.props} name="hourglass-end" size={16} type="font-awesome" color="#d0021b" iconStyle={{ left: 0, top: 6 }} />
</View>
@ -705,8 +729,8 @@ export class BlueTransactionOnchainIcon extends Component {
render() {
return (
<View {...this.props}>
<View style={stylesBlueIcon.boxIncomming}>
<View style={stylesBlueIcon.ballIncomming}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={stylesBlueIcon.ballIncoming}>
<Icon
{...this.props}
name="link"
@ -726,7 +750,7 @@ export class BlueTransactionOffchainIcon extends Component {
render() {
return (
<View {...this.props}>
<View style={stylesBlueIcon.boxIncomming}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={stylesBlueIcon.ballOutgoingWithoutRotate}>
<Icon {...this.props} name="bolt" size={16} type="font-awesome" color="#d0021b" iconStyle={{ left: 0, top: 7 }} />
</View>
@ -740,8 +764,8 @@ export class BlueTransactionOffchainIncomingIcon extends Component {
render() {
return (
<View {...this.props}>
<View style={stylesBlueIcon.boxIncomming}>
<View style={stylesBlueIcon.ballIncommingWithoutRotate}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={stylesBlueIcon.ballIncomingWithoutRotate}>
<Icon {...this.props} name="bolt" size={16} type="font-awesome" color="#37c0a1" iconStyle={{ left: 0, top: 7 }} />
</View>
</View>
@ -754,7 +778,7 @@ export class BlueTransactionOutgoingIcon extends Component {
render() {
return (
<View {...this.props}>
<View style={stylesBlueIcon.boxIncomming}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={stylesBlueIcon.ballOutgoing}>
<Icon {...this.props} name="arrow-down" size={16} type="font-awesome" color="#d0021b" iconStyle={{ left: 0, top: 8 }} />
</View>
@ -1112,7 +1136,7 @@ export class BlueTransactionListItem extends Component {
} else {
return (
<View style={{ width: 25 }}>
<BlueTransactionIncommingIcon />
<BlueTransactionIncomingIcon />
</View>
);
}
@ -1171,6 +1195,195 @@ export class BlueTransactionListItem extends Component {
}
}
export class BlueListTransactionItem extends Component {
static propTypes = {
item: PropTypes.shape().isRequired,
itemPriceUnit: PropTypes.string,
};
static defaultProps = {
itemPriceUnit: BitcoinUnit.BTC,
};
txMemo = () => {
if (BlueApp.tx_metadata[this.props.item.hash] && BlueApp.tx_metadata[this.props.item.hash]['memo']) {
return BlueApp.tx_metadata[this.props.item.hash]['memo'];
}
return '';
};
rowTitle = () => {
const item = this.props.item;
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) {
return loc.formatBalanceWithoutSuffix(item.value && item.value, this.props.itemPriceUnit, true).toString();
} else if (invoiceExpiration < now) {
if (item.ispaid) {
return loc.formatBalanceWithoutSuffix(item.value && item.value, this.props.itemPriceUnit, true).toString();
} else {
return loc.lnd.expired;
}
}
} else {
return loc.formatBalanceWithoutSuffix(item.value && item.value, this.props.itemPriceUnit, true).toString();
}
};
rowTitleStyle = () => {
const item = this.props.item;
let color = '#37c0a1';
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) {
color = '#37c0a1';
} else if (invoiceExpiration < now) {
if (item.ispaid) {
color = '#37c0a1';
} else {
color = '#FF0000';
}
}
} else if (item.value / 100000000 < 0) {
color = BlueApp.settings.foregroundColor;
}
return {
fontWeight: '600',
fontSize: 16,
color: color,
};
};
avatar = () => {
// is it lightning refill tx?
if (this.props.item.category === 'receive' && this.props.item.confirmations < 3) {
return (
<View style={{ width: 25 }}>
<BlueTransactionPendingIcon />
</View>
);
}
if (this.props.item.type && this.props.item.type === 'bitcoind_tx') {
return (
<View style={{ width: 25 }}>
<BlueTransactionOnchainIcon />
</View>
);
}
if (this.props.item.type === 'paid_invoice') {
// is it lightning offchain payment?
return (
<View style={{ width: 25 }}>
<BlueTransactionOffchainIcon />
</View>
);
}
if (this.props.item.type === 'user_invoice' || this.props.item.type === 'payment_request') {
if (!this.props.item.ispaid) {
const currentDate = new Date();
const now = (currentDate.getTime() / 1000) | 0;
const invoiceExpiration = this.props.item.timestamp + this.props.item.expire_time;
if (invoiceExpiration < now) {
return (
<View style={{ width: 25 }}>
<BlueTransactionExpiredIcon />
</View>
);
}
} else {
return (
<View style={{ width: 25 }}>
<BlueTransactionOffchainIncomingIcon />
</View>
);
}
}
if (!this.props.item.confirmations) {
return (
<View style={{ width: 25 }}>
<BlueTransactionPendingIcon />
</View>
);
} else if (this.props.item.value < 0) {
return (
<View style={{ width: 25 }}>
<BlueTransactionOutgoingIcon />
</View>
);
} else {
return (
<View style={{ width: 25 }}>
<BlueTransactionIncomingIcon />
</View>
);
}
};
subtitle = () => {
return (
(this.props.item.confirmations < 7 ? loc.transactions.list.conf + ': ' + this.props.item.confirmations + ' ' : '') +
this.txMemo() +
(this.props.item.memo || '')
);
};
onPress = () => {
if (this.props.item.hash) {
NavigationService.navigate('TransactionDetails', { hash: this.props.item.hash });
} else if (
this.props.item.type === 'user_invoice' ||
this.props.item.type === 'payment_request' ||
this.props.item.type === 'paid_invoice'
) {
const lightningWallet = BlueApp.getWallets().filter(wallet => {
if (typeof wallet === 'object') {
if (wallet.hasOwnProperty('secret')) {
return wallet.getSecret() === this.props.item.fromWallet;
}
}
});
NavigationService.navigate('LNDViewInvoice', {
invoice: this.props.item,
fromWallet: lightningWallet[0],
isModal: false,
});
}
};
render() {
return (
<BlueListItem
avatar={this.avatar()}
title={loc.transactionTimeToReadable(this.props.item.received)}
subtitle={this.subtitle()}
onPress={this.onPress}
badge={{
value: 3,
textStyle: { color: 'orange' },
containerStyle: { marginTop: 0 },
}}
hideChevron
rightTitle={this.rowTitle()}
rightTitleStyle={this.rowTitleStyle()}
/>
);
}
}
const sliderWidth = width * 1;
const itemWidth = width * 0.82;
const sliderHeight = 190;
@ -1451,7 +1664,6 @@ export class BlueBitcoinAmount extends Component {
ref={textInput => (this.textInput = textInput)}
editable={!this.props.isLoading && !this.props.disabled}
value={amount}
autoFocus={this.props.pointerEvents !== 'none'}
placeholderTextColor={this.props.disabled ? '#99a0ab' : '#0f5cc0'}
style={{
color: this.props.disabled ? '#99a0ab' : '#0f5cc0',

48
package-lock.json generated
View File

@ -2992,15 +2992,6 @@
"object-visit": "^1.0.0"
}
},
"color": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color/-/color-2.0.1.tgz",
"integrity": "sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw==",
"requires": {
"color-convert": "^1.9.1",
"color-string": "^1.5.2"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@ -3014,15 +3005,6 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"color-string": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
"integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"color-support": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
@ -11026,9 +11008,9 @@
"integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks="
},
"prettier": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.1.tgz",
"integrity": "sha512-XXUITwIkGb3CPJ2hforHah/zTINRyie5006Jd2HKy2qz7snEJXl0KLfsJZW/wst9g6R2rFvqba3VpNYdu1hDcA=="
"version": "1.16.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.2.tgz",
"integrity": "sha512-vBMdCn1LjrFi2CpBsiWVKOq+WP9poXDTIGPe2sG3eE33LQ3b6IUgmaMjLZKKY+frD/8FqPeEK1qAx9mOV8iruA=="
},
"prettier-eslint": {
"version": "8.8.2",
@ -12339,12 +12321,9 @@
}
},
"react-native-svg": {
"version": "9.0.6",
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-9.0.6.tgz",
"integrity": "sha512-oCPl7HPH0yuBva9HZ+TssHS4iVWAGylBffSOwGYN7Kq2zatXeTMfEFyW7JzWMqdGYAFrPldoTtEp9w0vZ3LTLQ==",
"requires": {
"color": "^2.0.1"
}
"version": "9.0.7",
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-9.0.7.tgz",
"integrity": "sha512-+MKWoHri3Z2NLdSrCtw3KKM/z3xWd3nFu9D7/ThPfp/KjdA957eaPhJ2IwOwmjf5s5HlMJ7P4EeCpPs0UQB9oQ=="
},
"react-native-tab-view": {
"version": "1.3.1",
@ -13647,21 +13626,6 @@
}
}
},
"simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
"requires": {
"is-arrayish": "^0.3.1"
},
"dependencies": {
"is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
}
}
},
"sisteransi": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.0.tgz",

View File

@ -14,7 +14,7 @@ import {
Text,
} from 'react-native';
import { Icon } from 'react-native-elements';
import { BlueNavigationStyle, BlueButton, BlueBitcoinAmount, BlueAddressInput } from '../../BlueComponents';
import { BlueNavigationStyle, BlueButton, BlueUseAllFundsButton, BlueBitcoinAmount, BlueAddressInput } from '../../BlueComponents';
import PropTypes from 'prop-types';
import Modal from 'react-native-modal';
import NetworkTransactionFees, { NetworkTransactionFee } from '../../models/networkTransactionFees';
@ -30,7 +30,6 @@ let loc = require('../../loc');
let bitcoin = require('bitcoinjs-lib');
const btcAddressRx = /^[a-zA-Z0-9]{26,35}$/;
export default class SendDetails extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
@ -399,10 +398,17 @@ export default class SendDetails extends Component {
onWalletSelect = wallet => {
this.setState({ fromAddress: wallet.getAddress(), fromSecret: wallet.getSecret(), fromWallet: wallet }, () =>
this.props.navigation.goBack(null),
this.props.navigation.goBack(),
);
};
useAllFundsPressed = async () => {
const total = 0;
const fee = 0;
this.setState({ amount: total - fee });
Keyboard.dismiss();
};
renderFeeSelectionModal = () => {
return (
<Modal
@ -525,7 +531,6 @@ export default class SendDetails extends Component {
</View>
);
}
return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View style={{ flex: 1, justifyContent: 'space-between' }}>
@ -535,6 +540,7 @@ export default class SendDetails extends Component {
isLoading={this.state.isLoading}
amount={this.state.amount}
onChangeText={text => this.setState({ amount: text })}
inputAccessoryViewID={BlueUseAllFundsButton.InputAccessoryViewID}
/>
<BlueAddressInput
onChangeText={text => {
@ -610,6 +616,7 @@ export default class SendDetails extends Component {
</KeyboardAvoidingView>
</View>
{this.renderWalletSelectionButton()}
<BlueUseAllFundsButton wallet={this.state.fromWallet} onUseAllPressed={this.useAllFundsPressed} />
</View>
</TouchableWithoutFeedback>
);

View File

@ -1,20 +1,6 @@
import React, { Component } from 'react';
import { View, TouchableOpacity, Text, FlatList, RefreshControl, ScrollView } from 'react-native';
import {
BlueTransactionOnchainIcon,
BlueLoading,
SafeBlueArea,
WalletsCarousel,
BlueTransactionIncommingIcon,
BlueTransactionOutgoingIcon,
BlueTransactionPendingIcon,
BlueTransactionOffchainIcon,
BlueTransactionExpiredIcon,
BlueList,
BlueListItem,
BlueHeaderDefaultMain,
BlueTransactionOffchainIncomingIcon,
} from '../../BlueComponents';
import { BlueLoading, SafeBlueArea, WalletsCarousel, BlueList, BlueHeaderDefaultMain, BlueListTransactionItem } from '../../BlueComponents';
import { Icon } from 'react-native-elements';
import { NavigationEvents } from 'react-navigation';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
@ -232,60 +218,9 @@ export default class WalletsList extends Component {
}
};
rowTitle = item => {
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) {
return loc.formatBalanceWithoutSuffix(item.value && item.value, item.walletPreferredBalanceUnit, true).toString();
} else if (invoiceExpiration < now) {
if (item.ispaid) {
return loc.formatBalanceWithoutSuffix(item.value && item.value, item.walletPreferredBalanceUnit, true).toString();
} else {
return loc.lnd.expired;
}
}
} else {
return loc.formatBalanceWithoutSuffix(item.value && item.value, item.walletPreferredBalanceUnit, true).toString();
}
};
rowTitleStyle = item => {
let color = '#37c0a1';
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) {
color = '#37c0a1';
} else if (invoiceExpiration < now) {
if (item.ispaid) {
color = '#37c0a1';
} else {
color = '#FF0000';
}
}
} else if (item.value / 100000000 < 0) {
color = BlueApp.settings.foregroundColor;
}
return {
fontWeight: '600',
fontSize: 16,
color: color,
};
};
_renderItem = data => <BlueListTransactionItem item={data.item} itemPriceUnit={data.item.walletPreferredBalanceUnit} />;
render() {
const { navigate } = this.props.navigation;
if (this.state.isLoading) {
return <BlueLoading />;
}
@ -338,117 +273,7 @@ export default class WalletsList extends Component {
data={this.state.dataSource}
extraData={this.state.dataSource}
keyExtractor={this._keyExtractor}
renderItem={rowData => {
return (
<BlueListItem
avatar={(() => {
// is it lightning refill tx?
if (rowData.item.category === 'receive' && rowData.item.confirmations < 3) {
return (
<View style={{ width: 25 }}>
<BlueTransactionPendingIcon />
</View>
);
}
if (rowData.item.type && rowData.item.type === 'bitcoind_tx') {
return (
<View style={{ width: 25 }}>
<BlueTransactionOnchainIcon />
</View>
);
}
if (rowData.item.type === 'paid_invoice') {
// is it lightning offchain payment?
return (
<View style={{ width: 25 }}>
<BlueTransactionOffchainIcon />
</View>
);
}
if (rowData.item.type === 'user_invoice' || rowData.item.type === 'payment_request') {
if (!rowData.item.ispaid) {
const currentDate = new Date();
const now = (currentDate.getTime() / 1000) | 0;
const invoiceExpiration = rowData.item.timestamp + rowData.item.expire_time;
if (invoiceExpiration < now) {
return (
<View style={{ width: 25 }}>
<BlueTransactionExpiredIcon />
</View>
);
}
} else {
return (
<View style={{ width: 25 }}>
<BlueTransactionOffchainIncomingIcon />
</View>
);
}
}
if (!rowData.item.confirmations) {
return (
<View style={{ width: 25 }}>
<BlueTransactionPendingIcon />
</View>
);
} else if (rowData.item.value < 0) {
return (
<View style={{ width: 25 }}>
<BlueTransactionOutgoingIcon />
</View>
);
} else {
return (
<View style={{ width: 25 }}>
<BlueTransactionIncommingIcon />
</View>
);
}
})()}
title={loc.transactionTimeToReadable(rowData.item.received)}
subtitle={
(rowData.item.confirmations < 7 ? loc.transactions.list.conf + ': ' + rowData.item.confirmations + ' ' : '') +
this.txMemo(rowData.item.hash) +
(rowData.item.memo || '')
}
onPress={() => {
if (rowData.item.hash) {
navigate('TransactionDetails', {
hash: rowData.item.hash,
});
} else if (
rowData.item.type === 'user_invoice' ||
rowData.item.type === 'payment_request' ||
rowData.item.type === 'paid_invoice'
) {
const lightningWallet = this.state.wallets.filter(wallet => {
if (typeof wallet === 'object') {
if (wallet.hasOwnProperty('secret')) {
return wallet.getSecret() === rowData.item.fromWallet;
}
}
});
this.props.navigation.navigate('LNDViewInvoice', {
invoice: rowData.item,
fromWallet: lightningWallet[0],
isModal: false,
});
}
}}
badge={{
value: 3,
textStyle: { color: 'orange' },
containerStyle: { marginTop: 0 },
}}
hideChevron
rightTitle={this.rowTitle(rowData.item)}
rightTitleStyle={this.rowTitleStyle(rowData.item)}
/>
);
}}
renderItem={this._renderItem}
/>
</BlueList>
</ScrollView>