2020-05-28 10:44:15 +02:00
/* global alert */
2018-01-30 23:42:38 +01:00
import React , { Component } from 'react' ;
2020-05-28 10:44:15 +02:00
import {
StatusBar ,
View ,
TouchableOpacity ,
Text ,
StyleSheet ,
InteractionManager ,
Clipboard ,
RefreshControl ,
SectionList ,
Alert ,
Platform ,
} from 'react-native' ;
2020-06-24 05:17:27 +02:00
import { BlueScanButton , WalletsCarousel , BlueHeaderDefaultMain , BlueTransactionListItem , BlueNavigationStyle } from '../../BlueComponents' ;
2018-09-01 01:28:19 +02:00
import { Icon } from 'react-native-elements' ;
2020-05-20 20:04:28 +02:00
import DeeplinkSchemaMatch from '../../class/deeplink-schema-match' ;
2018-12-18 07:05:03 +01:00
import ReactNativeHapticFeedback from 'react-native-haptic-feedback' ;
2018-03-18 03:48:23 +01:00
import PropTypes from 'prop-types' ;
2020-05-28 10:44:15 +02:00
import { AppStorage , PlaceholderWallet } from '../../class' ;
2020-05-24 12:27:08 +02:00
import WalletImport from '../../class/wallet-import' ;
2020-05-28 10:44:15 +02:00
import ActionSheet from '../ActionSheet' ;
import ImagePicker from 'react-native-image-picker' ;
2020-06-19 02:24:26 +02:00
import * as NavigationService from '../../NavigationService' ;
2020-07-20 15:38:46 +02:00
import loc from '../../loc' ;
2020-07-15 19:32:59 +02:00
import { BlueCurrentTheme } from '../../components/themes' ;
2020-07-01 13:56:52 +02:00
const EV = require ( '../../blue_modules/events' ) ;
const A = require ( '../../blue_modules/analytics' ) ;
2020-06-01 14:54:23 +02:00
const BlueApp : AppStorage = require ( '../../BlueApp' ) ;
2020-07-01 13:56:52 +02:00
const BlueElectrum = require ( '../../blue_modules/BlueElectrum' ) ;
2020-05-28 10:44:15 +02:00
const LocalQRCode = require ( '@remobile/react-native-qrcode-local-image' ) ;
2018-01-30 23:42:38 +01:00
2020-05-17 03:41:38 +02:00
const WalletsListSections = { CAROUSEL : 'CAROUSEL' , LOCALTRADER : 'LOCALTRADER' , TRANSACTIONS : 'TRANSACTIONS' } ;
2018-01-30 23:42:38 +01:00
export default class WalletsList extends Component {
2019-12-14 09:02:40 +01:00
walletsCarousel = React . createRef ( ) ;
2018-01-30 23:42:38 +01:00
constructor ( props ) {
super ( props ) ;
this . state = {
isLoading : true ,
2019-02-17 02:22:14 +01:00
isFlatListRefreshControlHidden : true ,
2018-12-11 23:52:46 +01:00
wallets : BlueApp . getWallets ( ) . concat ( false ) ,
2019-12-28 17:22:43 +01:00
timeElpased : 0 ,
2020-05-17 03:41:38 +02:00
dataSource : [ ] ,
2018-03-17 21:39:21 +01:00
} ;
2019-12-14 09:02:40 +01:00
EV ( EV . enum . WALLETS _COUNT _CHANGED , ( ) => this . redrawScreen ( true ) ) ;
2018-10-09 06:25:36 +02:00
// here, when we receive TRANSACTIONS_COUNT_CHANGED we do not query
// remote server, we just redraw the screen
2019-12-14 09:02:40 +01:00
EV ( EV . enum . TRANSACTIONS _COUNT _CHANGED , this . redrawScreen ) ;
2018-01-30 23:42:38 +01:00
}
2018-12-11 23:52:46 +01:00
componentDidMount ( ) {
2020-05-28 10:44:15 +02:00
console . log ( 'wallets/list componentDidMount' ) ;
2019-03-16 13:48:17 +01:00
// the idea is that upon wallet launch we will refresh
// all balances and all transactions here:
2020-05-28 10:44:15 +02:00
this . redrawScreen ( ) ;
2019-03-16 13:48:17 +01:00
InteractionManager . runAfterInteractions ( async ( ) => {
try {
await BlueElectrum . waitTillConnected ( ) ;
2020-06-01 14:54:23 +02:00
const balanceStart = + new Date ( ) ;
2019-03-16 13:48:17 +01:00
await BlueApp . fetchWalletBalances ( ) ;
2020-06-01 14:54:23 +02:00
const balanceEnd = + new Date ( ) ;
2019-03-16 13:48:17 +01:00
console . log ( 'fetch all wallet balances took' , ( balanceEnd - balanceStart ) / 1000 , 'sec' ) ;
2020-06-01 14:54:23 +02:00
const start = + new Date ( ) ;
2019-03-16 13:48:17 +01:00
await BlueApp . fetchWalletTransactions ( ) ;
2020-06-01 14:54:23 +02:00
const end = + new Date ( ) ;
2019-03-16 13:48:17 +01:00
console . log ( 'fetch all wallet txs took' , ( end - start ) / 1000 , 'sec' ) ;
2020-06-15 12:05:11 +02:00
await BlueApp . saveToDisk ( ) ;
2019-12-25 22:06:26 +01:00
} catch ( error ) {
2020-01-21 00:58:33 +01:00
console . log ( error ) ;
2019-03-16 13:48:17 +01:00
}
} ) ;
2020-05-28 10:44:15 +02:00
2019-12-28 17:22:43 +01:00
this . interval = setInterval ( ( ) => {
this . setState ( prev => ( { timeElapsed : prev . timeElapsed + 1 } ) ) ;
} , 60000 ) ;
2020-05-20 20:04:28 +02:00
this . redrawScreen ( ) ;
2020-05-27 13:12:17 +02:00
2020-05-28 10:44:15 +02:00
this . _unsubscribe = this . props . navigation . addListener ( 'focus' , this . onNavigationEventFocus ) ;
2019-12-28 17:22:43 +01:00
}
componentWillUnmount ( ) {
clearInterval ( this . interval ) ;
2020-05-27 13:12:17 +02:00
this . _unsubscribe ( ) ;
2018-10-09 06:25:36 +02:00
}
2018-01-30 23:42:38 +01:00
2018-07-02 13:09:34 +02:00
/ * *
2018-12-25 20:07:43 +01:00
* Forcefully fetches TXs and balance for lastSnappedTo ( i . e . current ) wallet .
* Triggered manually by user on pull - to - refresh .
2018-07-02 13:09:34 +02:00
* /
2020-05-28 10:44:15 +02:00
refreshTransactions = ( ) => {
2018-03-17 21:39:21 +01:00
this . setState (
2018-06-25 00:22:46 +02:00
{
2019-02-23 21:16:18 +01:00
isFlatListRefreshControlHidden : false ,
2018-06-25 00:22:46 +02:00
} ,
2019-02-17 02:22:14 +01:00
( ) => {
InteractionManager . runAfterInteractions ( async ( ) => {
2018-06-25 00:22:46 +02:00
let noErr = true ;
try {
2019-07-13 17:21:03 +02:00
await BlueElectrum . ping ( ) ;
await BlueElectrum . waitTillConnected ( ) ;
2020-06-01 14:54:23 +02:00
const balanceStart = + new Date ( ) ;
2020-05-28 10:44:15 +02:00
await BlueApp . fetchWalletBalances ( this . walletsCarousel . current . currentIndex || 0 ) ;
2020-06-01 14:54:23 +02:00
const balanceEnd = + new Date ( ) ;
2019-01-29 03:27:07 +01:00
console . log ( 'fetch balance took' , ( balanceEnd - balanceStart ) / 1000 , 'sec' ) ;
2020-06-01 14:54:23 +02:00
const start = + new Date ( ) ;
2020-05-28 10:44:15 +02:00
await BlueApp . fetchWalletTransactions ( this . walletsCarousel . current . currentIndex || 0 ) ;
2020-06-01 14:54:23 +02:00
const end = + new Date ( ) ;
2018-10-09 06:25:36 +02:00
console . log ( 'fetch tx took' , ( end - start ) / 1000 , 'sec' ) ;
2018-06-25 00:22:46 +02:00
} catch ( err ) {
noErr = false ;
console . warn ( err ) ;
}
if ( noErr ) await BlueApp . saveToDisk ( ) ; // caching
2019-02-17 02:22:14 +01:00
this . redrawScreen ( ) ;
} ) ;
2018-06-25 00:22:46 +02:00
} ,
) ;
2020-05-28 10:44:15 +02:00
} ;
2018-06-25 00:22:46 +02:00
2019-12-14 09:02:40 +01:00
redrawScreen = ( scrollToEnd = false ) => {
2019-02-17 02:22:14 +01:00
console . log ( 'wallets/list redrawScreen()' ) ;
2020-05-28 10:44:15 +02:00
// here, when we receive REMOTE_TRANSACTIONS_COUNT_CHANGED we fetch TXs and balance for current wallet.
// placing event subscription here so it gets exclusively re-subscribed more often. otherwise we would
// have to unsubscribe on unmount and resubscribe again on mount.
EV ( EV . enum . REMOTE _TRANSACTIONS _COUNT _CHANGED , this . refreshTransactions . bind ( this ) , true ) ;
2019-01-10 16:04:16 +01:00
if ( BlueApp . getBalance ( ) !== 0 ) {
A ( A . ENUM . GOT _NONZERO _BALANCE ) ;
2019-11-29 00:16:04 +01:00
} else {
A ( A . ENUM . GOT _ZERO _BALANCE ) ;
2019-01-10 16:04:16 +01:00
}
2018-07-06 17:41:48 +02:00
2019-12-14 09:02:40 +01:00
const wallets = BlueApp . getWallets ( ) . concat ( false ) ;
if ( scrollToEnd ) {
scrollToEnd = wallets . length > this . state . wallets . length ;
}
this . setState (
{
isLoading : false ,
isFlatListRefreshControlHidden : true ,
dataSource : BlueApp . getTransactions ( null , 10 ) ,
wallets : BlueApp . getWallets ( ) . concat ( false ) ,
} ,
( ) => {
if ( scrollToEnd ) {
2020-05-17 03:41:38 +02:00
this . walletsCarousel . current . snapToItem ( this . state . wallets . length - 2 ) ;
2019-12-14 09:02:40 +01:00
}
} ,
) ;
} ;
2018-06-25 00:22:46 +02:00
txMemo ( hash ) {
2020-06-01 14:54:23 +02:00
if ( BlueApp . tx _metadata [ hash ] && BlueApp . tx _metadata [ hash ] . memo ) {
return BlueApp . tx _metadata [ hash ] . memo ;
2018-06-25 00:22:46 +02:00
}
return '' ;
}
2020-05-17 14:17:08 +02:00
handleClick = index => {
2018-10-09 06:25:36 +02:00
console . log ( 'click' , index ) ;
2020-06-01 14:54:23 +02:00
const wallet = BlueApp . wallets [ index ] ;
2018-06-25 00:22:46 +02:00
if ( wallet ) {
2019-12-27 03:21:07 +01:00
if ( wallet . type === PlaceholderWallet . type ) {
Alert . alert (
2020-07-20 15:38:46 +02:00
loc . wallets . add _details ,
loc . wallets . list _import _problem ,
2019-12-27 03:21:07 +01:00
[
{
2020-07-20 15:38:46 +02:00
text : loc . wallets . details _delete ,
2019-12-27 03:21:07 +01:00
onPress : ( ) => {
WalletImport . removePlaceholderWallet ( ) ;
EV ( EV . enum . WALLETS _COUNT _CHANGED ) ;
} ,
style : 'destructive' ,
} ,
{
2020-07-20 15:38:46 +02:00
text : loc . wallets . list _tryagain ,
2019-12-27 03:21:07 +01:00
onPress : ( ) => {
2020-07-06 18:04:44 +02:00
this . props . navigation . navigate ( 'AddWalletRoot' , { screen : 'ImportWallet' , params : { label : wallet . getSecret ( ) } } ) ;
2019-12-27 03:21:07 +01:00
WalletImport . removePlaceholderWallet ( ) ;
EV ( EV . enum . WALLETS _COUNT _CHANGED ) ;
} ,
style : 'default' ,
} ,
] ,
{ cancelable : false } ,
) ;
} else {
this . props . navigation . navigate ( 'WalletTransactions' , {
wallet : wallet ,
key : ` WalletTransactions- ${ wallet . getID ( ) } ` ,
} ) ;
}
2018-06-25 00:22:46 +02:00
} else {
// if its out of index - this must be last card with incentive to create wallet
2019-12-27 03:21:07 +01:00
if ( ! BlueApp . getWallets ( ) . some ( wallet => wallet . type === PlaceholderWallet . type ) ) {
2020-05-27 13:12:17 +02:00
this . props . navigation . navigate ( 'AddWalletRoot' ) ;
2019-12-27 03:21:07 +01:00
}
2018-06-25 00:22:46 +02:00
}
2020-05-17 14:17:08 +02:00
} ;
2018-06-25 00:22:46 +02:00
2020-05-17 14:17:08 +02:00
onSnapToItem = index => {
2018-06-25 00:22:46 +02:00
console . log ( 'onSnapToItem' , index ) ;
if ( index < BlueApp . getWallets ( ) . length ) {
2018-10-09 06:25:36 +02:00
// not the last
2018-06-25 00:22:46 +02:00
}
2018-07-02 15:51:24 +02:00
2019-12-27 03:21:07 +01:00
if ( this . state . wallets [ index ] . type === PlaceholderWallet . type ) {
return ;
}
2018-07-02 15:51:24 +02:00
// now, lets try to fetch balance and txs for this wallet in case it has changed
this . lazyRefreshWallet ( index ) ;
2020-05-17 14:17:08 +02:00
} ;
2018-07-02 15:51:24 +02:00
/ * *
* Decides whether wallet with such index shoud be refreshed ,
* refreshes if yes and redraws the screen
* @ param index { Integer } Index of the wallet .
* @ return { Promise . < void > }
* /
async lazyRefreshWallet ( index ) {
/** @type {Array.<AbstractWallet>} wallets */
2020-06-01 14:54:23 +02:00
const wallets = BlueApp . getWallets ( ) ;
2018-07-05 02:56:31 +02:00
if ( ! wallets [ index ] ) {
return ;
}
2018-10-09 06:25:36 +02:00
2020-06-01 14:54:23 +02:00
const oldBalance = wallets [ index ] . getBalance ( ) ;
2018-07-02 15:51:24 +02:00
let noErr = true ;
2018-07-14 22:32:36 +02:00
let didRefresh = false ;
2018-07-02 15:51:24 +02:00
try {
2019-12-27 03:21:07 +01:00
if ( wallets && wallets [ index ] && wallets [ index ] . type !== PlaceholderWallet . type && wallets [ index ] . timeToRefreshBalance ( ) ) {
2018-07-02 15:51:24 +02:00
console . log ( 'snapped to, and now its time to refresh wallet #' , index ) ;
await wallets [ index ] . fetchBalance ( ) ;
2018-07-07 15:04:32 +02:00
if ( oldBalance !== wallets [ index ] . getBalance ( ) || wallets [ index ] . getUnconfirmedBalance ( ) !== 0 ) {
2018-07-05 02:56:31 +02:00
console . log ( 'balance changed, thus txs too' ) ;
2018-07-02 15:51:24 +02:00
// balance changed, thus txs too
await wallets [ index ] . fetchTransactions ( ) ;
2019-02-17 02:22:14 +01:00
this . redrawScreen ( ) ;
2018-07-14 22:32:36 +02:00
didRefresh = true ;
} else if ( wallets [ index ] . timeToRefreshTransaction ( ) ) {
2018-09-01 01:28:19 +02:00
console . log ( wallets [ index ] . getLabel ( ) , 'thinks its time to refresh TXs' ) ;
2018-07-14 22:32:36 +02:00
await wallets [ index ] . fetchTransactions ( ) ;
2018-09-01 01:28:19 +02:00
if ( wallets [ index ] . fetchPendingTransactions ) {
await wallets [ index ] . fetchPendingTransactions ( ) ;
}
2018-12-25 20:07:43 +01:00
if ( wallets [ index ] . fetchUserInvoices ) {
await wallets [ index ] . fetchUserInvoices ( ) ;
2019-06-01 22:45:01 +02:00
await wallets [ index ] . fetchBalance ( ) ; // chances are, paid ln invoice was processed during `fetchUserInvoices()` call and altered user's balance, so its worth fetching balance again
2018-12-25 20:07:43 +01:00
}
2019-02-17 02:22:14 +01:00
this . redrawScreen ( ) ;
2018-07-14 22:32:36 +02:00
didRefresh = true ;
2018-07-03 22:11:02 +02:00
} else {
2018-07-05 02:56:31 +02:00
console . log ( 'balance not changed' ) ;
2018-07-02 15:51:24 +02:00
}
}
} catch ( Err ) {
noErr = false ;
console . warn ( Err ) ;
}
2018-07-14 22:32:36 +02:00
if ( noErr && didRefresh ) {
2018-07-02 15:51:24 +02:00
await BlueApp . saveToDisk ( ) ; // caching
}
2018-01-30 23:42:38 +01:00
}
2018-12-11 23:52:46 +01:00
_keyExtractor = ( _item , index ) => index . toString ( ) ;
2018-09-18 09:24:42 +02:00
2018-10-09 06:25:36 +02:00
renderListHeaderComponent = ( ) => {
return (
2020-07-15 19:32:59 +02:00
< View style = { styles . listHeaderBack } >
2020-07-20 15:38:46 +02:00
< Text style = { styles . listHeaderText } > { loc . transactions . list _title } < / T e x t >
2018-10-09 06:25:36 +02:00
< / V i e w >
) ;
} ;
2018-12-11 23:52:46 +01:00
handleLongPress = ( ) => {
2019-12-27 03:21:07 +01:00
if ( BlueApp . getWallets ( ) . length > 1 && ! BlueApp . getWallets ( ) . some ( wallet => wallet . type === PlaceholderWallet . type ) ) {
2018-12-11 23:52:46 +01:00
this . props . navigation . navigate ( 'ReorderWallets' ) ;
2018-12-18 07:05:03 +01:00
} else {
2019-05-03 14:36:11 +02:00
ReactNativeHapticFeedback . trigger ( 'notificationError' , { ignoreAndroidSystemSettings : false } ) ;
2018-12-11 23:52:46 +01:00
}
} ;
2020-05-17 03:41:38 +02:00
renderTransactionListsRow = data => {
2020-03-26 21:15:00 +01:00
return (
2020-05-24 11:17:26 +02:00
< View style = { styles . transaction } >
2020-03-26 21:15:00 +01:00
< BlueTransactionListItem item = { data . item } itemPriceUnit = { data . item . walletPreferredBalanceUnit } / >
< / V i e w >
) ;
2019-02-17 02:22:14 +01:00
} ;
2019-12-28 01:53:34 +01:00
2020-04-15 23:10:24 +02:00
renderLocalTrader = ( ) => {
if ( BlueApp . getWallets ( ) . length > 0 && ! BlueApp . getWallets ( ) . some ( wallet => wallet . type === PlaceholderWallet . type ) ) {
return (
< TouchableOpacity
onPress = { ( ) => {
2020-07-15 19:32:59 +02:00
this . props . navigation . navigate ( 'HodlHodl' , { params : { wallet : this . state . wallet } , screen : 'HodlHodl' } ) ;
2020-04-15 23:10:24 +02:00
} }
2020-05-24 11:17:26 +02:00
style = { styles . ltRoot }
2020-04-15 23:10:24 +02:00
>
2020-05-24 11:17:26 +02:00
< View style = { styles . ltTextWrap } >
< Text style = { styles . ltTextBig } > Local Trader < / T e x t >
2020-07-20 15:38:46 +02:00
< Text style = { styles . ltTextSmall } > { loc . hodl . p2p } < / T e x t >
2020-04-15 23:10:24 +02:00
< / V i e w >
2020-05-24 11:17:26 +02:00
< View style = { styles . ltButtonWrap } >
< Text style = { styles . ltButton } > New < / T e x t >
2020-04-15 23:10:24 +02:00
< / V i e w >
< / T o u c h a b l e O p a c i t y >
) ;
2020-05-17 03:41:38 +02:00
} else {
return null ;
2020-04-15 23:10:24 +02:00
}
} ;
2020-05-17 03:41:38 +02:00
renderWalletsCarousel = ( ) => {
return (
< WalletsCarousel
removeClippedSubviews = { false }
data = { this . state . wallets }
2020-05-17 18:29:56 +02:00
onPress = { this . handleClick }
2020-05-17 03:41:38 +02:00
handleLongPress = { this . handleLongPress }
onSnapToItem = { this . onSnapToItem }
ref = { this . walletsCarousel }
2020-05-21 17:36:46 +02:00
testID = "WalletsList"
2020-05-17 03:41:38 +02:00
/ >
) ;
} ;
renderSectionItem = item => {
switch ( item . section . key ) {
case WalletsListSections . CAROUSEL :
return this . renderWalletsCarousel ( ) ;
case WalletsListSections . LOCALTRADER :
return this . renderLocalTrader ( ) ;
case WalletsListSections . TRANSACTIONS :
return this . renderTransactionListsRow ( item ) ;
default :
return null ;
}
} ;
renderSectionHeader = ( { section } ) => {
switch ( section . key ) {
case WalletsListSections . CAROUSEL :
return (
< BlueHeaderDefaultMain
2020-07-20 15:38:46 +02:00
leftText = { loc . wallets . list _title }
2020-05-17 03:41:38 +02:00
onNewWalletPress = {
! BlueApp . getWallets ( ) . some ( wallet => wallet . type === PlaceholderWallet . type )
2020-05-27 13:12:17 +02:00
? ( ) => this . props . navigation . navigate ( 'AddWalletRoot' )
2020-05-17 03:41:38 +02:00
: null
}
/ >
) ;
case WalletsListSections . TRANSACTIONS :
return this . renderListHeaderComponent ( ) ;
default :
return null ;
2018-01-30 23:42:38 +01:00
}
2020-05-17 03:41:38 +02:00
} ;
2020-05-17 14:17:08 +02:00
renderSectionFooter = ( { section } ) => {
switch ( section . key ) {
case WalletsListSections . TRANSACTIONS :
if ( this . state . dataSource . length === 0 && ! this . state . isLoading ) {
return (
2020-05-24 11:17:26 +02:00
< View style = { styles . footerRoot } >
2020-07-20 15:38:46 +02:00
< Text style = { styles . footerEmpty } > { loc . wallets . list _empty _txs1 } < / T e x t >
< Text style = { styles . footerStart } > { loc . wallets . list _empty _txs2 } < / T e x t >
2020-05-17 14:17:08 +02:00
< / V i e w >
) ;
} else {
return null ;
}
default :
return null ;
}
} ;
2020-05-21 13:24:12 +02:00
renderScanButton = ( ) => {
2020-05-22 02:21:08 +02:00
if ( BlueApp . getWallets ( ) . length > 0 && ! BlueApp . getWallets ( ) . some ( wallet => wallet . type === PlaceholderWallet . type ) ) {
return (
2020-05-24 11:17:26 +02:00
< View style = { styles . scanButton } >
2020-05-28 10:44:15 +02:00
< BlueScanButton onPress = { this . onScanButtonPressed } onLongPress = { this . sendButtonLongPress } / >
2020-05-22 02:21:08 +02:00
< / V i e w >
) ;
} else {
return null ;
}
2020-05-21 13:24:12 +02:00
} ;
2020-05-17 03:41:38 +02:00
sectionListKeyExtractor = ( item , index ) => {
return ` ${ item } ${ index } } ` ;
} ;
2020-05-20 20:04:28 +02:00
onScanButtonPressed = ( ) => {
2020-05-30 07:30:43 +02:00
this . props . navigation . navigate ( 'ScanQRCodeRoot' , {
screen : 'ScanQRCode' ,
params : {
launchedBy : this . props . route . name ,
onBarScanned : this . onBarScanned ,
showFileImportButton : false ,
} ,
2020-05-20 20:04:28 +02:00
} ) ;
} ;
onBarScanned = value => {
DeeplinkSchemaMatch . navigationRouteFor ( { url : value } , completionValue => {
ReactNativeHapticFeedback . trigger ( 'impactLight' , { ignoreAndroidSystemSettings : false } ) ;
2020-06-02 15:25:03 +02:00
this . props . navigation . navigate ( ... completionValue ) ;
2020-05-20 20:04:28 +02:00
} ) ;
} ;
2020-05-28 10:44:15 +02:00
onNavigationEventFocus = ( ) => {
this . redrawScreen ( ) ;
} ;
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 . onBarScanned ( result ) ;
} else {
2020-07-20 15:38:46 +02:00
alert ( loc . send . qr _error _no _qrcode ) ;
2020-05-28 10:44:15 +02:00
}
} ) ;
}
} ,
) ;
} ;
copyFromClipbard = async ( ) => {
this . onBarScanned ( await Clipboard . getString ( ) ) ;
} ;
sendButtonLongPress = async ( ) => {
const isClipboardEmpty = ( await Clipboard . getString ( ) ) . replace ( ' ' , '' ) . length === 0 ;
if ( Platform . OS === 'ios' ) {
2020-07-20 15:38:46 +02:00
const options = [ loc . _ . cancel , loc . wallets . list _long _choose , loc . wallets . list _long _scan ] ;
2020-05-28 10:44:15 +02:00
if ( ! isClipboardEmpty ) {
2020-07-20 15:38:46 +02:00
options . push ( loc . wallets . list _long _clipboard ) ;
2020-05-28 10:44:15 +02:00
}
ActionSheet . showActionSheetWithOptions ( { options , cancelButtonIndex : 0 } , buttonIndex => {
if ( buttonIndex === 1 ) {
this . choosePhoto ( ) ;
} else if ( buttonIndex === 2 ) {
2020-05-30 07:30:43 +02:00
this . props . navigation . navigate ( 'ScanQRCodeRoot' , {
screen : 'ScanQRCode' ,
params : {
launchedBy : this . props . route . name ,
onBarScanned : this . onBarScanned ,
showFileImportButton : false ,
} ,
2020-05-28 10:44:15 +02:00
} ) ;
} else if ( buttonIndex === 3 ) {
this . copyFromClipbard ( ) ;
}
} ) ;
} else if ( Platform . OS === 'android' ) {
2020-06-01 14:54:23 +02:00
const buttons = [
2020-05-28 10:44:15 +02:00
{
2020-07-20 15:38:46 +02:00
text : loc . _ . cancel ,
2020-05-28 10:44:15 +02:00
onPress : ( ) => { } ,
style : 'cancel' ,
} ,
{
2020-07-20 15:38:46 +02:00
text : loc . wallets . list _long _choose ,
2020-05-28 10:44:15 +02:00
onPress : this . choosePhoto ,
} ,
{
2020-07-20 15:38:46 +02:00
text : loc . wallets . list _long _scan ,
2020-05-28 10:44:15 +02:00
onPress : ( ) =>
2020-05-30 07:30:43 +02:00
this . props . navigation . navigate ( 'ScanQRCodeRoot' , {
screen : 'ScanQRCode' ,
params : {
launchedBy : this . props . route . name ,
onBarScanned : this . onBarScanned ,
showFileImportButton : false ,
} ,
2020-05-28 10:44:15 +02:00
} ) ,
} ,
] ;
if ( ! isClipboardEmpty ) {
buttons . push ( {
2020-07-20 15:38:46 +02:00
text : loc . wallets . list _long _clipboard ,
2020-05-28 10:44:15 +02:00
onPress : this . copyFromClipbard ,
} ) ;
}
ActionSheet . showActionSheetWithOptions ( {
title : '' ,
message : '' ,
buttons ,
} ) ;
}
} ;
2020-05-17 03:41:38 +02:00
render ( ) {
2018-01-30 23:42:38 +01:00
return (
2020-05-24 11:17:26 +02:00
< View style = { styles . root } >
2020-07-15 19:32:59 +02:00
< StatusBar barStyle = "default" / >
2020-05-20 20:04:28 +02:00
< View style = { styles . walletsListWrapper } >
< SectionList
2020-05-28 10:44:15 +02:00
refreshControl = { < RefreshControl onRefresh = { this . refreshTransactions } refreshing = { ! this . state . isFlatListRefreshControlHidden } / > }
2020-05-20 20:04:28 +02:00
renderItem = { this . renderSectionItem }
keyExtractor = { this . sectionListKeyExtractor }
renderSectionHeader = { this . renderSectionHeader }
2020-06-11 15:13:58 +02:00
initialNumToRender = { 20 }
2020-05-24 11:17:26 +02:00
contentInset = { styles . scrollContent }
2020-05-20 20:04:28 +02:00
renderSectionFooter = { this . renderSectionFooter }
sections = { [
{ key : WalletsListSections . CAROUSEL , data : [ WalletsListSections . CAROUSEL ] } ,
{ key : WalletsListSections . LOCALTRADER , data : [ WalletsListSections . LOCALTRADER ] } ,
{ key : WalletsListSections . TRANSACTIONS , data : this . state . dataSource } ,
] }
/ >
2020-05-21 13:26:57 +02:00
{ this . renderScanButton ( ) }
2020-05-20 20:04:28 +02:00
< / V i e w >
2020-05-21 13:24:12 +02:00
< / V i e w >
2018-01-30 23:42:38 +01:00
) ;
}
2018-03-17 21:39:21 +01:00
}
2019-12-28 01:53:34 +01:00
2020-07-06 18:04:44 +02:00
const styles = StyleSheet . create ( {
root : {
flex : 1 ,
} ,
scrollContent : {
top : 0 ,
left : 0 ,
bottom : 60 ,
right : 0 ,
} ,
wrapper : {
2020-07-15 19:32:59 +02:00
backgroundColor : BlueCurrentTheme . colors . brandingColor ,
2020-07-06 18:04:44 +02:00
flex : 1 ,
} ,
walletsListWrapper : {
flex : 1 ,
2020-07-15 19:32:59 +02:00
backgroundColor : BlueCurrentTheme . colors . brandingColor ,
2020-07-06 18:04:44 +02:00
} ,
headerStyle : {
... Platform . select ( {
ios : {
marginTop : 44 ,
height : 32 ,
alignItems : 'flex-end' ,
justifyContent : 'center' ,
} ,
android : {
marginTop : 8 ,
height : 44 ,
alignItems : 'flex-end' ,
justifyContent : 'center' ,
} ,
} ) ,
} ,
headerTouch : {
height : 48 ,
paddingRight : 16 ,
paddingLeft : 32 ,
paddingVertical : 10 ,
} ,
2020-07-16 19:41:20 +02:00
listHeaderBack : {
backgroundColor : BlueCurrentTheme . colors . background ,
} ,
2020-07-06 18:04:44 +02:00
listHeaderText : {
paddingLeft : 16 ,
fontWeight : 'bold' ,
fontSize : 24 ,
marginVertical : 8 ,
2020-07-15 19:32:59 +02:00
color : BlueCurrentTheme . colors . foregroundColor ,
2020-07-06 18:04:44 +02:00
} ,
ltRoot : {
flexDirection : 'row' ,
justifyContent : 'space-between' ,
alignItems : 'center' ,
marginHorizontal : 16 ,
marginVertical : 16 ,
2020-07-15 19:32:59 +02:00
backgroundColor : BlueCurrentTheme . colors . ballOutgoingExpired ,
2020-07-06 18:04:44 +02:00
padding : 16 ,
borderRadius : 6 ,
} ,
ltTextWrap : {
flexDirection : 'column' ,
} ,
ltTextBig : {
fontSize : 16 ,
fontWeight : '600' ,
2020-07-15 19:32:59 +02:00
color : BlueCurrentTheme . colors . foregroundColor ,
2020-07-06 18:04:44 +02:00
} ,
ltTextSmall : {
fontSize : 13 ,
fontWeight : '500' ,
2020-07-15 19:32:59 +02:00
color : BlueCurrentTheme . colors . alternativeTextColor ,
2020-07-06 18:04:44 +02:00
} ,
ltButtonWrap : {
flexDirection : 'column' ,
backgroundColor : '#007AFF' ,
borderRadius : 16 ,
} ,
ltButton : {
paddingHorizontal : 16 ,
paddingVertical : 8 ,
fontSize : 13 ,
color : '#fff' ,
fontWeight : '600' ,
} ,
footerRoot : {
top : 80 ,
height : 160 ,
marginBottom : 80 ,
} ,
footerEmpty : {
fontSize : 18 ,
color : '#9aa0aa' ,
textAlign : 'center' ,
} ,
footerStart : {
fontSize : 18 ,
color : '#9aa0aa' ,
textAlign : 'center' ,
fontWeight : '600' ,
} ,
scanButton : {
flexDirection : 'row' ,
alignSelf : 'center' ,
backgroundColor : 'transparent' ,
position : 'absolute' ,
bottom : 30 ,
borderRadius : 30 ,
minHeight : 48 ,
overflow : 'hidden' ,
} ,
listHeader : {
backgroundColor : '#FFFFFF' ,
} ,
transaction : {
marginHorizontal : 4 ,
} ,
} ) ;
2018-03-18 03:48:23 +01:00
WalletsList . propTypes = {
navigation : PropTypes . shape ( {
navigate : PropTypes . func ,
2020-05-27 13:12:17 +02:00
addListener : PropTypes . func ,
} ) ,
route : PropTypes . shape ( {
name : PropTypes . string ,
params : PropTypes . object ,
2018-03-18 03:48:23 +01:00
} ) ,
} ;
2020-07-15 19:32:59 +02:00
WalletsList . navigationOptions = ( { navigation , route } ) => {
return {
... BlueNavigationStyle ( navigation , true ) ,
title : '' ,
headerStyle : {
backgroundColor : BlueCurrentTheme . colors . customHeader ,
borderBottomWidth : 0 ,
elevation : 0 ,
shadowOpacity : 0 ,
shadowOffset : { height : 0 , width : 0 } ,
} ,
headerRight : ( ) => (
< TouchableOpacity testID = "SettingsButton" style = { styles . headerTouch } onPress = { ( ) => NavigationService . navigate ( 'Settings' ) } >
< Icon size = { 22 } name = "kebab-horizontal" type = "octicon" color = { BlueCurrentTheme . colors . foregroundColor } / >
< / T o u c h a b l e O p a c i t y >
) ,
} ;
} ;