diff --git a/BlueApp.js b/BlueApp.js index 0bbc8e4db..53d32d2c1 100644 --- a/BlueApp.js +++ b/BlueApp.js @@ -15,7 +15,7 @@ async function startAndDecrypt(retry) { let password = false; if (await BlueApp.storageIsEncrypted()) { do { - password = await prompt((retry && loc._.bad_password) || loc._.enter_password, loc._.storage_is_encrypted); + password = await prompt((retry && loc._.bad_password) || loc._.enter_password, loc._.storage_is_encrypted, false); } while (!password); } let success = await BlueApp.loadFromDisk(password); diff --git a/BlueComponents.js b/BlueComponents.js index b527efff7..46537fba8 100644 --- a/BlueComponents.js +++ b/BlueComponents.js @@ -883,9 +883,9 @@ export class NewWalletPannel extends Component { } } -let sliderWidth = width * 1; -let itemWidth = width * 0.82; -let sliderHeight = 190; +const sliderWidth = width * 1; +const itemWidth = width * 0.82; +const sliderHeight = 190; export class WalletsCarousel extends Component { constructor(props) { @@ -1023,25 +1023,24 @@ export class WalletsCarousel extends Component { render() { return ( - - { - WalletsCarousel.carousel = c; - }} - renderItem={this._renderItem} - sliderWidth={sliderWidth} - itemWidth={itemWidth} - inactiveSlideScale={1} - inactiveSlideOpacity={0.7} - onSnapToItem={index => { - if (this.onSnapToItem) { - this.onSnapToItem(index); - } - console.log('snapped to card #', index); - }} - /> - + { + WalletsCarousel.carousel = c; + }} + renderItem={this._renderItem} + sliderWidth={sliderWidth} + sliderHeight={sliderHeight} + itemWidth={itemWidth} + inactiveSlideScale={1} + inactiveSlideOpacity={0.7} + onSnapToItem={index => { + if (this.onSnapToItem) { + this.onSnapToItem(index); + } + console.log('snapped to card #', index); + }} + /> ); } } diff --git a/HDWallet.test.js b/HDWallet.test.js index 2b93df7c3..067b1a6c5 100644 --- a/HDWallet.test.js +++ b/HDWallet.test.js @@ -220,6 +220,9 @@ it('HD breadwallet works', async function() { await hdBread.fetchTransactions(); assert.ok(hdBread._lastTxFetch > 0); assert.equal(hdBread.transactions.length, 177); + for (let tx of hdBread.getTransactions()) { + assert.ok(tx.confirmations); + } assert.equal(hdBread.next_free_address_index, 10); assert.equal(hdBread.next_free_change_address_index, 118); diff --git a/MainBottomTabs.js b/MainBottomTabs.js index 807055c09..e02b47815 100644 --- a/MainBottomTabs.js +++ b/MainBottomTabs.js @@ -1,6 +1,11 @@ import { createStackNavigator } from 'react-navigation'; -import wallets from './screen/wallets'; +import Settings from './screen/settings/settings'; +import About from './screen/settings/about'; +import Language from './screen/settings/language'; +import EncryptStorage from './screen/settings/encryptStorage'; +import WalletsList from './screen/wallets/list'; +import WalletTransactions from './screen/wallets/transactions'; import AddWallet from './screen/wallets/add'; import ImportWallet from './screen/wallets/import'; import WalletDetails from './screen/wallets/details'; @@ -20,15 +25,48 @@ import sendCreate from './screen/send/create'; import ManageFunds from './screen/lnd/manageFunds'; import ScanLndInvoice from './screen/lnd/scanLndInvoice'; +const WalletsStackNavigator = createStackNavigator({ + Wallets: { + screen: WalletsList, + path: 'wallets', + }, + Settings: { + screen: Settings, + path: 'Settings', + navigationOptions: { + headerStyle: { + backgroundColor: '#FFFFFF', + borderBottomWidth: 0, + }, + headerTintColor: '#0c2550', + }, + }, + About: { + screen: About, + path: 'About', + }, + Language: { + screen: Language, + path: 'Language', + }, + EncryptStorage: { + screen: EncryptStorage, + path: 'EncryptStorage', + }, +}); + const Tabs = createStackNavigator( { Wallets: { - screen: wallets, + screen: WalletsStackNavigator, path: 'wallets', navigationOptions: { header: null, }, }, + WalletTransactions: { + screen: WalletTransactions, + }, AddWallet: { screen: AddWallet, }, @@ -44,7 +82,6 @@ const Tabs = createStackNavigator( WalletExport: { screen: WalletExport, }, - // TransactionDetails: { diff --git a/class/abstract-hd-wallet.js b/class/abstract-hd-wallet.js index d2e519691..4a9bc25ee 100644 --- a/class/abstract-hd-wallet.js +++ b/class/abstract-hd-wallet.js @@ -239,6 +239,11 @@ export class AbstractHDWallet extends LegacyWallet { break; } + let latestBlock = false; + if (response.body.info && response.body.info.latest_block) { + latestBlock = response.body.info.latest_block.height; + } + this._lastTxFetch = +new Date(); // processing TXs and adding to internal memory @@ -291,6 +296,9 @@ export class AbstractHDWallet extends LegacyWallet { } tx.value = value; // new BigNumber(value).div(100000000).toString() * 1; + if (!tx.confirmations && latestBlock) { + tx.confirmations = latestBlock - tx.block_height; + } this.transactions.push(tx); } diff --git a/class/app-storage.js b/class/app-storage.js index 7eeb3ec15..7f58b2acc 100644 --- a/class/app-storage.js +++ b/class/app-storage.js @@ -312,7 +312,14 @@ export class AppStorage { for (let wallet of this.wallets) { txs = txs.concat(wallet.getTransactions()); } - return txs; + + for (let t of txs) { + t.sort_ts = +new Date(t.received); + } + + return txs.sort(function(a, b) { + return b.sort_ts > a.sort_ts; + }); } /** diff --git a/class/lightning-custodian-wallet.js b/class/lightning-custodian-wallet.js index 2a1ce8898..f97e4c538 100644 --- a/class/lightning-custodian-wallet.js +++ b/class/lightning-custodian-wallet.js @@ -16,6 +16,11 @@ export class LightningCustodianWallet extends LegacyWallet { this.info_raw = false; } + allowSend() { + console.log(this.getBalance(), this.getBalance() > 0); + return this.getBalance() > 0; + } + getAddress() { return ''; } diff --git a/events.js b/events.js index 444f53d4f..5e2854149 100644 --- a/events.js +++ b/events.js @@ -20,9 +20,19 @@ function EV(eventName, arg) { } EV.enum = { + // emitted when local wallet created or deleted, so one must redraw wallets carousel WALLETS_COUNT_CHANGED: 'WALLETS_COUNT_CHANGED', + + // emitted when local wallet (usually current wallet) has changed number of transactions + // so one must redraw main screen transactions list and WalletTransactions screen tx list TRANSACTIONS_COUNT_CHANGED: 'TRANSACTIONS_COUNT_CHANGED', + + // emitted when we know for sure that on remote server tx list + // changed (usually for current wallet) + REMOTE_TRANSACTIONS_COUNT_CHANGED: 'REMOTE_TRANSACTIONS_COUNT_CHANGED', + CREATE_TRANSACTION_NEW_DESTINATION_ADDRESS: 'CREATE_TRANSACTION_NEW_DESTINATION_ADDRESS', + // RECEIVE_ADDRESS_CHANGED: 'RECEIVE_ADDRESS_CHANGED', }; diff --git a/loc/en.js b/loc/en.js index 3d91566e4..242b472be 100644 --- a/loc/en.js +++ b/loc/en.js @@ -10,6 +10,7 @@ module.exports = { never: 'never', }, wallets: { + options: 'options', list: { app_name: 'Blue Wallet', title: 'wallets', diff --git a/loc/es.js b/loc/es.js index f0dd3490e..c159b6288 100644 --- a/loc/es.js +++ b/loc/es.js @@ -10,6 +10,7 @@ module.exports = { never: 'nunca', }, wallets: { + options: 'opciones', list: { app_name: 'Blue Wallet', title: 'carteras', diff --git a/loc/pt_BR.js b/loc/pt_BR.js index a29dcbfeb..3340db7ac 100644 --- a/loc/pt_BR.js +++ b/loc/pt_BR.js @@ -10,6 +10,7 @@ module.exports = { never: 'nunca...', }, wallets: { + options: 'options', list: { tabBarLabel: 'Wallets', app_name: 'Blue Wallet', diff --git a/loc/pt_PT.js b/loc/pt_PT.js index 82daa8aa8..84bb2c6a1 100644 --- a/loc/pt_PT.js +++ b/loc/pt_PT.js @@ -10,6 +10,7 @@ module.exports = { never: 'never', }, wallets: { + options: 'options', list: { app_name: 'Blue Wallet', title: 'wallets', diff --git a/loc/ru.js b/loc/ru.js index 509cded56..17cface35 100644 --- a/loc/ru.js +++ b/loc/ru.js @@ -10,6 +10,7 @@ module.exports = { never: 'никогда', }, wallets: { + options: 'options', list: { app_name: 'BlueWallet', title: 'кошельки', diff --git a/loc/ua.js b/loc/ua.js index b327b0a08..12fed94c4 100644 --- a/loc/ua.js +++ b/loc/ua.js @@ -10,6 +10,7 @@ module.exports = { never: 'ніколи', }, wallets: { + options: 'options', list: { app_name: 'BlueWallet', title: 'гаманці', diff --git a/prompt.js b/prompt.js index 85eb65c1e..76004ffc4 100644 --- a/prompt.js +++ b/prompt.js @@ -1,27 +1,34 @@ import { AlertIOS } from 'react-native'; -module.exports = (title, text) => { +module.exports = (title, text, isCancelable = true) => { return new Promise((resolve, reject) => { - AlertIOS.prompt( - title, - text, - [ - { - text: 'Cancel', - onPress: () => { - reject(Error('Cancel Pressed')); + const buttons = isCancelable + ? [ + { + text: 'Cancel', + onPress: () => { + reject(Error('Cancel Pressed')); + }, + style: 'cancel', }, - style: 'cancel', - }, - { - text: 'OK', - onPress: password => { - console.log('OK Pressed, password: ' + password); - resolve(password); + { + text: 'OK', + onPress: password => { + console.log('OK Pressed, password: ' + password); + resolve(password); + }, }, - }, - ], - 'secure-text', - ); + ] + : [ + { + text: 'OK', + onPress: password => { + console.log('OK Pressed, password: ' + password); + resolve(password); + }, + }, + ]; + + AlertIOS.prompt(title, text, buttons, 'secure-text'); }); }; diff --git a/screen/lnd/scanLndInvoice.js b/screen/lnd/scanLndInvoice.js index 90804f7e9..e70c8d01e 100644 --- a/screen/lnd/scanLndInvoice.js +++ b/screen/lnd/scanLndInvoice.js @@ -130,7 +130,7 @@ export default class ScanLndInvoice extends React.Component { } console.log('payInvoice took', (end - start) / 1000, 'sec'); - EV(EV.enum.TRANSACTIONS_COUNT_CHANGED); + EV(EV.enum.REMOTE_TRANSACTIONS_COUNT_CHANGED); // someone should fetch txs alert('Success'); this.props.navigation.goBack(); diff --git a/screen/send/create.js b/screen/send/create.js index 946391de7..5f69c2c46 100644 --- a/screen/send/create.js +++ b/screen/send/create.js @@ -126,7 +126,7 @@ export default class SendCreate extends Component { broadcastSuccessMessage: '', }); } else { - EV(EV.enum.TRANSACTIONS_COUNT_CHANGED); + EV(EV.enum.REMOTE_TRANSACTIONS_COUNT_CHANGED); // someone should fetch txs this.setState({ broadcastErrorMessage: '' }); this.setState({ broadcastSuccessMessage: 'Success! TXID: ' + JSON.stringify(result.result), diff --git a/screen/settings/encryptStorage.js b/screen/settings/encryptStorage.js index a796802c6..8cbae9a07 100644 --- a/screen/settings/encryptStorage.js +++ b/screen/settings/encryptStorage.js @@ -68,7 +68,7 @@ export default class EncryptStorage extends Component { this.setState({ isLoading: true }); let p1 = await prompt(loc.settings.password, loc.settings.password_explain).catch(() => { this.setState({ isLoading: false }); - this.props.navigation.goBack(); + p1 = undefined; }); if (!p1) { this.setState({ isLoading: false }); @@ -76,7 +76,6 @@ export default class EncryptStorage extends Component { } let p2 = await prompt(loc.settings.password, loc.settings.retype_password).catch(() => { this.setState({ isLoading: false }); - this.props.navigation.goBack(); }); if (p1 === p2) { await BlueApp.encryptStorage(p1); diff --git a/screen/settings/settings.js b/screen/settings/settings.js index 039657654..ebcec12b7 100644 --- a/screen/settings/settings.js +++ b/screen/settings/settings.js @@ -8,11 +8,13 @@ let loc = require('../../loc'); export default class Settings extends Component { static navigationOptions = { - headerStyle: { - backgroundColor: '#FFFFFF', - borderBottomWidth: 0, + navigationOptions: { + headerStyle: { + backgroundColor: '#FFFFFF', + borderBottomWidth: 0, + }, + headerTintColor: '#0c2550', }, - headerTintColor: '#0c2550', }; constructor(props) { diff --git a/screen/wallets.js b/screen/wallets.js deleted file mode 100644 index 1221bbaaf..000000000 --- a/screen/wallets.js +++ /dev/null @@ -1,30 +0,0 @@ -import { createStackNavigator } from 'react-navigation'; -import WalletsList from './wallets/list'; -import Settings from '../screen/settings/settings'; -import About from '../screen/settings/about'; -import Language from '../screen/settings/language'; -import EncryptStorage from '../screen/settings/encryptStorage'; - -const WalletsNavigator = createStackNavigator({ - WalletsList: { - screen: WalletsList, - }, - Settings: { - screen: Settings, - path: 'Settings', - }, - About: { - screen: About, - path: 'About', - }, - Language: { - screen: Language, - path: 'Language', - }, - EncryptStorage: { - screen: EncryptStorage, - path: 'EncryptStorage', - }, -}); - -export default WalletsNavigator; diff --git a/screen/wallets/details.js b/screen/wallets/details.js index 62dbb6623..8c029ec16 100644 --- a/screen/wallets/details.js +++ b/screen/wallets/details.js @@ -120,7 +120,7 @@ export default class WalletDetails extends Component { await BlueApp.saveToDisk(); EV(EV.enum.TRANSACTIONS_COUNT_CHANGED); EV(EV.enum.WALLETS_COUNT_CHANGED); - this.props.navigation.goBack(); + this.props.navigation.navigate('Wallets'); }} title={loc.wallets.details.yes_delete} /> diff --git a/screen/wallets/list.js b/screen/wallets/list.js index 2a9af8e82..2fe36288b 100644 --- a/screen/wallets/list.js +++ b/screen/wallets/list.js @@ -1,9 +1,7 @@ import React, { Component } from 'react'; -import { View, TouchableOpacity, Text, FlatList, RefreshControl, LayoutAnimation } from 'react-native'; +import { View, TouchableOpacity, Text, FlatList, RefreshControl, LayoutAnimation, ScrollView } from 'react-native'; import { - BlueText, BlueTransactionOnchainIcon, - ManageFundsBigButton, BlueLoading, SafeBlueArea, WalletsCarousel, @@ -11,15 +9,12 @@ import { BlueTransactionOutgoingIcon, BlueTransactionPendingIcon, BlueTransactionOffchainIcon, - BlueSendButtonIcon, - BlueReceiveButtonIcon, BlueList, BlueListItem, BlueHeaderDefaultMain, } from '../../BlueComponents'; import { Icon } from 'react-native-elements'; import PropTypes from 'prop-types'; -import { LightningCustodianWallet } from '../../class/lightning-custodian-wallet'; const BigNumber = require('bignumber.js'); let EV = require('../../events'); let A = require('../../analytics'); @@ -63,17 +58,32 @@ export default class WalletsList extends Component { isLoading: true, }; EV(EV.enum.WALLETS_COUNT_CHANGED, this.refreshFunction.bind(this)); - EV(EV.enum.TRANSACTIONS_COUNT_CHANGED, this.refreshTransactions.bind(this)); + + // here, when we receive TRANSACTIONS_COUNT_CHANGED we do not query + // remote server, we just redraw the screen + EV(EV.enum.TRANSACTIONS_COUNT_CHANGED, this.refreshFunction.bind(this)); } async componentDidMount() { this.refreshFunction(); - } // end of componendDidMount + + LayoutAnimation.configureNext(customLayoutSpringAnimation); + this.setState({ + isLoading: false, + dataSource: BlueApp.getTransactions(), + }); + } /** * Forcefully fetches TXs and balance for lastSnappedTo (i.e. current) wallet */ refreshTransactions() { + if (!(this.lastSnappedTo < BlueApp.getWallets().length)) { + // last card, nop + console.log('last card, nop'); + return; + } + this.setState( { isTransactionsLoading: true, @@ -88,7 +98,7 @@ export default class WalletsList extends Component { let start = +new Date(); await BlueApp.fetchWalletTransactions(that.lastSnappedTo || 0); let end = +new Date(); - console.log('tx took', (end - start) / 1000, 'sec'); + console.log('fetch tx took', (end - start) / 1000, 'sec'); } catch (err) { noErr = false; console.warn(err); @@ -109,38 +119,11 @@ export default class WalletsList extends Component { A(A.ENUM.GOT_NONZERO_BALANCE); } - setTimeout(() => { - console.log('refreshFunction()'); - let showSend = false; - let showReceive = false; - let showManageFundsBig = false; - let showManageFundsSmallButton = false; - let wallets = BlueApp.getWallets(); - let wallet = wallets[this.lastSnappedTo || 0]; - if (wallet) { - showSend = wallet.allowSend(); - showReceive = wallet.allowReceive(); - } - - if (wallet && wallet.type === new LightningCustodianWallet().type && !showSend) { - showManageFundsBig = true; - showManageFundsSmallButton = false; - } - - if (wallet && wallet.type === new LightningCustodianWallet().type && wallet.getBalance() > 0) { - showManageFundsSmallButton = true; - } - - this.setState({ - isLoading: false, - isTransactionsLoading: false, - showReceiveButton: showReceive, - showSendButton: showSend, - showManageFundsBigButton: showManageFundsBig, - showManageFundsSmallButton, - dataSource: BlueApp.getTransactions(this.lastSnappedTo || 0), - }); - }, 1); + this.setState({ + isLoading: false, + isTransactionsLoading: false, + dataSource: BlueApp.getTransactions(), + }); } txMemo(hash) { @@ -151,12 +134,11 @@ export default class WalletsList extends Component { } handleClick(index) { - console.log('cick', index); + console.log('click', index); let wallet = BlueApp.wallets[index]; if (wallet) { - this.props.navigation.navigate('WalletDetails', { - address: wallet.getAddress(), // either one of them will work - secret: wallet.getSecret(), + this.props.navigation.navigate('WalletTransactions', { + wallet: wallet, }); } else { // if its out of index - this must be last card with incentive to create wallet @@ -168,63 +150,15 @@ export default class WalletsList extends Component { console.log('onSnapToItem', index); this.lastSnappedTo = index; LayoutAnimation.configureNext(customLayoutSpringAnimation); - this.setState({ - isLoading: false, - showReceiveButton: false, - showManageFundsBigButton: false, - showManageFundsSmallButton: false, - showSendButton: false, - dataSource: BlueApp.getTransactions(index), - }); if (index < BlueApp.getWallets().length) { - // do not show for last card - - let showSend = false; - let showReceive = false; - let showManageFundsBig = false; - let wallets = BlueApp.getWallets(); - let wallet = wallets[this.lastSnappedTo || 0]; - if (wallet) { - showSend = wallet.allowSend(); - showReceive = wallet.allowReceive(); - } - console.log({ showSend }); - let showManageFundsSmallButton = true; - if (wallet && wallet.type === new LightningCustodianWallet().type && !showSend) { - showManageFundsBig = true; - showManageFundsSmallButton = false; - } - - if (wallet && wallet.type === new LightningCustodianWallet().type) { - } else { - showManageFundsSmallButton = false; - } - - console.log({ showManageFundsBig }); - - LayoutAnimation.configureNext(customLayoutSpringAnimation); - this.setState({ - showReceiveButton: showReceive, - showManageFundsBigButton: showManageFundsBig, - showManageFundsSmallButton, - showSendButton: showSend, - }); + // not the last } // now, lets try to fetch balance and txs for this wallet in case it has changed this.lazyRefreshWallet(index); } - isLightning() { - let w = BlueApp.getWallets()[this.lastSnappedTo || 0]; - if (w && w.type === new LightningCustodianWallet().type) { - return true; - } - - return false; - } - /** * Decides whether wallet with such index shoud be refreshed, * refreshes if yes and redraws the screen @@ -237,6 +171,7 @@ export default class WalletsList extends Component { if (!wallets[index]) { return; } + let oldBalance = wallets[index].getBalance(); let noErr = true; let didRefresh = false; @@ -275,6 +210,24 @@ export default class WalletsList extends Component { _keyExtractor = (item, index) => index.toString(); + renderListHeaderComponent = () => { + return ( + + + {loc.transactions.list.title} + + + ); + }; + render() { const { navigate } = this.props.navigation; @@ -283,275 +236,107 @@ export default class WalletsList extends Component { } return ( - - this.props.navigation.navigate('AddWallet')} /> - { - this.handleClick(index); - }} - onSnapToItem={index => { - this.onSnapToItem(index); - }} - /> + + this.refreshTransactions()} refreshing={this.state.isTransactionsLoading} />} + > + this.props.navigation.navigate('AddWallet')} /> + { + this.handleClick(index); + }} + onSnapToItem={index => { + this.onSnapToItem(index); + }} + /> + + { + return ( + { + // is it lightning refill tx? + if (rowData.item.category === 'receive' && rowData.item.confirmations < 3) { + return ( + + + + ); + } - {(() => { - if (this.state.showManageFundsSmallButton) { - return ( - { - let walletIndex = this.lastSnappedTo || 0; + if (rowData.item.type && rowData.item.type === 'bitcoind_tx') { + return ( + + + + ); + } + if (rowData.item.type === 'paid_invoice') { + // is it lightning offchain payment? + return ( + + + + ); + } - let c = 0; - for (let w of BlueApp.getWallets()) { - if (c++ === walletIndex) { - console.log('navigating to secret ', w.getSecret()); - navigate('ManageFunds', { fromSecret: w.getSecret() }); + if (!rowData.item.confirmations) { + return ( + + + + ); + } else if (rowData.item.value < 0) { + return ( + + + + ); + } else { + return ( + + + + ); + } + })()} + 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 || '') } - } - }} - > - {loc.lnd.title} - - - ); - } - })()} - - {(() => { - return ( - - - - {loc.transactions.list.title} - - - - - {(() => { - if (BlueApp.getTransactions(this.lastSnappedTo || 0).length === 0) { - return ( - - - {(this.isLightning() && - 'Lightning wallet should be used for your daily\ntransactions. Fees are unfairly cheap and\nspeed is blazing fast.') || - loc.wallets.list.empty_txs1} - - - {(this.isLightning() && '\nTo start using it tap on "manage funds"\nand topup your balance') || - loc.wallets.list.empty_txs2} - - - ); - } - })()} - - - - - this.refreshTransactions()} refreshing={this.state.isTransactionsLoading} /> - } - data={this.state.dataSource} - extraData={this.state.dataSource} - keyExtractor={this._keyExtractor} - renderItem={rowData => { - return ( - { - // is it lightning refill tx? - if (rowData.item.category === 'receive' && rowData.item.confirmations < 3) { - return ( - - - - ); - } - - if (rowData.item.type && rowData.item.type === 'bitcoind_tx') { - return ( - - - - ); - } - if (rowData.item.type === 'paid_invoice') { - // is it lightning offchain payment? - return ( - - - - ); - } - - if (!rowData.item.confirmations) { - return ( - - - - ); - } else if (rowData.item.value < 0) { - return ( - - - - ); - } else { - return ( - - - - ); - } - })()} - 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, - }); - } - }} - badge={{ - value: 3, - textStyle: { color: 'orange' }, - containerStyle: { marginTop: 0 }, - }} - hideChevron - rightTitle={new BigNumber((rowData.item.value && rowData.item.value) || 0).div(100000000).toString()} - rightTitleStyle={{ - fontWeight: '600', - fontSize: 16, - color: rowData.item.value / 100000000 < 0 ? BlueApp.settings.foregroundColor : '#37c0a1', - }} - /> - ); + onPress={() => { + if (rowData.item.hash) { + navigate('TransactionDetails', { + hash: rowData.item.hash, + }); + } + }} + badge={{ + value: 3, + textStyle: { color: 'orange' }, + containerStyle: { marginTop: 0 }, + }} + hideChevron + rightTitle={new BigNumber((rowData.item.value && rowData.item.value) || 0).div(100000000).toString()} + rightTitleStyle={{ + fontWeight: '600', + fontSize: 16, + color: rowData.item.value / 100000000 < 0 ? BlueApp.settings.foregroundColor : '#37c0a1', }} /> - - - - ); - })()} - - {(() => { - if (this.state.showReceiveButton) { - return ( - { - let start = +new Date(); - let walletIndex = this.lastSnappedTo || 0; - console.log('receiving on #', walletIndex); - - let c = 0; - for (let w of BlueApp.getWallets()) { - if (c++ === walletIndex) { - console.log('found receiving address, secret=', w.getAddress(), ',', w.getSecret()); - navigate('ReceiveDetails', { address: w.getAddress(), secret: w.getSecret() }); - if (w.getAddress()) { - // EV(EV.enum.RECEIVE_ADDRESS_CHANGED, w.getAddress()); - } - } - } - let end = +new Date(); - console.log('took', (end - start) / 1000, 'sec'); - }} - /> - ); - } - })()} - - {(() => { - if (this.state.showSendButton) { - return ( - { - let walletIndex = this.lastSnappedTo || 0; - - let c = 0; - for (let w of BlueApp.getWallets()) { - if (c++ === walletIndex) { - if (w.type === new LightningCustodianWallet().type) { - navigate('ScanLndInvoice', { fromSecret: w.getSecret() }); - } else { - navigate('SendDetails', { fromAddress: w.getAddress(), fromSecret: w.getSecret() }); - } - } - } - }} - /> - ); - } - })()} - - {(() => { - if (this.state.showManageFundsBigButton) { - return ( - { - let walletIndex = this.lastSnappedTo || 0; - - let c = 0; - for (let w of BlueApp.getWallets()) { - if (c++ === walletIndex) { - console.log('navigating to secret ', w.getSecret()); - navigate('ManageFunds', { fromSecret: w.getSecret() }); - } - } - }} - /> - ); - } - })()} - + ); + }} + /> + + ); })()} + ); } diff --git a/screen/wallets/transactions.js b/screen/wallets/transactions.js new file mode 100644 index 000000000..e609a4e98 --- /dev/null +++ b/screen/wallets/transactions.js @@ -0,0 +1,516 @@ +import React, { Component } from 'react'; +import { Text, Dimensions, Button, View, Image, FlatList, RefreshControl, TouchableOpacity } from 'react-native'; +import PropTypes from 'prop-types'; +import { LinearGradient } from 'expo'; +import { + WatchOnlyWallet, + HDLegacyBreadwalletWallet, + HDSegwitP2SHWallet, + LightningCustodianWallet, + LegacyWallet, + HDLegacyP2PKHWallet, +} from '../../class'; +import { + BlueText, + BlueTransactionOnchainIcon, + ManageFundsBigButton, + BlueTransactionIncommingIcon, + BlueTransactionOutgoingIcon, + BlueTransactionPendingIcon, + BlueTransactionOffchainIcon, + BlueSendButtonIcon, + BlueReceiveButtonIcon, + BlueList, + BlueListItem, +} from '../../BlueComponents'; +import { Icon } from 'react-native-elements'; +/** @type {AppStorage} */ +let BlueApp = require('../../BlueApp'); +let loc = require('../../loc'); +const BigNumber = require('bignumber.js'); +let EV = require('../../events'); +const { width } = Dimensions.get('window'); + +export default class WalletTransactions extends Component { + static navigationOptions = ({ navigation }) => { + return { + headerRight: ( +