REF: move all inline styles to StyleSheet.create

This commit is contained in:
Ivan Vershigora 2020-05-24 12:17:26 +03:00
parent 6a6ac478cc
commit 68e10cd7f1
45 changed files with 2714 additions and 1597 deletions

View file

@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { TouchableOpacity, ActivityIndicator, TextInput, Keyboard, BackHandler, View, Alert, Platform } from 'react-native'; import { TouchableOpacity, ActivityIndicator, TextInput, Keyboard, BackHandler, View, Alert, Platform, StyleSheet } from 'react-native';
import { WebView } from 'react-native-webview'; import { WebView } from 'react-native-webview';
import { BlueNavigationStyle, SafeBlueArea } from '../../BlueComponents'; import { BlueNavigationStyle, SafeBlueArea } from '../../BlueComponents';
import Ionicons from 'react-native-vector-icons/Ionicons'; import Ionicons from 'react-native-vector-icons/Ionicons';
@ -30,9 +30,9 @@ var webln = {
window.ReactNativeWebView.postMessage(JSON.stringify({ sendPayment: paymentRequest })); window.ReactNativeWebView.postMessage(JSON.stringify({ sendPayment: paymentRequest }));
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
/* nop. intentionally, forever hang promise. /* nop. intentionally, forever hang promise.
lapp page usually asynchroniously checks payment itself, via ajax, lapp page usually asynchroniously checks payment itself, via ajax,
so atm there's no need to pass payment preimage from RN to webview and fullfill promise. so atm there's no need to pass payment preimage from RN to webview and fullfill promise.
might change in future */ might change in future */
}); });
}, },
makeInvoice: function(RequestInvoiceArgs) { makeInvoice: function(RequestInvoiceArgs) {
@ -90,51 +90,51 @@ bluewalletResponses = {};
webln = { webln = {
enable : function () { enable : function () {
window.ReactNativeWebView.postMessage(JSON.stringify({'enable': true})); window.ReactNativeWebView.postMessage(JSON.stringify({'enable': true}));
return new Promise(function(resolve, reject){ return new Promise(function(resolve, reject){
resolve(true); resolve(true);
}) })
}, },
getInfo : function () { getInfo : function () {
window.ReactNativeWebView.postMessage('getInfo'); window.ReactNativeWebView.postMessage('getInfo');
return new Promise(function(resolve, reject){ return new Promise(function(resolve, reject){
reject('not implemented'); reject('not implemented');
}) })
}, },
sendPayment: function(paymentRequest) { sendPayment: function(paymentRequest) {
window.ReactNativeWebView.postMessage(JSON.stringify({ sendPayment: paymentRequest })); window.ReactNativeWebView.postMessage(JSON.stringify({ sendPayment: paymentRequest }));
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
/* nop. intentionally, forever hang promise. /* nop. intentionally, forever hang promise.
lapp page usually asynchroniously checks payment itself, via ajax, lapp page usually asynchroniously checks payment itself, via ajax,
so atm there's no need to pass payment preimage from RN to webview and fullfill promise. so atm there's no need to pass payment preimage from RN to webview and fullfill promise.
might change in future */ might change in future */
}); });
}, },
makeInvoice: function (RequestInvoiceArgs) { makeInvoice: function (RequestInvoiceArgs) {
var id = Math.random(); var id = Math.random();
window.ReactNativeWebView.postMessage(JSON.stringify({makeInvoice: RequestInvoiceArgs, id: id})); window.ReactNativeWebView.postMessage(JSON.stringify({makeInvoice: RequestInvoiceArgs, id: id}));
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
var interval = setInterval(function () { var interval = setInterval(function () {
if (bluewalletResponses[id]) { if (bluewalletResponses[id]) {
clearInterval(interval); clearInterval(interval);
resolve(bluewalletResponses[id]); resolve(bluewalletResponses[id]);
} }
}, 1000); }, 1000);
}); });
}, },
signMessage: function () { signMessage: function () {
window.ReactNativeWebView.postMessage('signMessage'); window.ReactNativeWebView.postMessage('signMessage');
return new Promise(function(resolve, reject){ return new Promise(function(resolve, reject){
reject('not implemented'); reject('not implemented');
}) })
}, },
verifyMessage: function () { verifyMessage: function () {
window.ReactNativeWebView.postMessage('verifyMessage'); window.ReactNativeWebView.postMessage('verifyMessage');
return new Promise(function(resolve, reject){ return new Promise(function(resolve, reject){
reject('not implemented'); reject('not implemented');
}) })
}, },
}; };
@ -142,17 +142,17 @@ webln = {
/* listening to events that might come from RN: */ /* listening to events that might come from RN: */
document.addEventListener("message", function(event) { document.addEventListener("message", function(event) {
window.ReactNativeWebView.postMessage("inside webview, received post message: " + event.detail); window.ReactNativeWebView.postMessage("inside webview, received post message: " + event.detail);
var json; var json;
try { try {
json = JSON.parse(event.detail); json = JSON.parse(event.detail);
} catch (_) {} } catch (_) {}
if (json && json.bluewalletResponse) { if (json && json.bluewalletResponse) {
/* this is an answer to one of our inside-webview calls. /* this is an answer to one of our inside-webview calls.
we store it in answers hashmap for someone who cares about it */ we store it in answers hashmap for someone who cares about it */
bluewalletResponses[json.id] = json.bluewalletResponse bluewalletResponses[json.id] = json.bluewalletResponse
} }
}, false); }, false);
@ -160,50 +160,119 @@ document.addEventListener("message", function(event) {
function tryToPay(invoice) { function tryToPay(invoice) {
window.ReactNativeWebView.postMessage(JSON.stringify({sendPayment:invoice})); window.ReactNativeWebView.postMessage(JSON.stringify({sendPayment:invoice}));
} }
/* for non-webln compatible pages we do it oldschool, /* for non-webln compatible pages we do it oldschool,
searching for all bolt11 manually */ searching for all bolt11 manually */
setInterval(function() { setInterval(function() {
window.ReactNativeWebView.postMessage('interval'); window.ReactNativeWebView.postMessage('interval');
var searchText = "lnbc"; var searchText = "lnbc";
var aTags = document.getElementsByTagName("span"); var aTags = document.getElementsByTagName("span");
var i; var i;
for (i = 0; i < aTags.length; i++) { for (i = 0; i < aTags.length; i++) {
if (aTags[i].textContent.indexOf(searchText) === 0) { if (aTags[i].textContent.indexOf(searchText) === 0) {
tryToPay(aTags[i].textContent); tryToPay(aTags[i].textContent);
} }
} }
/* ------------------------- */ /* ------------------------- */
aTags = document.getElementsByTagName("input"); aTags = document.getElementsByTagName("input");
for (i = 0; i < aTags.length; i++) { for (i = 0; i < aTags.length; i++) {
if (aTags[i].value.indexOf(searchText) === 0) { if (aTags[i].value.indexOf(searchText) === 0) {
tryToPay(aTags[i].value); tryToPay(aTags[i].value);
} }
} }
/* ------------------------- */ /* ------------------------- */
aTags = document.getElementsByTagName("a"); aTags = document.getElementsByTagName("a");
searchText = "lightning:lnbc"; searchText = "lightning:lnbc";
for (i = 0; i < aTags.length; i++) { for (i = 0; i < aTags.length; i++) {
var href = aTags[i].getAttribute('href') + ''; var href = aTags[i].getAttribute('href') + '';
if (href.indexOf(searchText) === 0) { if (href.indexOf(searchText) === 0) {
tryToPay(href.replace('lightning:', '')); tryToPay(href.replace('lightning:', ''));
} }
} }
}, 1000); }, 1000);
`; `;
const styles = StyleSheet.create({
safeRoot: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
minHeight: 44,
},
safeBack: {
marginHorizontal: 8,
},
safeURL: {
flex: 1,
marginHorizontal: 8,
alignItems: 'center',
justifyContent: 'center',
},
safeURLTextWrap: {
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
},
safeURLText: {
flex: 1,
marginLeft: 4,
minHeight: 33,
},
safeURLHome: {
alignContent: 'flex-end',
height: 44,
flexDirection: 'row',
marginHorizontal: 8,
},
sync: {
color: 'red',
backgroundColor: 'transparent',
paddingLeft: 15,
},
activity: {
flex: 1,
justifyContent: 'center',
paddingLeft: 20,
alignContent: 'center',
},
goBack: {
backgroundColor: 'transparent',
paddingLeft: 10,
},
colorRed: {
color: 'red',
},
colorGray: {
color: 'gray',
},
transparent: {
backgroundColor: 'transparent',
},
colorGreen: {
color: 'green',
},
});
export default class Browser extends Component { export default class Browser extends Component {
static navigationOptions = ({ navigation }) => ({ static navigationOptions = ({ navigation }) => ({
@ -353,46 +422,28 @@ export default class Browser extends Component {
render() { render() {
return ( return (
<SafeBlueArea> <SafeBlueArea>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', minHeight: 44 }}> <View style={styles.safeRoot}>
<TouchableOpacity <TouchableOpacity
disabled={!this.state.canGoBack} disabled={!this.state.canGoBack}
onPress={() => { onPress={() => {
this.webview.goBack(); this.webview.goBack();
}} }}
style={{ marginHorizontal: 8 }} style={styles.safeBack}
> >
<Ionicons <Ionicons
name={'ios-arrow-round-back'} name="ios-arrow-round-back"
size={36} size={36}
style={{ style={[styles.goBack, this.state.canGoBack ? styles.colorRed : styles.colorGray]}
color: this.state.canGoBack ? 'red' : 'gray',
backgroundColor: 'transparent',
paddingLeft: 10,
}}
/> />
</TouchableOpacity> </TouchableOpacity>
<View style={{ flex: 1, marginHorizontal: 8, alignItems: 'center', justifyContent: 'center' }}> <View style={styles.safeURL}>
<View <View style={styles.safeURLTextWrap}>
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
}}
>
<TextInput <TextInput
onChangeText={text => this.setState({ stateURL: text })} onChangeText={text => this.setState({ stateURL: text })}
value={this.state.stateURL} value={this.state.stateURL}
numberOfLines={1} numberOfLines={1}
style={{ flex: 1, marginLeft: 4, minHeight: 33 }} style={styles.safeURLText}
editable editable
onSubmitEditing={() => { onSubmitEditing={() => {
Keyboard.dismiss(); Keyboard.dismiss();
@ -405,7 +456,7 @@ export default class Browser extends Component {
/> />
</View> </View>
</View> </View>
<View style={{ alignContent: 'flex-end', height: 44, flexDirection: 'row', marginHorizontal: 8 }}> <View style={styles.safeURLHome}>
{Platform.OS !== 'ios' && ( // on iOS lappbrowser opens blank page, thus, no HOME button {Platform.OS !== 'ios' && ( // on iOS lappbrowser opens blank page, thus, no HOME button
<TouchableOpacity <TouchableOpacity
onPress={() => { onPress={() => {
@ -414,12 +465,9 @@ export default class Browser extends Component {
}} }}
> >
<Ionicons <Ionicons
name={'ios-home'} name="ios-home"
size={36} size={36}
style={{ style={[styles.transparent, this.state.weblnEnabled ? styles.colorGreen : styles.colorRed]}
color: this.state.weblnEnabled ? 'green' : 'red',
backgroundColor: 'transparent',
}}
/> />
</TouchableOpacity> </TouchableOpacity>
)} )}
@ -434,17 +482,9 @@ export default class Browser extends Component {
}} }}
> >
{!this.state.pageIsLoading ? ( {!this.state.pageIsLoading ? (
<Ionicons <Ionicons name="ios-sync" size={36} style={styles.sync} />
name={'ios-sync'}
size={36}
style={{
color: 'red',
backgroundColor: 'transparent',
paddingLeft: 15,
}}
/>
) : ( ) : (
<View style={{ flex: 1, justifyContent: 'center', paddingLeft: 20, alignContent: 'center' }}> <View style={styles.activity}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
)} )}

View file

@ -9,6 +9,7 @@ import {
TouchableWithoutFeedback, TouchableWithoutFeedback,
TouchableOpacity, TouchableOpacity,
Text, Text,
StyleSheet,
} from 'react-native'; } from 'react-native';
import { import {
BlueNavigationStyle, BlueNavigationStyle,
@ -28,6 +29,103 @@ let BlueApp = require('../../BlueApp');
let EV = require('../../events'); let EV = require('../../events');
let loc = require('../../loc'); let loc = require('../../loc');
const styles = StyleSheet.create({
createButton: {
marginHorizontal: 56,
marginVertical: 16,
minHeight: 45,
alignContent: 'center',
backgroundColor: '#FFFFFF',
},
scanRoot: {
height: 36,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#9AA0AA',
borderRadius: 4,
paddingVertical: 4,
paddingHorizontal: 8,
marginHorizontal: 4,
},
scanClick: {
marginLeft: 4,
color: BlueApp.settings.inverseForegroundColor,
},
walletRoot: {
marginBottom: 16,
alignItems: 'center',
justifyContent: 'center',
},
walletChooseWrap: {
flexDirection: 'row',
alignItems: 'center',
},
walletChooseText: {
color: '#9aa0aa',
fontSize: 14,
marginRight: 8,
},
walletNameWrap: {
flexDirection: 'row',
alignItems: 'center',
marginVertical: 4,
},
walletNameTouch: {
flexDirection: 'row',
alignItems: 'center',
},
walletNameText: {
color: '#0c2550',
fontSize: 14,
},
walletNameBalance: {
color: '#0c2550',
fontSize: 14,
fontWeight: '600',
marginLeft: 8,
marginRight: 4,
},
walletNameSats: {
color: '#0c2550',
fontSize: 11,
fontWeight: '600',
textAlignVertical: 'bottom',
marginTop: 2,
},
error: {
flex: 1,
paddingTop: 20,
},
root: {
flex: 1,
justifyContent: 'space-between',
},
amount: {
flex: 1,
backgroundColor: '#FFFFFF',
},
fiat: {
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
},
fiat2: {
flex: 1,
marginHorizontal: 8,
minHeight: 33,
},
});
export default class LNDCreateInvoice extends Component { export default class LNDCreateInvoice extends Component {
static navigationOptions = ({ navigation }) => ({ static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true), ...BlueNavigationStyle(navigation, true),
@ -194,7 +292,7 @@ export default class LNDCreateInvoice extends Component {
renderCreateButton = () => { renderCreateButton = () => {
return ( return (
<View style={{ marginHorizontal: 56, marginVertical: 16, minHeight: 45, alignContent: 'center', backgroundColor: '#FFFFFF' }}> <View style={styles.createButton}>
{this.state.isLoading ? ( {this.state.isLoading ? (
<ActivityIndicator /> <ActivityIndicator />
) : ( ) : (
@ -215,20 +313,10 @@ export default class LNDCreateInvoice extends Component {
}); });
Keyboard.dismiss(); Keyboard.dismiss();
}} }}
style={{ style={styles.scanRoot}
height: 36,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#9AA0AA',
borderRadius: 4,
paddingVertical: 4,
paddingHorizontal: 8,
marginHorizontal: 4,
}}
> >
<Icon name="qrcode" size={22} type="font-awesome" color={BlueApp.settings.inverseForegroundColor} /> <Icon name="qrcode" size={22} type="font-awesome" color={BlueApp.settings.inverseForegroundColor} />
<Text style={{ marginLeft: 4, color: BlueApp.settings.inverseForegroundColor }}>{loc.send.details.scan}</Text> <Text style={styles.scanClick}>{loc.send.details.scan}</Text>
</TouchableOpacity> </TouchableOpacity>
); );
}; };
@ -236,32 +324,30 @@ export default class LNDCreateInvoice extends Component {
renderWalletSelectionButton = () => { renderWalletSelectionButton = () => {
if (this.state.renderWalletSelectionButtonHidden) return; if (this.state.renderWalletSelectionButtonHidden) return;
return ( return (
<View style={{ marginBottom: 16, alignItems: 'center', justifyContent: 'center' }}> <View style={styles.walletRoot}>
{!this.state.isLoading && ( {!this.state.isLoading && (
<TouchableOpacity <TouchableOpacity
style={{ flexDirection: 'row', alignItems: 'center' }} style={styles.walletChooseWrap}
onPress={() => onPress={() =>
this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.OFFCHAIN }) this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.OFFCHAIN })
} }
> >
<Text style={{ color: '#9aa0aa', fontSize: 14, marginRight: 8 }}>{loc.wallets.select_wallet.toLowerCase()}</Text> <Text style={styles.walletChooseText}>{loc.wallets.select_wallet.toLowerCase()}</Text>
<Icon name="angle-right" size={18} type="font-awesome" color="#9aa0aa" /> <Icon name="angle-right" size={18} type="font-awesome" color="#9aa0aa" />
</TouchableOpacity> </TouchableOpacity>
)} )}
<View style={{ flexDirection: 'row', alignItems: 'center', marginVertical: 4 }}> <View style={styles.walletNameWrap}>
<TouchableOpacity <TouchableOpacity
style={{ flexDirection: 'row', alignItems: 'center' }} style={styles.walletNameTouch}
onPress={() => onPress={() =>
this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.OFFCHAIN }) this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.OFFCHAIN })
} }
> >
<Text style={{ color: '#0c2550', fontSize: 14 }}>{this.state.fromWallet.getLabel()}</Text> <Text style={styles.walletNameText}>{this.state.fromWallet.getLabel()}</Text>
<Text style={{ color: '#0c2550', fontSize: 14, fontWeight: '600', marginLeft: 8, marginRight: 4 }}> <Text style={styles.walletNameBalance}>
{loc.formatBalanceWithoutSuffix(this.state.fromWallet.getBalance(), BitcoinUnit.SATS, false)} {loc.formatBalanceWithoutSuffix(this.state.fromWallet.getBalance(), BitcoinUnit.SATS, false)}
</Text> </Text>
<Text style={{ color: '#0c2550', fontSize: 11, fontWeight: '600', textAlignVertical: 'bottom', marginTop: 2 }}> <Text style={styles.walletNameSats}>{BitcoinUnit.SATS}</Text>
{BitcoinUnit.SATS}
</Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</View> </View>
@ -275,7 +361,7 @@ export default class LNDCreateInvoice extends Component {
render() { render() {
if (!this.state.fromWallet) { if (!this.state.fromWallet) {
return ( return (
<View style={{ flex: 1, paddingTop: 20 }}> <View style={styles.error}>
<Text>System error: Source wallet not found (this should never happen)</Text> <Text>System error: Source wallet not found (this should never happen)</Text>
</View> </View>
); );
@ -283,8 +369,8 @@ export default class LNDCreateInvoice extends Component {
return ( return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}> <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View style={{ flex: 1, justifyContent: 'space-between' }}> <View style={styles.root}>
<View style={{ flex: 1, backgroundColor: '#FFFFFF' }}> <View style={styles.amount}>
<KeyboardAvoidingView behavior="position"> <KeyboardAvoidingView behavior="position">
<BlueBitcoinAmount <BlueBitcoinAmount
isLoading={this.state.isLoading} isLoading={this.state.isLoading}
@ -307,28 +393,13 @@ export default class LNDCreateInvoice extends Component {
unit={BitcoinUnit.SATS} unit={BitcoinUnit.SATS}
inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID} inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}
/> />
<View <View style={styles.fiat}>
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
}}
>
<TextInput <TextInput
onChangeText={text => this.setState({ description: text })} onChangeText={text => this.setState({ description: text })}
placeholder={loc.receive.details.label} placeholder={loc.receive.details.label}
value={this.state.description} value={this.state.description}
numberOfLines={1} numberOfLines={1}
style={{ flex: 1, marginHorizontal: 8, minHeight: 33 }} style={styles.fiat2}
editable={!this.state.isLoading} editable={!this.state.isLoading}
onSubmitEditing={Keyboard.dismiss} onSubmitEditing={Keyboard.dismiss}
inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID} inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}

View file

@ -1,6 +1,6 @@
/* global alert */ /* global alert */
import React, { Component } from 'react'; import React, { Component } from 'react';
import { View, Share } from 'react-native'; import { View, Share, StyleSheet } from 'react-native';
import { import {
BlueLoading, BlueLoading,
BlueCopyTextToClipboard, BlueCopyTextToClipboard,
@ -16,6 +16,31 @@ import QRCode from 'react-native-qrcode-svg';
let BlueApp = require('../../BlueApp'); let BlueApp = require('../../BlueApp');
const loc = require('../../loc'); const loc = require('../../loc');
const styles = StyleSheet.create({
loading: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
root: {
flex: 1,
},
wrapper: {
flex: 1,
justifyContent: 'space-between',
alignItems: 'center',
},
qrcode: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 16,
},
share: {
marginBottom: 25,
},
});
export default class LNDViewAdditionalInvoiceInformation extends Component { export default class LNDViewAdditionalInvoiceInformation extends Component {
static navigationOptions = ({ navigation }) => ({ static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(), ...BlueNavigationStyle(),
@ -38,16 +63,16 @@ export default class LNDViewAdditionalInvoiceInformation extends Component {
render() { render() {
if (typeof this.state.walletInfo === 'undefined') { if (typeof this.state.walletInfo === 'undefined') {
return ( return (
<SafeBlueArea style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <SafeBlueArea style={styles.loading}>
<BlueLoading /> <BlueLoading />
</SafeBlueArea> </SafeBlueArea>
); );
} }
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<View style={{ flex: 1, justifyContent: 'space-between', alignItems: 'center' }}> <View style={styles.wrapper}>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', paddingHorizontal: 16 }}> <View style={styles.qrcode}>
<QRCode <QRCode
value={this.state.walletInfo.uris[0]} value={this.state.walletInfo.uris[0]}
logo={require('../../img/qr-code.png')} logo={require('../../img/qr-code.png')}
@ -60,7 +85,7 @@ export default class LNDViewAdditionalInvoiceInformation extends Component {
<BlueText>{loc.lndViewInvoice.open_direct_channel}</BlueText> <BlueText>{loc.lndViewInvoice.open_direct_channel}</BlueText>
<BlueCopyTextToClipboard text={this.state.walletInfo.uris[0]} /> <BlueCopyTextToClipboard text={this.state.walletInfo.uris[0]} />
</View> </View>
<View style={{ marginBottom: 25 }}> <View style={styles.share}>
<BlueButton <BlueButton
icon={{ icon={{
name: 'share-alternative', name: 'share-alternative',

View file

@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { View, Text, Dimensions, ScrollView, BackHandler, InteractionManager, TouchableOpacity } from 'react-native'; import { View, Text, Dimensions, ScrollView, BackHandler, InteractionManager, TouchableOpacity, StyleSheet } from 'react-native';
import Share from 'react-native-share'; import Share from 'react-native-share';
import { import {
BlueLoading, BlueLoading,
@ -21,6 +21,97 @@ const loc = require('../../loc');
const EV = require('../../events'); const EV = require('../../events');
const { width, height } = Dimensions.get('window'); const { width, height } = Dimensions.get('window');
const styles = StyleSheet.create({
root: {
flex: 1,
},
center: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
valueRoot: {
flex: 2,
flexDirection: 'column',
justifyContent: 'center',
},
valueAmount: {
flexDirection: 'row',
justifyContent: 'center',
paddingBottom: 8,
},
valueText: {
color: '#0f5cc0',
fontSize: 32,
fontWeight: '600',
},
valueSats: {
color: '#0f5cc0',
fontSize: 16,
marginHorizontal: 4,
paddingBottom: 3,
fontWeight: '600',
alignSelf: 'flex-end',
},
memo: {
color: '#9aa0aa',
fontSize: 14,
marginHorizontal: 4,
paddingBottom: 6,
fontWeight: '400',
alignSelf: 'center',
},
paid: {
flex: 3,
alignItems: 'center',
justifyContent: 'center',
},
paidMark: {
marginTop: -100,
marginBottom: 16,
},
detailsRoot: {
flex: 1,
justifyContent: 'flex-end',
marginBottom: 24,
alignItems: 'center',
},
detailsTouch: {
flexDirection: 'row',
alignItems: 'center',
},
detailsText: {
color: '#9aa0aa',
fontSize: 14,
marginRight: 8,
},
expired: {
backgroundColor: '#ccddf9',
width: 120,
height: 120,
borderRadius: 60,
alignSelf: 'center',
justifyContent: 'center',
marginTop: -100,
marginBottom: 30,
},
activeRoot: {
flex: 1,
alignItems: 'center',
marginTop: 8,
justifyContent: 'space-between',
},
activeQrcode: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingHorizontal: 16,
},
additionalInfo: {
backgroundColor: BlueApp.settings.brandingColor,
},
});
export default class LNDViewInvoice extends Component { export default class LNDViewInvoice extends Component {
static navigationOptions = ({ navigation }) => static navigationOptions = ({ navigation }) =>
navigation.getParam('isModal') === true navigation.getParam('isModal') === true
@ -120,8 +211,8 @@ export default class LNDViewInvoice extends Component {
if (this.state.showPreimageQr) { if (this.state.showPreimageQr) {
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <View style={styles.center}>
<BlueText>Preimage:</BlueText> <BlueText>Preimage:</BlueText>
<BlueSpacing20 /> <BlueSpacing20 />
<QRCode <QRCode
@ -144,62 +235,31 @@ export default class LNDViewInvoice extends Component {
if (invoice.ispaid || invoice.type === 'paid_invoice') { if (invoice.ispaid || invoice.type === 'paid_invoice') {
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<View style={{ flex: 2, flexDirection: 'column', justifyContent: 'center' }}> <View style={styles.valueRoot}>
{invoice.type === 'paid_invoice' && invoice.value && ( {invoice.type === 'paid_invoice' && invoice.value && (
<View style={{ flexDirection: 'row', justifyContent: 'center', paddingBottom: 8 }}> <View style={styles.valueAmount}>
<Text style={{ color: '#0f5cc0', fontSize: 32, fontWeight: '600' }}>{invoice.value}</Text> <Text style={styles.valueText}>{invoice.value}</Text>
<Text <Text style={styles.valueSats}>{loc.lndViewInvoice.sats}</Text>
style={{
color: '#0f5cc0',
fontSize: 16,
marginHorizontal: 4,
paddingBottom: 3,
fontWeight: '600',
alignSelf: 'flex-end',
}}
>
{loc.lndViewInvoice.sats}
</Text>
</View> </View>
)} )}
{invoice.type === 'user_invoice' && invoice.amt && ( {invoice.type === 'user_invoice' && invoice.amt && (
<View style={{ flexDirection: 'row', justifyContent: 'center', paddingBottom: 8 }}> <View style={styles.valueAmount}>
<Text style={{ color: '#0f5cc0', fontSize: 32, fontWeight: '600' }}>{invoice.amt}</Text> <Text style={styles.valueText}>{invoice.amt}</Text>
<Text <Text style={styles.valueSats}>{loc.lndViewInvoice.sats}</Text>
style={{
color: '#0f5cc0',
fontSize: 16,
marginHorizontal: 4,
paddingBottom: 3,
fontWeight: '600',
alignSelf: 'flex-end',
}}
>
{loc.lndViewInvoice.sats}
</Text>
</View> </View>
)} )}
{!invoice.ispaid && invoice.memo && invoice.memo.length > 0 && ( {!invoice.ispaid && invoice.memo && invoice.memo.length > 0 && <Text style={styles.memo}>{invoice.memo}</Text>}
<Text
style={{ color: '#9aa0aa', fontSize: 14, marginHorizontal: 4, paddingBottom: 6, fontWeight: '400', alignSelf: 'center' }}
>
{invoice.memo}
</Text>
)}
</View> </View>
<View style={{ flex: 3, alignItems: 'center', justifyContent: 'center' }}> <View style={styles.paid}>
<BlueBigCheckmark style={{ marginTop: -100, marginBottom: 16 }} /> <BlueBigCheckmark style={styles.paidMark} />
<BlueText>{loc.lndViewInvoice.has_been_paid}</BlueText> <BlueText>{loc.lndViewInvoice.has_been_paid}</BlueText>
</View> </View>
<View style={{ flex: 1, justifyContent: 'flex-end', marginBottom: 24, alignItems: 'center' }}> <View style={styles.detailsRoot}>
{invoice.payment_preimage && typeof invoice.payment_preimage === 'string' ? ( {invoice.payment_preimage && typeof invoice.payment_preimage === 'string' ? (
<TouchableOpacity <TouchableOpacity style={styles.detailsTouch} onPress={() => this.setState({ showPreimageQr: true })}>
style={{ flexDirection: 'row', alignItems: 'center' }} <Text style={styles.detailsText}>{loc.send.create.details}</Text>
onPress={() => this.setState({ showPreimageQr: true })}
>
<Text style={{ color: '#9aa0aa', fontSize: 14, marginRight: 8 }}>{loc.send.create.details}</Text>
<Icon name="angle-right" size={18} type="font-awesome" color="#9aa0aa" /> <Icon name="angle-right" size={18} type="font-awesome" color="#9aa0aa" />
</TouchableOpacity> </TouchableOpacity>
) : ( ) : (
@ -211,20 +271,9 @@ export default class LNDViewInvoice extends Component {
} }
if (invoiceExpiration < now && !invoice.ispaid) { if (invoiceExpiration < now && !invoice.ispaid) {
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <View style={styles.center}>
<View <View style={styles.expired}>
style={{
backgroundColor: '#ccddf9',
width: 120,
height: 120,
borderRadius: 60,
alignSelf: 'center',
justifyContent: 'center',
marginTop: -100,
marginBottom: 30,
}}
>
<Icon name="times" size={50} type="font-awesome" color="#0f5cc0" /> <Icon name="times" size={50} type="font-awesome" color="#0f5cc0" />
</View> </View>
<BlueText>{loc.lndViewInvoice.wasnt_paid_and_expired}</BlueText> <BlueText>{loc.lndViewInvoice.wasnt_paid_and_expired}</BlueText>
@ -234,8 +283,8 @@ export default class LNDViewInvoice extends Component {
} else if (invoiceExpiration > now && invoice.ispaid) { } else if (invoiceExpiration > now && invoice.ispaid) {
if (invoice.ispaid) { if (invoice.ispaid) {
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <View style={styles.center}>
<BlueText>{loc.lndViewInvoice.has_been_paid}</BlueText> <BlueText>{loc.lndViewInvoice.has_been_paid}</BlueText>
</View> </View>
</SafeBlueArea> </SafeBlueArea>
@ -247,16 +296,8 @@ export default class LNDViewInvoice extends Component {
return ( return (
<SafeBlueArea> <SafeBlueArea>
<ScrollView> <ScrollView>
<View <View style={styles.activeRoot} onLayout={this.onLayout}>
style={{ <View style={styles.activeQrcode}>
flex: 1,
alignItems: 'center',
marginTop: 8,
justifyContent: 'space-between',
}}
onLayout={this.onLayout}
>
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', paddingHorizontal: 16 }}>
<QRCode <QRCode
value={typeof this.state.invoice === 'object' ? invoice.payment_request : invoice} value={typeof this.state.invoice === 'object' ? invoice.payment_request : invoice}
logo={require('../../img/qr-code.png')} logo={require('../../img/qr-code.png')}
@ -305,9 +346,7 @@ export default class LNDViewInvoice extends Component {
/> />
<BlueSpacing20 /> <BlueSpacing20 />
<BlueButton <BlueButton
style={{ style={styles.additionalInfo}
backgroundColor: BlueApp.settings.brandingColor,
}}
onPress={() => this.props.navigation.navigate('LNDViewAdditionalInvoiceInformation', { fromWallet: this.state.fromWallet })} onPress={() => this.props.navigation.navigate('LNDViewAdditionalInvoiceInformation', { fromWallet: this.state.fromWallet })}
title={loc.lndViewInvoice.additional_info} title={loc.lndViewInvoice.additional_info}
/> />

View file

@ -1,6 +1,6 @@
/* global alert */ /* global alert */
import React from 'react'; import React from 'react';
import { Text, ActivityIndicator, KeyboardAvoidingView, View, TouchableOpacity, Keyboard, ScrollView } from 'react-native'; import { Text, ActivityIndicator, KeyboardAvoidingView, View, TouchableOpacity, Keyboard, ScrollView, StyleSheet } from 'react-native';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import {
BlueButton, BlueButton,
@ -22,6 +22,78 @@ let BlueApp = require('../../BlueApp');
let EV = require('../../events'); let EV = require('../../events');
const loc = require('../../loc'); const loc = require('../../loc');
const styles = StyleSheet.create({
walletSelectRoot: {
marginBottom: 16,
alignItems: 'center',
justifyContent: 'flex-end',
},
walletSelectTouch: {
flexDirection: 'row',
alignItems: 'center',
},
walletSelectText: {
color: '#9aa0aa',
fontSize: 14,
marginRight: 8,
},
walletWrap: {
flexDirection: 'row',
alignItems: 'center',
marginVertical: 4,
},
walletWrapTouch: {
flexDirection: 'row',
alignItems: 'center',
},
walletWrapLabel: {
color: '#0c2550',
fontSize: 14,
},
walletWrapBalance: {
color: '#0c2550',
fontSize: 14,
fontWeight: '600',
marginLeft: 4,
marginRight: 4,
},
walletWrapSats: {
color: '#0c2550',
fontSize: 11,
fontWeight: '600',
textAlignVertical: 'bottom',
marginTop: 2,
},
root: {
flex: 1,
},
scroll: {
flex: 1,
justifyContent: 'space-between',
},
scrollMargin: {
marginTop: 60,
},
description: {
flexDirection: 'row',
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 0,
borderRadius: 4,
},
descriptionText: {
color: '#81868e',
fontWeight: '500',
fontSize: 14,
},
expiresIn: {
color: '#81868e',
fontSize: 12,
left: 20,
top: 10,
},
});
export default class ScanLndInvoice extends React.Component { export default class ScanLndInvoice extends React.Component {
static navigationOptions = ({ navigation }) => ({ static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true), ...BlueNavigationStyle(navigation, true),
@ -213,32 +285,30 @@ export default class ScanLndInvoice extends React.Component {
renderWalletSelectionButton = () => { renderWalletSelectionButton = () => {
if (this.state.renderWalletSelectionButtonHidden) return; if (this.state.renderWalletSelectionButtonHidden) return;
return ( return (
<View style={{ marginBottom: 16, alignItems: 'center', justifyContent: 'flex-end' }}> <View style={styles.walletSelectRoot}>
{!this.state.isLoading && ( {!this.state.isLoading && (
<TouchableOpacity <TouchableOpacity
style={{ flexDirection: 'row', alignItems: 'center' }} style={styles.walletSelectTouch}
onPress={() => onPress={() =>
this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.OFFCHAIN }) this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.OFFCHAIN })
} }
> >
<Text style={{ color: '#9aa0aa', fontSize: 14, marginRight: 8 }}>{loc.wallets.select_wallet.toLowerCase()}</Text> <Text style={styles.walletSelectText}>{loc.wallets.select_wallet.toLowerCase()}</Text>
<Icon name="angle-right" size={18} type="font-awesome" color="#9aa0aa" /> <Icon name="angle-right" size={18} type="font-awesome" color="#9aa0aa" />
</TouchableOpacity> </TouchableOpacity>
)} )}
<View style={{ flexDirection: 'row', alignItems: 'center', marginVertical: 4 }}> <View style={styles.walletWrap}>
<TouchableOpacity <TouchableOpacity
style={{ flexDirection: 'row', alignItems: 'center' }} style={styles.walletWrapTouch}
onPress={() => onPress={() =>
this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.OFFCHAIN }) this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.OFFCHAIN })
} }
> >
<Text style={{ color: '#0c2550', fontSize: 14 }}>{this.state.fromWallet.getLabel()}</Text> <Text style={styles.walletWrapLabel}>{this.state.fromWallet.getLabel()}</Text>
<Text style={{ color: '#0c2550', fontSize: 14, fontWeight: '600', marginLeft: 4, marginRight: 4 }}> <Text style={styles.walletWrapBalance}>
{loc.formatBalanceWithoutSuffix(this.state.fromWallet.getBalance(), BitcoinUnit.SATS, false)} {loc.formatBalanceWithoutSuffix(this.state.fromWallet.getBalance(), BitcoinUnit.SATS, false)}
</Text> </Text>
<Text style={{ color: '#0c2550', fontSize: 11, fontWeight: '600', textAlignVertical: 'bottom', marginTop: 2 }}> <Text style={styles.walletWrapSats}>{BitcoinUnit.SATS}</Text>
{BitcoinUnit.SATS}
</Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</View> </View>
@ -256,11 +326,11 @@ export default class ScanLndInvoice extends React.Component {
return <BlueLoading />; return <BlueLoading />;
} }
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<View style={{ flex: 1 }}> <View style={styles.root}>
<ScrollView contentContainerStyle={{ flex: 1, justifyContent: 'space-between' }}> <ScrollView contentContainerStyle={styles.scroll}>
<KeyboardAvoidingView enabled behavior="position" keyboardVerticalOffset={20}> <KeyboardAvoidingView enabled behavior="position" keyboardVerticalOffset={20}>
<View style={{ marginTop: 60 }}> <View style={styles.scrollMargin}>
<BlueBitcoinAmount <BlueBitcoinAmount
pointerEvents={this.state.isAmountInitiallyEmpty ? 'auto' : 'none'} pointerEvents={this.state.isAmountInitiallyEmpty ? 'auto' : 'none'}
isLoading={this.state.isLoading} isLoading={this.state.isLoading}
@ -292,22 +362,12 @@ export default class ScanLndInvoice extends React.Component {
inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID} inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}
launchedBy={this.props.navigation.state.routeName} launchedBy={this.props.navigation.state.routeName}
/> />
<View <View style={styles.description}>
style={{ <Text numberOfLines={0} style={styles.descriptionText}>
flexDirection: 'row',
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 0,
borderRadius: 4,
}}
>
<Text numberOfLines={0} style={{ color: '#81868e', fontWeight: '500', fontSize: 14 }}>
{this.state.hasOwnProperty('decoded') && this.state.decoded !== undefined ? this.state.decoded.description : ''} {this.state.hasOwnProperty('decoded') && this.state.decoded !== undefined ? this.state.decoded.description : ''}
</Text> </Text>
</View> </View>
{this.state.expiresIn !== undefined && ( {this.state.expiresIn !== undefined && <Text style={styles.expiresIn}>Expires in: {this.state.expiresIn}</Text>}
<Text style={{ color: '#81868e', fontSize: 12, left: 20, top: 10 }}>Expires in: {this.state.expiresIn}</Text>
)}
<BlueCard> <BlueCard>
{this.state.isLoading ? ( {this.state.isLoading ? (

View file

@ -1,6 +1,6 @@
/* global alert */ /* global alert */
import React, { Component } from 'react'; import React, { Component } from 'react';
import { ScrollView } from 'react-native'; import { ScrollView, StyleSheet } from 'react-native';
import { BlueLoading, BlueButton, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle, BlueSpacing20 } from '../BlueComponents'; import { BlueLoading, BlueButton, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle, BlueSpacing20 } from '../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
@ -10,6 +10,12 @@ let prompt = require('../prompt');
let EV = require('../events'); let EV = require('../events');
let loc = require('../loc'); let loc = require('../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
},
});
export default class PlausibleDeniability extends Component { export default class PlausibleDeniability extends Component {
static navigationOptions = { static navigationOptions = {
...BlueNavigationStyle(), ...BlueNavigationStyle(),
@ -35,7 +41,7 @@ export default class PlausibleDeniability extends Component {
} }
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<BlueCard> <BlueCard>
<ScrollView maxHeight={450}> <ScrollView maxHeight={450}>
<BlueText>{loc.plausibledeniability.help}</BlueText> <BlueText>{loc.plausibledeniability.help}</BlueText>

View file

@ -133,28 +133,13 @@ const ReceiveDetails = () => {
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'position' : null}> <KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'position' : null}>
<View style={styles.modalContent}> <View style={styles.modalContent}>
<BlueBitcoinAmount amount={customAmount || ''} onChangeText={setCustomAmount} /> <BlueBitcoinAmount amount={customAmount || ''} onChangeText={setCustomAmount} />
<View <View style={styles.customAmount}>
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
}}
>
<TextInput <TextInput
onChangeText={setCustomLabel} onChangeText={setCustomLabel}
placeholder={loc.receive.details.label} placeholder={loc.receive.details.label}
value={customLabel || ''} value={customLabel || ''}
numberOfLines={1} numberOfLines={1}
style={{ flex: 1, marginHorizontal: 8, minHeight: 33 }} style={styles.customAmountText}
/> />
</View> </View>
<BlueSpacing20 /> <BlueSpacing20 />
@ -187,7 +172,7 @@ const ReceiveDetails = () => {
}; };
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
{isHandOffUseEnabled && address !== undefined && ( {isHandOffUseEnabled && address !== undefined && (
<Handoff <Handoff
title={`Bitcoin Transaction ${address}`} title={`Bitcoin Transaction ${address}`}
@ -195,23 +180,20 @@ const ReceiveDetails = () => {
url={`https://blockstream.info/address/${address}`} url={`https://blockstream.info/address/${address}`}
/> />
)} )}
<ScrollView contentContainerStyle={{ justifyContent: 'space-between' }}> <ScrollView contentContainerStyle={styles.scroll}>
<View style={{ marginTop: 32, alignItems: 'center', paddingHorizontal: 16 }}> <View style={styles.scrollBody}>
{isCustom && ( {isCustom && (
<> <>
<BlueText <BlueText style={styles.amount} numberOfLines={1}>
style={{ color: '#0c2550', fontWeight: '600', fontSize: 36, textAlign: 'center', paddingBottom: 24 }}
numberOfLines={1}
>
{customAmount} {BitcoinUnit.BTC} {customAmount} {BitcoinUnit.BTC}
</BlueText> </BlueText>
<BlueText style={{ color: '#0c2550', fontWeight: '600', textAlign: 'center', paddingBottom: 24 }} numberOfLines={1}> <BlueText style={styles.label} numberOfLines={1}>
{customLabel} {customLabel}
</BlueText> </BlueText>
</> </>
)} )}
{bip21encoded === undefined ? ( {bip21encoded === undefined ? (
<View style={{ alignItems: 'center', width: 300, height: 300 }}> <View style={styles.loading}>
<BlueLoading /> <BlueLoading />
</View> </View>
) : ( ) : (
@ -228,7 +210,7 @@ const ReceiveDetails = () => {
)} )}
<BlueCopyTextToClipboard text={isCustom ? bip21encoded : address} /> <BlueCopyTextToClipboard text={isCustom ? bip21encoded : address} />
</View> </View>
<View style={{ alignItems: 'center', alignContent: 'flex-end', marginBottom: 24 }}> <View style={styles.share}>
<BlueButtonLink title={loc.receive.details.setAmount} onPress={showCustomAmountModal} /> <BlueButtonLink title={loc.receive.details.setAmount} onPress={showCustomAmountModal} />
<View> <View>
<BlueButton <BlueButton
@ -272,4 +254,57 @@ const styles = StyleSheet.create({
justifyContent: 'flex-end', justifyContent: 'flex-end',
margin: 0, margin: 0,
}, },
customAmount: {
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
},
customAmountText: {
flex: 1,
marginHorizontal: 8,
minHeight: 33,
},
root: {
flex: 1,
},
scroll: {
justifyContent: 'space-between',
},
scrollBody: {
marginTop: 32,
alignItems: 'center',
paddingHorizontal: 16,
},
amount: {
color: '#0c2550',
fontWeight: '600',
fontSize: 36,
textAlign: 'center',
paddingBottom: 24,
},
label: {
color: '#0c2550',
fontWeight: '600',
textAlign: 'center',
paddingBottom: 24,
},
loading: {
alignItems: 'center',
width: 300,
height: 300,
},
share: {
alignItems: 'center',
alignContent: 'flex-end',
marginBottom: 24,
},
}); });

View file

@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { ScrollView, View } from 'react-native'; import { ScrollView, View, StyleSheet } from 'react-native';
import { BlueLoading, BlueSpacing20, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../BlueComponents'; import { BlueLoading, BlueSpacing20, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { SegwitP2SHWallet, LegacyWallet, HDSegwitP2SHWallet, HDSegwitBech32Wallet } from '../class'; import { SegwitP2SHWallet, LegacyWallet, HDSegwitP2SHWallet, HDSegwitBech32Wallet } from '../class';
@ -8,6 +8,15 @@ const BlueCrypto = require('react-native-blue-crypto');
let encryption = require('../encryption'); let encryption = require('../encryption');
let BlueElectrum = require('../BlueElectrum'); let BlueElectrum = require('../BlueElectrum');
const styles = StyleSheet.create({
root: {
flex: 1,
},
center: {
alignItems: 'center',
},
});
export default class Selftest extends Component { export default class Selftest extends Component {
static navigationOptions = () => ({ static navigationOptions = () => ({
...BlueNavigationStyle(), ...BlueNavigationStyle(),
@ -208,7 +217,7 @@ export default class Selftest extends Component {
} }
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<BlueCard> <BlueCard>
<ScrollView> <ScrollView>
<BlueSpacing20 /> <BlueSpacing20 />
@ -216,7 +225,7 @@ export default class Selftest extends Component {
{(() => { {(() => {
if (this.state.isOk) { if (this.state.isOk) {
return ( return (
<View style={{ alignItems: 'center' }}> <View style={styles.center}>
<BlueText testID="SelfTestOk" h4> <BlueText testID="SelfTestOk" h4>
OK OK
</BlueText> </BlueText>
@ -224,7 +233,7 @@ export default class Selftest extends Component {
); );
} else { } else {
return ( return (
<View style={{ alignItems: 'center' }}> <View style={styles.center}>
<BlueText h4 numberOfLines={0}> <BlueText h4 numberOfLines={0}>
{this.state.errorMessage} {this.state.errorMessage}
</BlueText> </BlueText>

View file

@ -1,6 +1,6 @@
/* global alert */ /* global alert */
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Image, View, TouchableOpacity, Platform } from 'react-native'; import { Image, View, TouchableOpacity, Platform, StyleSheet } from 'react-native';
import { RNCamera } from 'react-native-camera'; import { RNCamera } from 'react-native-camera';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import ImagePicker from 'react-native-image-picker'; import ImagePicker from 'react-native-image-picker';
@ -11,6 +11,51 @@ import RNFS from 'react-native-fs';
const LocalQRCode = require('@remobile/react-native-qrcode-local-image'); const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
const createHash = require('create-hash'); const createHash = require('create-hash');
const styles = StyleSheet.create({
root: {
flex: 1,
backgroundColor: '#000000',
},
rnCamera: {
flex: 1,
justifyContent: 'space-between',
backgroundColor: '#000000',
},
closeTouch: {
width: 40,
height: 40,
backgroundColor: 'rgba(0,0,0,0.4)',
justifyContent: 'center',
borderRadius: 20,
position: 'absolute',
right: 16,
top: 44,
},
closeImage: {
alignSelf: 'center',
},
imagePickerTouch: {
width: 40,
height: 40,
backgroundColor: 'rgba(0,0,0,0.4)',
justifyContent: 'center',
borderRadius: 20,
position: 'absolute',
left: 24,
bottom: 48,
},
filePickerTouch: {
width: 40,
height: 40,
backgroundColor: 'rgba(0,0,0,0.4)',
justifyContent: 'center',
borderRadius: 20,
position: 'absolute',
left: 96,
bottom: 48,
},
});
const ScanQRCode = ({ const ScanQRCode = ({
showCloseButton = true, showCloseButton = true,
// eslint-disable-next-line react-hooks/rules-of-hooks // eslint-disable-next-line react-hooks/rules-of-hooks
@ -80,7 +125,7 @@ const ScanQRCode = ({
}; };
return ( return (
<View style={{ flex: 1, backgroundColor: '#000000' }}> <View style={styles.root}>
{!isLoading && ( {!isLoading && (
<RNCamera <RNCamera
captureAudio={false} captureAudio={false}
@ -90,39 +135,18 @@ const ScanQRCode = ({
buttonPositive: 'OK', buttonPositive: 'OK',
buttonNegative: 'Cancel', buttonNegative: 'Cancel',
}} }}
style={{ flex: 1, justifyContent: 'space-between', backgroundColor: '#000000' }} style={styles.rnCamera}
onBarCodeRead={onBarCodeRead} onBarCodeRead={onBarCodeRead}
barCodeTypes={[RNCamera.Constants.BarCodeType.qr]} barCodeTypes={[RNCamera.Constants.BarCodeType.qr]}
/> />
)} )}
{showCloseButton && ( {showCloseButton && (
<TouchableOpacity <TouchableOpacity style={styles.closeTouch} onPress={() => navigate(launchedBy)}>
style={{ <Image style={styles.closeImage} source={require('../../img/close-white.png')} />
width: 40,
height: 40,
backgroundColor: 'rgba(0,0,0,0.4)',
justifyContent: 'center',
borderRadius: 20,
position: 'absolute',
right: 16,
top: 44,
}}
onPress={() => navigate(launchedBy)}
>
<Image style={{ alignSelf: 'center' }} source={require('../../img/close-white.png')} />
</TouchableOpacity> </TouchableOpacity>
)} )}
<TouchableOpacity <TouchableOpacity
style={{ style={styles.imagePickerTouch}
width: 40,
height: 40,
backgroundColor: 'rgba(0,0,0,0.4)',
justifyContent: 'center',
borderRadius: 20,
position: 'absolute',
left: 24,
bottom: 48,
}}
onPress={() => { onPress={() => {
if (!isLoading) { if (!isLoading) {
setIsLoading(true); setIsLoading(true);
@ -152,19 +176,7 @@ const ScanQRCode = ({
<Icon name="image" type="font-awesome" color="#ffffff" /> <Icon name="image" type="font-awesome" color="#ffffff" />
</TouchableOpacity> </TouchableOpacity>
{showFileImportButton && ( {showFileImportButton && (
<TouchableOpacity <TouchableOpacity style={styles.filePickerTouch} onPress={showFilePicker}>
style={{
width: 40,
height: 40,
backgroundColor: 'rgba(0,0,0,0.4)',
justifyContent: 'center',
borderRadius: 20,
position: 'absolute',
left: 96,
bottom: 48,
}}
onPress={showFilePicker}
>
<Icon name="file-import" type="material-community" color="#ffffff" /> <Icon name="file-import" type="material-community" color="#ffffff" />
</TouchableOpacity> </TouchableOpacity>
)} )}

View file

@ -60,19 +60,7 @@ export default function Broadcast() {
{BROADCAST_RESULT.pending === broadcastResult && <ActivityIndicator size="small" />} {BROADCAST_RESULT.pending === broadcastResult && <ActivityIndicator size="small" />}
</View> </View>
<TextInput <TextInput
style={{ style={styles.text}
flex: 1,
borderColor: '#ebebeb',
backgroundColor: '#d2f8d6',
borderRadius: 4,
marginTop: 20,
color: '#37c0a1',
fontWeight: '500',
fontSize: 14,
paddingHorizontal: 16,
paddingBottom: 16,
paddingTop: 16,
}}
maxHeight={100} maxHeight={100}
minHeight={100} minHeight={100}
maxWidth={'100%'} maxWidth={'100%'}
@ -134,6 +122,19 @@ const styles = StyleSheet.create({
height: 30, height: 30,
maxHeight: 30, maxHeight: 30,
}, },
text: {
flex: 1,
borderColor: '#ebebeb',
backgroundColor: '#d2f8d6',
borderRadius: 4,
marginTop: 20,
color: '#37c0a1',
fontWeight: '500',
fontSize: 14,
paddingHorizontal: 16,
paddingBottom: 16,
paddingTop: 16,
},
}); });
function SuccessScreen({ tx }) { function SuccessScreen({ tx }) {

View file

@ -105,7 +105,9 @@ export default class Confirm extends Component {
this.setState({ isLoading: false }); this.setState({ isLoading: false });
} }
} catch (error) { } catch (error) {
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); ReactNativeHapticFeedback.trigger('notificationError', {
ignoreAndroidSystemSettings: false,
});
this.setState({ isLoading: false }); this.setState({ isLoading: false });
alert(error.message); alert(error.message);
} }
@ -115,38 +117,20 @@ export default class Confirm extends Component {
_renderItem = ({ index, item }) => { _renderItem = ({ index, item }) => {
return ( return (
<> <>
<View style={{ flexDirection: 'row', justifyContent: 'center' }}> <View style={styles.valueWrap}>
<Text <Text testID={'TransactionValue'} style={styles.valueValue}>
testID={'TransactionValue'}
style={{
color: '#0f5cc0',
fontSize: 36,
fontWeight: '600',
}}
>
{!item.value || item.value === BitcoinUnit.MAX {!item.value || item.value === BitcoinUnit.MAX
? currency.satoshiToBTC(this.state.fromWallet.getBalance() - this.state.feeSatoshi) ? currency.satoshiToBTC(this.state.fromWallet.getBalance() - this.state.feeSatoshi)
: item.amount || currency.satoshiToBTC(item.value)} : item.amount || currency.satoshiToBTC(item.value)}
</Text> </Text>
<Text <Text style={styles.valueUnit}>{' ' + BitcoinUnit.BTC}</Text>
style={{
color: '#0f5cc0',
fontSize: 16,
marginHorizontal: 4,
paddingBottom: 6,
fontWeight: '600',
alignSelf: 'flex-end',
}}
>
{' ' + BitcoinUnit.BTC}
</Text>
</View> </View>
<BlueCard> <BlueCard>
<Text style={styles.transactionDetailsTitle}>{loc.send.create.to}</Text> <Text style={styles.transactionDetailsTitle}>{loc.send.create.to}</Text>
<Text style={styles.transactionDetailsSubtitle}>{item.address}</Text> <Text style={styles.transactionDetailsSubtitle}>{item.address}</Text>
</BlueCard> </BlueCard>
{this.state.recipients.length > 1 && ( {this.state.recipients.length > 1 && (
<BlueText style={{ alignSelf: 'flex-end', marginRight: 18, marginVertical: 8 }}> <BlueText style={styles.valueOf}>
{index + 1} of {this.state.recipients.length} {index + 1} of {this.state.recipients.length}
</BlueText> </BlueText>
)} )}
@ -155,13 +139,13 @@ export default class Confirm extends Component {
}; };
renderSeparator = () => { renderSeparator = () => {
return <View style={{ backgroundColor: BlueApp.settings.inputBorderColor, height: 0.5, margin: 16 }} />; return <View style={styles.separator} />;
}; };
render() { render() {
return ( return (
<SafeBlueArea style={{ flex: 1, paddingTop: 19 }}> <SafeBlueArea style={styles.root}>
<View style={{ marginTop: 16, alignItems: 'center', justifyContent: 'space-between' }}> <View style={styles.rootWrap}>
<FlatList <FlatList
scrollEnabled={this.state.recipients.length > 1} scrollEnabled={this.state.recipients.length > 1}
extraData={this.state.recipients} extraData={this.state.recipients}
@ -169,20 +153,11 @@ export default class Confirm extends Component {
renderItem={this._renderItem} renderItem={this._renderItem}
keyExtractor={(_item, index) => `${index}`} keyExtractor={(_item, index) => `${index}`}
ItemSeparatorComponent={this.renderSeparator} ItemSeparatorComponent={this.renderSeparator}
style={{ maxHeight: '55%' }} style={styles.flat}
/> />
<View style={{ flexDirection: 'row', justifyContent: 'center', paddingTop: 16, paddingBottom: 16 }}> <View style={styles.cardContainer}>
<BlueCard> <BlueCard>
<Text <Text style={styles.cardText}>
style={{
color: '#37c0a1',
fontSize: 14,
marginHorizontal: 4,
paddingBottom: 6,
fontWeight: '500',
alignSelf: 'center',
}}
>
{loc.send.create.fee}: {loc.formatBalance(this.state.feeSatoshi, BitcoinUnit.BTC)} ( {loc.send.create.fee}: {loc.formatBalance(this.state.feeSatoshi, BitcoinUnit.BTC)} (
{currency.satoshiToLocalCurrency(this.state.feeSatoshi)}) {currency.satoshiToLocalCurrency(this.state.feeSatoshi)})
</Text> </Text>
@ -195,7 +170,7 @@ export default class Confirm extends Component {
<TouchableOpacity <TouchableOpacity
testID={'TransactionDetailsButton'} testID={'TransactionDetailsButton'}
style={{ marginVertical: 24 }} style={styles.txDetails}
onPress={async () => { onPress={async () => {
if (this.isBiometricUseCapableAndEnabled) { if (this.isBiometricUseCapableAndEnabled) {
if (!(await Biometric.unlockWithBiometrics())) { if (!(await Biometric.unlockWithBiometrics())) {
@ -214,9 +189,7 @@ export default class Confirm extends Component {
}); });
}} }}
> >
<Text style={{ color: '#0c2550', fontSize: 15, fontWeight: '500', alignSelf: 'center' }}> <Text style={styles.txText}>{loc.transactions.details.transaction_details}</Text>
{loc.transactions.details.transaction_details}
</Text>
</TouchableOpacity> </TouchableOpacity>
</BlueCard> </BlueCard>
</View> </View>
@ -239,6 +212,68 @@ const styles = StyleSheet.create({
fontSize: 15, fontSize: 15,
marginBottom: 20, marginBottom: 20,
}, },
valueWrap: {
flexDirection: 'row',
justifyContent: 'center',
},
valueValue: {
color: '#0f5cc0',
fontSize: 36,
fontWeight: '600',
},
valueUnit: {
color: '#0f5cc0',
fontSize: 16,
marginHorizontal: 4,
paddingBottom: 6,
fontWeight: '600',
alignSelf: 'flex-end',
},
valueOf: {
alignSelf: 'flex-end',
marginRight: 18,
marginVertical: 8,
},
separator: {
backgroundColor: BlueApp.settings.inputBorderColor,
height: 0.5,
margin: 16,
},
root: {
flex: 1,
paddingTop: 19,
},
rootWrap: {
marginTop: 16,
alignItems: 'center',
justifyContent: 'space-between',
},
flat: {
maxHeight: '55%',
},
cardContainer: {
flexDirection: 'row',
justifyContent: 'center',
paddingTop: 16,
paddingBottom: 16,
},
cardText: {
color: '#37c0a1',
fontSize: 14,
marginHorizontal: 4,
paddingBottom: 6,
fontWeight: '500',
alignSelf: 'center',
},
txDetails: {
marginVertical: 24,
},
txText: {
color: '#0c2550',
fontSize: 15,
fontWeight: '500',
alignSelf: 'center',
},
}); });
Confirm.propTypes = { Confirm.propTypes = {

View file

@ -32,7 +32,7 @@ export default class SendCreate extends Component {
...BlueNavigationStyle, ...BlueNavigationStyle,
title: loc.send.create.details, title: loc.send.create.details,
headerRight: navigation.state.params.exportTXN ? ( headerRight: navigation.state.params.exportTXN ? (
<TouchableOpacity style={{ marginRight: 16 }} onPress={navigation.state.params.exportTXN}> <TouchableOpacity style={styles.export} onPress={navigation.state.params.exportTXN}>
<Icon size={22} name="share-alternative" type="entypo" color={BlueApp.settings.foregroundColor} /> <Icon size={22} name="share-alternative" type="entypo" color={BlueApp.settings.foregroundColor} />
</TouchableOpacity> </TouchableOpacity>
) : null, ) : null,
@ -110,7 +110,7 @@ export default class SendCreate extends Component {
{BitcoinUnit.BTC} {BitcoinUnit.BTC}
</Text> </Text>
{this.state.recipients.length > 1 && ( {this.state.recipients.length > 1 && (
<BlueText style={{ alignSelf: 'flex-end' }}> <BlueText style={styles.itemOf}>
{index + 1} of {this.state.recipients.length} {index + 1} of {this.state.recipients.length}
</BlueText> </BlueText>
)} )}
@ -120,41 +120,23 @@ export default class SendCreate extends Component {
}; };
renderSeparator = () => { renderSeparator = () => {
return <View style={{ backgroundColor: BlueApp.settings.inputBorderColor, height: 0.5, marginVertical: 16 }} />; return <View style={styles.separator} />;
}; };
render() { render() {
return ( return (
<SafeBlueArea style={{ flex: 1, paddingTop: 19 }}> <SafeBlueArea style={styles.root}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}> <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<ScrollView> <ScrollView>
<BlueCard style={{ alignItems: 'center', flex: 1 }}> <BlueCard style={styles.card}>
<BlueText style={{ color: '#0c2550', fontWeight: '500' }}>{loc.send.create.this_is_hex}</BlueText> <BlueText style={styles.cardText}>{loc.send.create.this_is_hex}</BlueText>
<TextInput <TextInput testID={'TxhexInput'} style={styles.cardTx} height={72} multiline editable value={this.state.tx} />
testID={'TxhexInput'}
style={{
borderColor: '#ebebeb',
backgroundColor: '#d2f8d6',
borderRadius: 4,
marginTop: 20,
color: '#37c0a1',
fontWeight: '500',
fontSize: 14,
paddingHorizontal: 16,
paddingBottom: 16,
paddingTop: 16,
}}
height={72}
multiline
editable
value={this.state.tx}
/>
<TouchableOpacity style={{ marginVertical: 24 }} onPress={() => Clipboard.setString(this.state.tx)}> <TouchableOpacity style={styles.actionTouch} onPress={() => Clipboard.setString(this.state.tx)}>
<Text style={{ color: '#9aa0aa', fontSize: 15, fontWeight: '500', alignSelf: 'center' }}>Copy and broadcast later</Text> <Text style={styles.actionText}>Copy and broadcast later</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={{ marginVertical: 24 }} onPress={() => Linking.openURL('https://coinb.in/?verify=' + this.state.tx)}> <TouchableOpacity style={styles.actionTouch} onPress={() => Linking.openURL('https://coinb.in/?verify=' + this.state.tx)}>
<Text style={{ color: '#9aa0aa', fontSize: 15, fontWeight: '500', alignSelf: 'center' }}>Verify on coinb.in</Text> <Text style={styles.actionText}>Verify on coinb.in</Text>
</TouchableOpacity> </TouchableOpacity>
</BlueCard> </BlueCard>
<BlueCard> <BlueCard>
@ -203,6 +185,50 @@ const styles = StyleSheet.create({
fontSize: 15, fontSize: 15,
marginBottom: 20, marginBottom: 20,
}, },
export: {
marginRight: 16,
},
itemOf: {
alignSelf: 'flex-end',
},
separator: {
backgroundColor: BlueApp.settings.inputBorderColor,
height: 0.5,
marginVertical: 16,
},
root: {
flex: 1,
paddingTop: 19,
},
card: {
alignItems: 'center',
flex: 1,
},
cardText: {
color: '#0c2550',
fontWeight: '500',
},
cardTx: {
borderColor: '#ebebeb',
backgroundColor: '#d2f8d6',
borderRadius: 4,
marginTop: 20,
color: '#37c0a1',
fontWeight: '500',
fontSize: 14,
paddingHorizontal: 16,
paddingBottom: 16,
paddingTop: 16,
},
actionTouch: {
marginVertical: 24,
},
actionText: {
color: '#9aa0aa',
fontSize: 15,
fontWeight: '500',
alignSelf: 'center',
},
}); });
SendCreate.propTypes = { SendCreate.propTypes = {

View file

@ -49,6 +49,174 @@ let loc = require('../../loc');
const btcAddressRx = /^[a-zA-Z0-9]{26,35}$/; const btcAddressRx = /^[a-zA-Z0-9]{26,35}$/;
const styles = StyleSheet.create({
loading: {
flex: 1,
paddingTop: 20,
},
root: {
flex: 1,
justifyContent: 'space-between',
},
scrollViewContent: {
flexWrap: 'wrap',
flexDirection: 'row',
},
modalContent: {
backgroundColor: '#FFFFFF',
padding: 22,
justifyContent: 'center',
alignItems: 'center',
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)',
minHeight: 200,
height: 200,
},
advancedTransactionOptionsModalContent: {
backgroundColor: '#FFFFFF',
padding: 22,
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)',
minHeight: 130,
},
bottomModal: {
justifyContent: 'flex-end',
margin: 0,
},
feeSliderInput: {
backgroundColor: '#d2f8d6',
minWidth: 127,
height: 60,
borderRadius: 8,
flexDirection: 'row',
justifyContent: 'center',
paddingHorizontal: 8,
},
feeSliderText: {
fontWeight: '600',
color: '#37c0a1',
marginBottom: 0,
marginRight: 4,
textAlign: 'right',
fontSize: 36,
},
feeSliderUnit: {
fontWeight: '600',
color: '#37c0a1',
paddingRight: 4,
textAlign: 'left',
fontSize: 16,
alignSelf: 'flex-end',
marginBottom: 14,
},
sliderContainer: {
flex: 1,
marginTop: 32,
minWidth: 240,
width: 240,
},
slider: {
flex: 1,
},
sliderLabels: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
marginTop: 14,
},
sliderLabel: {
fontWeight: '500',
fontSize: 13,
color: '#37c0a1',
},
createButton: {
marginHorizontal: 56,
marginVertical: 16,
alignContent: 'center',
backgroundColor: '#FFFFFF',
minHeight: 44,
},
select: {
marginBottom: 24,
alignItems: 'center',
},
selectTouch: {
flexDirection: 'row',
alignItems: 'center',
},
selectText: {
color: '#9aa0aa',
fontSize: 14,
marginRight: 8,
},
selectWrap: {
flexDirection: 'row',
alignItems: 'center',
marginVertical: 4,
},
selectLabel: {
color: '#0c2550',
fontSize: 14,
},
of: {
alignSelf: 'flex-end',
marginRight: 18,
marginVertical: 8,
},
memo: {
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
},
memoText: {
flex: 1,
marginHorizontal: 8,
minHeight: 33,
},
fee: {
flexDirection: 'row',
marginHorizontal: 20,
justifyContent: 'space-between',
alignItems: 'center',
},
feeLabel: {
color: '#81868e',
fontSize: 14,
},
feeRow: {
backgroundColor: '#d2f8d6',
minWidth: 40,
height: 25,
borderRadius: 4,
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 10,
},
feeValue: {
color: '#37c0a1',
marginBottom: 0,
marginRight: 4,
textAlign: 'right',
},
feeUnit: {
color: '#37c0a1',
paddingRight: 4,
textAlign: 'left',
},
});
export default class SendDetails extends Component { export default class SendDetails extends Component {
static navigationOptions = ({ navigation }) => ({ static navigationOptions = ({ navigation }) => ({
...BlueCreateTxNavigationStyle( ...BlueCreateTxNavigationStyle(
@ -527,7 +695,7 @@ export default class SendDetails extends Component {
> >
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'position' : null}> <KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'position' : null}>
<View style={styles.modalContent}> <View style={styles.modalContent}>
<TouchableOpacity style={styles.satoshisTextInput} onPress={() => this.textInput.focus()}> <TouchableOpacity style={styles.feeSliderInput} onPress={() => this.textInput.focus()}>
<TextInput <TextInput
keyboardType="numeric" keyboardType="numeric"
ref={ref => { ref={ref => {
@ -547,25 +715,13 @@ export default class SendDetails extends Component {
editable={!this.state.isLoading} editable={!this.state.isLoading}
placeholderTextColor="#37c0a1" placeholderTextColor="#37c0a1"
placeholder={this.state.networkTransactionFees.mediumFee.toString()} placeholder={this.state.networkTransactionFees.mediumFee.toString()}
style={{ fontWeight: '600', color: '#37c0a1', marginBottom: 0, marginRight: 4, textAlign: 'right', fontSize: 36 }} style={styles.feeSliderText}
inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID} inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}
/> />
<Text <Text style={styles.feeSliderUnit}>sat/b</Text>
style={{
fontWeight: '600',
color: '#37c0a1',
paddingRight: 4,
textAlign: 'left',
fontSize: 16,
alignSelf: 'flex-end',
marginBottom: 14,
}}
>
sat/b
</Text>
</TouchableOpacity> </TouchableOpacity>
{this.state.networkTransactionFees.fastestFee > 1 && ( {this.state.networkTransactionFees.fastestFee > 1 && (
<View style={{ flex: 1, marginTop: 32, minWidth: 240, width: 240 }}> <View style={styles.sliderContainer}>
<Slider <Slider
onValueChange={value => this.setState({ feeSliderValue: value.toFixed(0), fee: value.toFixed(0) })} onValueChange={value => this.setState({ feeSliderValue: value.toFixed(0), fee: value.toFixed(0) })}
minimumValue={1} minimumValue={1}
@ -573,11 +729,11 @@ export default class SendDetails extends Component {
value={Number(this.state.feeSliderValue)} value={Number(this.state.feeSliderValue)}
maximumTrackTintColor="#d8d8d8" maximumTrackTintColor="#d8d8d8"
minimumTrackTintColor="#37c0a1" minimumTrackTintColor="#37c0a1"
style={{ flex: 1 }} style={styles.slider}
/> />
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', marginTop: 14 }}> <View style={styles.sliderLabels}>
<Text style={{ fontWeight: '500', fontSize: 13, color: '#37c0a1' }}>slow</Text> <Text style={styles.sliderLabel}>slow</Text>
<Text style={{ fontWeight: '500', fontSize: 13, color: '#37c0a1' }}>fast</Text> <Text style={styles.sliderLabel}>fast</Text>
</View> </View>
</View> </View>
)} )}
@ -720,7 +876,7 @@ export default class SendDetails extends Component {
renderCreateButton = () => { renderCreateButton = () => {
return ( return (
<View style={{ marginHorizontal: 56, marginVertical: 16, alignContent: 'center', backgroundColor: '#FFFFFF', minHeight: 44 }}> <View style={styles.createButton}>
{this.state.isLoading ? ( {this.state.isLoading ? (
<ActivityIndicator /> <ActivityIndicator />
) : ( ) : (
@ -733,26 +889,26 @@ export default class SendDetails extends Component {
renderWalletSelectionButton = () => { renderWalletSelectionButton = () => {
if (this.state.renderWalletSelectionButtonHidden) return; if (this.state.renderWalletSelectionButtonHidden) return;
return ( return (
<View style={{ marginBottom: 24, alignItems: 'center' }}> <View style={styles.select}>
{!this.state.isLoading && ( {!this.state.isLoading && (
<TouchableOpacity <TouchableOpacity
style={{ flexDirection: 'row', alignItems: 'center' }} style={styles.selectTouch}
onPress={() => onPress={() =>
this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.ONCHAIN }) this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.ONCHAIN })
} }
> >
<Text style={{ color: '#9aa0aa', fontSize: 14, marginRight: 8 }}>{loc.wallets.select_wallet.toLowerCase()}</Text> <Text style={styles.selectText}>{loc.wallets.select_wallet.toLowerCase()}</Text>
<Icon name="angle-right" size={18} type="font-awesome" color="#9aa0aa" /> <Icon name="angle-right" size={18} type="font-awesome" color="#9aa0aa" />
</TouchableOpacity> </TouchableOpacity>
)} )}
<View style={{ flexDirection: 'row', alignItems: 'center', marginVertical: 4 }}> <View style={styles.selectWrap}>
<TouchableOpacity <TouchableOpacity
style={{ flexDirection: 'row', alignItems: 'center' }} style={styles.selectTouch}
onPress={() => onPress={() =>
this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.ONCHAIN }) this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.ONCHAIN })
} }
> >
<Text style={{ color: '#0c2550', fontSize: 14 }}>{this.state.fromWallet.getLabel()}</Text> <Text style={styles.selectLabel}>{this.state.fromWallet.getLabel()}</Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</View> </View>
@ -784,7 +940,13 @@ export default class SendDetails extends Component {
let rows = []; let rows = [];
for (let [index, item] of this.state.addresses.entries()) { for (let [index, item] of this.state.addresses.entries()) {
rows.push( rows.push(
<View style={{ minWidth: width, maxWidth: width, width: width }}> <View
style={{
minWidth: width,
maxWidth: width,
width: width,
}}
>
<BlueBitcoinAmount <BlueBitcoinAmount
isLoading={this.state.isLoading} isLoading={this.state.isLoading}
amount={item.amount ? item.amount.toString() : null} amount={item.amount ? item.amount.toString() : null}
@ -825,7 +987,7 @@ export default class SendDetails extends Component {
launchedBy={this.props.navigation.state.routeName} launchedBy={this.props.navigation.state.routeName}
/> />
{this.state.addresses.length > 1 && ( {this.state.addresses.length > 1 && (
<BlueText style={{ alignSelf: 'flex-end', marginRight: 18, marginVertical: 8 }}> <BlueText style={styles.of}>
{index + 1} of {this.state.addresses.length} {index + 1} of {this.state.addresses.length}
</BlueText> </BlueText>
)} )}
@ -862,20 +1024,20 @@ export default class SendDetails extends Component {
render() { render() {
if (this.state.isLoading || typeof this.state.fromWallet === 'undefined') { if (this.state.isLoading || typeof this.state.fromWallet === 'undefined') {
return ( return (
<View style={{ flex: 1, paddingTop: 20 }}> <View style={styles.loading}>
<BlueLoading /> <BlueLoading />
</View> </View>
); );
} }
return ( return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}> <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View style={{ flex: 1, justifyContent: 'space-between' }}> <View style={styles.root}>
<View> <View>
<KeyboardAvoidingView behavior="position"> <KeyboardAvoidingView behavior="position">
<ScrollView <ScrollView
pagingEnabled pagingEnabled
horizontal horizontal
contentContainerStyle={{ flexWrap: 'wrap', flexDirection: 'row' }} contentContainerStyle={styles.scrollViewContent}
ref={ref => (this.scrollView = ref)} ref={ref => (this.scrollView = ref)}
onContentSizeChange={() => this.scrollView.scrollToEnd()} onContentSizeChange={() => this.scrollView.scrollToEnd()}
onLayout={() => this.scrollView.scrollToEnd()} onLayout={() => this.scrollView.scrollToEnd()}
@ -885,29 +1047,13 @@ export default class SendDetails extends Component {
> >
{this.renderBitcoinTransactionInfoFields()} {this.renderBitcoinTransactionInfoFields()}
</ScrollView> </ScrollView>
<View <View hide={!this.state.showMemoRow} style={styles.memo}>
hide={!this.state.showMemoRow}
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
}}
>
<TextInput <TextInput
onChangeText={text => this.setState({ memo: text })} onChangeText={text => this.setState({ memo: text })}
placeholder={loc.send.details.note_placeholder} placeholder={loc.send.details.note_placeholder}
value={this.state.memo} value={this.state.memo}
numberOfLines={1} numberOfLines={1}
style={{ flex: 1, marginHorizontal: 8, minHeight: 33 }} style={styles.memoText}
editable={!this.state.isLoading} editable={!this.state.isLoading}
onSubmitEditing={Keyboard.dismiss} onSubmitEditing={Keyboard.dismiss}
inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID} inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}
@ -916,23 +1062,12 @@ export default class SendDetails extends Component {
<TouchableOpacity <TouchableOpacity
onPress={() => this.setState({ isFeeSelectionModalVisible: true })} onPress={() => this.setState({ isFeeSelectionModalVisible: true })}
disabled={this.state.isLoading} disabled={this.state.isLoading}
style={{ flexDirection: 'row', marginHorizontal: 20, justifyContent: 'space-between', alignItems: 'center' }} style={styles.fee}
> >
<Text style={{ color: '#81868e', fontSize: 14 }}>Fee</Text> <Text style={styles.feeLabel}>Fee</Text>
<View <View style={styles.feeRow}>
style={{ <Text style={styles.feeValue}>{this.state.fee}</Text>
backgroundColor: '#d2f8d6', <Text style={styles.feeUnit}>sat/b</Text>
minWidth: 40,
height: 25,
borderRadius: 4,
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 10,
}}
>
<Text style={{ color: '#37c0a1', marginBottom: 0, marginRight: 4, textAlign: 'right' }}>{this.state.fee}</Text>
<Text style={{ color: '#37c0a1', paddingRight: 4, textAlign: 'left' }}>sat/b</Text>
</View> </View>
</TouchableOpacity> </TouchableOpacity>
{this.renderCreateButton()} {this.renderCreateButton()}
@ -955,41 +1090,6 @@ export default class SendDetails extends Component {
} }
} }
const styles = StyleSheet.create({
modalContent: {
backgroundColor: '#FFFFFF',
padding: 22,
justifyContent: 'center',
alignItems: 'center',
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)',
minHeight: 200,
height: 200,
},
advancedTransactionOptionsModalContent: {
backgroundColor: '#FFFFFF',
padding: 22,
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)',
minHeight: 130,
},
bottomModal: {
justifyContent: 'flex-end',
margin: 0,
},
satoshisTextInput: {
backgroundColor: '#d2f8d6',
minWidth: 127,
height: 60,
borderRadius: 8,
flexDirection: 'row',
justifyContent: 'center',
paddingHorizontal: 8,
},
});
SendDetails.propTypes = { SendDetails.propTypes = {
navigation: PropTypes.shape({ navigation: PropTypes.shape({
pop: PropTypes.func, pop: PropTypes.func,

View file

@ -12,6 +12,7 @@ import {
Linking, Linking,
Platform, Platform,
PermissionsAndroid, PermissionsAndroid,
StyleSheet,
} from 'react-native'; } from 'react-native';
import QRCode from 'react-native-qrcode-svg'; import QRCode from 'react-native-qrcode-svg';
import { Text } from 'react-native-elements'; import { Text } from 'react-native-elements';
@ -39,6 +40,80 @@ const BlueApp = require('../../BlueApp');
const bitcoin = require('bitcoinjs-lib'); const bitcoin = require('bitcoinjs-lib');
const { height, width } = Dimensions.get('window'); const { height, width } = Dimensions.get('window');
const styles = StyleSheet.create({
root: {
flex: 1,
},
scrollViewContent: {
flexGrow: 1,
justifyContent: 'space-between',
},
container: {
flexDirection: 'row',
justifyContent: 'center',
paddingTop: 16,
paddingBottom: 16,
},
rootCamera: {
flex: 1,
justifyContent: 'space-between',
},
rootPadding: {
flex: 1,
paddingTop: 20,
},
closeCamera: {
width: 40,
height: 40,
backgroundColor: 'rgba(0,0,0,0.4)',
justifyContent: 'center',
borderRadius: 20,
position: 'absolute',
right: 16,
top: 64,
},
closeCameraImage: {
alignSelf: 'center',
},
blueBigCheckmark: {
marginTop: 143,
marginBottom: 53,
},
hexWrap: {
alignItems: 'center',
flex: 1,
},
hexLabel: {
color: '#0c2550',
fontWeight: '500',
},
hexInput: {
borderColor: '#ebebeb',
backgroundColor: '#d2f8d6',
borderRadius: 4,
marginTop: 20,
color: '#37c0a1',
fontWeight: '500',
fontSize: 14,
paddingHorizontal: 16,
paddingBottom: 16,
paddingTop: 16,
},
hexTouch: {
marginVertical: 24,
},
hexText: {
color: '#9aa0aa',
fontSize: 15,
fontWeight: '500',
alignSelf: 'center',
},
copyToClipboard: {
justifyContent: 'center',
alignItems: 'center',
},
});
export default class PsbtWithHardwareWallet extends Component { export default class PsbtWithHardwareWallet extends Component {
static navigationOptions = () => ({ static navigationOptions = () => ({
...BlueNavigationStyle(null, false), ...BlueNavigationStyle(null, false),
@ -144,7 +219,7 @@ export default class PsbtWithHardwareWallet extends Component {
_renderScanner() { _renderScanner() {
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<RNCamera <RNCamera
captureAudio={false} captureAudio={false}
androidCameraPermissionOptions={{ androidCameraPermissionOptions={{
@ -154,24 +229,12 @@ export default class PsbtWithHardwareWallet extends Component {
buttonNegative: 'Cancel', buttonNegative: 'Cancel',
}} }}
ref={ref => (this.cameraRef = ref)} ref={ref => (this.cameraRef = ref)}
style={{ flex: 1, justifyContent: 'space-between' }} style={styles.rootCamera}
onBarCodeRead={this.onBarCodeRead} onBarCodeRead={this.onBarCodeRead}
barCodeTypes={[RNCamera.Constants.BarCodeType.qr]} barCodeTypes={[RNCamera.Constants.BarCodeType.qr]}
/> />
<TouchableOpacity <TouchableOpacity style={styles.closeCamera} onPress={() => this.setState({ renderScanner: false })}>
style={{ <Image style={styles.closeCameraImage} source={require('../../img/close-white.png')} />
width: 40,
height: 40,
backgroundColor: 'rgba(0,0,0,0.4)',
justifyContent: 'center',
borderRadius: 20,
position: 'absolute',
right: 16,
top: 64,
}}
onPress={() => this.setState({ renderScanner: false })}
>
<Image style={{ alignSelf: 'center' }} source={require('../../img/close-white.png')} />
</TouchableOpacity> </TouchableOpacity>
</SafeBlueArea> </SafeBlueArea>
); );
@ -179,8 +242,8 @@ export default class PsbtWithHardwareWallet extends Component {
_renderSuccess() { _renderSuccess() {
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<BlueBigCheckmark style={{ marginTop: 143, marginBottom: 53 }} /> <BlueBigCheckmark style={styles.blueBigCheckmark} />
<BlueCard> <BlueCard>
<BlueButton onPress={this.props.navigation.dismiss} title={loc.send.success.done} /> <BlueButton onPress={this.props.navigation.dismiss} title={loc.send.success.done} />
</BlueCard> </BlueCard>
@ -190,33 +253,16 @@ export default class PsbtWithHardwareWallet extends Component {
_renderBroadcastHex() { _renderBroadcastHex() {
return ( return (
<View style={{ flex: 1, paddingTop: 20 }}> <View style={styles.rootPadding}>
<BlueCard style={{ alignItems: 'center', flex: 1 }}> <BlueCard style={styles.hexWrap}>
<BlueText style={{ color: '#0c2550', fontWeight: '500' }}>{loc.send.create.this_is_hex}</BlueText> <BlueText style={styles.hexLabel}>{loc.send.create.this_is_hex}</BlueText>
<TextInput <TextInput style={styles.hexInput} height={112} multiline editable value={this.state.txhex} />
style={{
borderColor: '#ebebeb',
backgroundColor: '#d2f8d6',
borderRadius: 4,
marginTop: 20,
color: '#37c0a1',
fontWeight: '500',
fontSize: 14,
paddingHorizontal: 16,
paddingBottom: 16,
paddingTop: 16,
}}
height={112}
multiline
editable
value={this.state.txhex}
/>
<TouchableOpacity style={{ marginVertical: 24 }} onPress={() => Clipboard.setString(this.state.txhex)}> <TouchableOpacity style={styles.hexTouch} onPress={() => Clipboard.setString(this.state.txhex)}>
<Text style={{ color: '#9aa0aa', fontSize: 15, fontWeight: '500', alignSelf: 'center' }}>Copy and broadcast later</Text> <Text style={styles.hexText}>Copy and broadcast later</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={{ marginVertical: 24 }} onPress={() => Linking.openURL('https://coinb.in/?verify=' + this.state.txhex)}> <TouchableOpacity style={styles.hexTouch} onPress={() => Linking.openURL('https://coinb.in/?verify=' + this.state.txhex)}>
<Text style={{ color: '#9aa0aa', fontSize: 15, fontWeight: '500', alignSelf: 'center' }}>Verify on coinb.in</Text> <Text style={styles.hexText}>Verify on coinb.in</Text>
</TouchableOpacity> </TouchableOpacity>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueButton onPress={this.broadcast} title={loc.send.confirm.sendNow} /> <BlueButton onPress={this.broadcast} title={loc.send.confirm.sendNow} />
@ -278,7 +324,7 @@ export default class PsbtWithHardwareWallet extends Component {
render() { render() {
if (this.state.isLoading) { if (this.state.isLoading) {
return ( return (
<View style={{ flex: 1, paddingTop: 20 }}> <View style={styles.rootPadding}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
); );
@ -289,9 +335,9 @@ export default class PsbtWithHardwareWallet extends Component {
if (this.state.txhex) return this._renderBroadcastHex(); if (this.state.txhex) return this._renderBroadcastHex();
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<ScrollView centerContent contentContainerStyle={{ flexGrow: 1, justifyContent: 'space-between' }}> <ScrollView centerContent contentContainerStyle={styles.scrollViewContent}>
<View style={{ flexDirection: 'row', justifyContent: 'center', paddingTop: 16, paddingBottom: 16 }}> <View style={styles.container}>
<BlueCard> <BlueCard>
<BlueText testID={'TextHelperForPSBT'}> <BlueText testID={'TextHelperForPSBT'}>
This is partially signed bitcoin transaction (PSBT). Please finish signing it with your hardware wallet. This is partially signed bitcoin transaction (PSBT). Please finish signing it with your hardware wallet.
@ -335,7 +381,7 @@ export default class PsbtWithHardwareWallet extends Component {
title={'Export to file'} title={'Export to file'}
/> />
<BlueSpacing20 /> <BlueSpacing20 />
<View style={{ justifyContent: 'center', alignItems: 'center' }}> <View style={styles.copyToClipboard}>
<BlueCopyToClipboardButton <BlueCopyToClipboardButton
stringToCopy={this.state.isFirstPSBTAlreadyBase64 ? this.state.psbt : this.state.psbt.toBase64()} stringToCopy={this.state.isFirstPSBTAlreadyBase64 ? this.state.psbt : this.state.psbt.toBase64()}
displayText={'Copy to Clipboard'} displayText={'Copy to Clipboard'}

View file

@ -1,12 +1,60 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { View } from 'react-native'; import { View, StyleSheet } from 'react-native';
import { Text, Icon } from 'react-native-elements'; import { Text, Icon } from 'react-native-elements';
import { BlueButton, SafeBlueArea, BlueCard } from '../../BlueComponents'; import { BlueButton, SafeBlueArea, BlueCard } from '../../BlueComponents';
import { BitcoinUnit } from '../../models/bitcoinUnits'; import { BitcoinUnit } from '../../models/bitcoinUnits';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
let loc = require('../../loc'); let loc = require('../../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
paddingTop: 19,
},
amout: {
alignItems: 'center',
flex: 1,
},
view: {
flexDirection: 'row',
justifyContent: 'center',
paddingTop: 76,
paddingBottom: 16,
},
amountValue: {
color: '#0f5cc0',
fontSize: 36,
fontWeight: '600',
},
amountUnit: {
color: '#0f5cc0',
fontSize: 16,
marginHorizontal: 4,
paddingBottom: 6,
fontWeight: '600',
alignSelf: 'flex-end',
},
feeText: {
color: '#37c0a1',
fontSize: 14,
marginHorizontal: 4,
paddingBottom: 6,
fontWeight: '500',
alignSelf: 'center',
},
ready: {
backgroundColor: '#ccddf9',
width: 120,
height: 120,
borderRadius: 60,
alignSelf: 'center',
justifyContent: 'center',
marginTop: 43,
marginBottom: 53,
},
});
export default class Success extends Component { export default class Success extends Component {
static navigationOptions = { static navigationOptions = {
header: null, header: null,
@ -32,73 +80,24 @@ export default class Success extends Component {
render() { render() {
return ( return (
<SafeBlueArea style={{ flex: 1, paddingTop: 19 }}> <SafeBlueArea style={styles.root}>
<BlueCard style={{ alignItems: 'center', flex: 1 }}> <BlueCard style={styles.amout}>
<View style={{ flexDirection: 'row', justifyContent: 'center', paddingTop: 76, paddingBottom: 16 }}> <View style={styles.view}>
<Text <Text style={styles.amountValue}>{this.state.amount}</Text>
style={{ <Text style={styles.amountUnit}>{' ' + this.state.amountUnit}</Text>
color: '#0f5cc0',
fontSize: 36,
fontWeight: '600',
}}
>
{this.state.amount}
</Text>
<Text
style={{
color: '#0f5cc0',
fontSize: 16,
marginHorizontal: 4,
paddingBottom: 6,
fontWeight: '600',
alignSelf: 'flex-end',
}}
>
{' ' + this.state.amountUnit}
</Text>
</View> </View>
{this.state.fee > 0 && ( {this.state.fee > 0 && (
<Text <Text style={styles.feeText}>
style={{
color: '#37c0a1',
fontSize: 14,
marginHorizontal: 4,
paddingBottom: 6,
fontWeight: '500',
alignSelf: 'center',
}}
>
{loc.send.create.fee}: {this.state.fee} {BitcoinUnit.BTC} {loc.send.create.fee}: {this.state.fee} {BitcoinUnit.BTC}
</Text> </Text>
)} )}
{this.state.fee <= 0 && ( {this.state.fee <= 0 && (
<Text <Text numberOfLines={0} style={styles.feeText}>
numberOfLines={0}
style={{
color: '#37c0a1',
fontSize: 14,
marginHorizontal: 4,
paddingBottom: 6,
fontWeight: '500',
alignSelf: 'center',
}}
>
{this.state.invoiceDescription} {this.state.invoiceDescription}
</Text> </Text>
)} )}
</BlueCard> </BlueCard>
<View <View style={styles.ready}>
style={{
backgroundColor: '#ccddf9',
width: 120,
height: 120,
borderRadius: 60,
alignSelf: 'center',
justifyContent: 'center',
marginTop: 43,
marginBottom: 53,
}}
>
<Icon name="check" size={50} type="font-awesome" color="#0f5cc0" /> <Icon name="check" size={50} type="font-awesome" color="#0f5cc0" />
</View> </View>
<BlueCard> <BlueCard>

View file

@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ScrollView, Platform, TouchableWithoutFeedback, TouchableOpacity } from 'react-native'; import { ScrollView, Platform, TouchableWithoutFeedback, TouchableOpacity, StyleSheet } from 'react-native';
import { BlueLoading, BlueText, BlueSpacing20, BlueListItem, SafeBlueArea, BlueNavigationStyle, BlueCard } from '../../BlueComponents'; import { BlueLoading, BlueText, BlueSpacing20, BlueListItem, SafeBlueArea, BlueNavigationStyle, BlueCard } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { AppStorage } from '../../class'; import { AppStorage } from '../../class';
@ -8,6 +8,12 @@ import HandoffSettings from '../../class/handoff';
let BlueApp: AppStorage = require('../../BlueApp'); let BlueApp: AppStorage = require('../../BlueApp');
let loc = require('../../loc'); let loc = require('../../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
},
});
const GeneralSettings = () => { const GeneralSettings = () => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [isAdancedModeEnabled, setIsAdancedModeEnabled] = useState(false); const [isAdancedModeEnabled, setIsAdancedModeEnabled] = useState(false);
@ -34,7 +40,7 @@ const GeneralSettings = () => {
return isLoading ? ( return isLoading ? (
<BlueLoading /> <BlueLoading />
) : ( ) : (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView> <ScrollView>
{BlueApp.getWallets().length > 1 && ( {BlueApp.getWallets().length > 1 && (
<> <>

View file

@ -1,9 +1,15 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ScrollView, TouchableOpacity } from 'react-native'; import { ScrollView, TouchableOpacity, StyleSheet } from 'react-native';
import { BlueNavigationStyle, BlueLoading, SafeBlueArea, BlueListItem } from '../../BlueComponents'; import { BlueNavigationStyle, BlueLoading, SafeBlueArea, BlueListItem } from '../../BlueComponents';
import { useNavigation } from 'react-navigation-hooks'; import { useNavigation } from 'react-navigation-hooks';
const loc = require('../../loc'); const loc = require('../../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
},
});
const NetworkSettings = () => { const NetworkSettings = () => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const { navigate } = useNavigation(); const { navigate } = useNavigation();
@ -15,7 +21,7 @@ const NetworkSettings = () => {
return isLoading ? ( return isLoading ? (
<BlueLoading /> <BlueLoading />
) : ( ) : (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView> <ScrollView>
<BlueListItem title={'Electrum server'} component={TouchableOpacity} onPress={() => navigate('ElectrumSettings')} /> <BlueListItem title={'Electrum server'} component={TouchableOpacity} onPress={() => navigate('ElectrumSettings')} />
<BlueListItem title={loc.settings.lightning_settings} component={TouchableOpacity} onPress={() => navigate('LightningSettings')} /> <BlueListItem title={loc.settings.lightning_settings} component={TouchableOpacity} onPress={() => navigate('LightningSettings')} />

View file

@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ScrollView, Linking, Dimensions, Image, View, Text } from 'react-native'; import { ScrollView, Linking, Dimensions, Image, View, Text, StyleSheet } from 'react-native';
import { useNavigation } from 'react-navigation-hooks'; import { useNavigation } from 'react-navigation-hooks';
import { import {
BlueTextCentered, BlueTextCentered,
@ -17,6 +17,43 @@ import Rate, { AndroidMarket } from 'react-native-rate';
const { width, height } = Dimensions.get('window'); const { width, height } = Dimensions.get('window');
const loc = require('../../loc/'); const loc = require('../../loc/');
const styles = StyleSheet.create({
root: {
flex: 1,
},
center: {
justifyContent: 'center',
alignItems: 'center',
marginTop: 54,
},
logo: {
width: 102,
height: 124,
},
textFree: {
maxWidth: 260,
marginVertical: 24,
color: '#9AA0AA',
fontSize: 15,
textAlign: 'center',
fontWeight: '500',
},
textBackup: {
maxWidth: 260,
marginBottom: 40,
color: '#0C2550',
fontSize: 15,
textAlign: 'center',
fontWeight: '500',
},
buildWith: {
backgroundColor: '#f9f9f9',
padding: 16,
paddingTop: 0,
borderRadius: 8,
},
});
const About = () => { const About = () => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const { navigate } = useNavigation(); const { navigate } = useNavigation();
@ -68,23 +105,13 @@ const About = () => {
return isLoading ? ( return isLoading ? (
<BlueLoading /> <BlueLoading />
) : ( ) : (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<ScrollView testID="AboutScrollView"> <ScrollView testID="AboutScrollView">
<BlueCard> <BlueCard>
<View style={{ justifyContent: 'center', alignItems: 'center', marginTop: 54 }}> <View style={styles.center}>
<Image <Image style={styles.logo} source={require('../../img/bluebeast.png')} />
source={require('../../img/bluebeast.png')} <Text style={styles.textFree}>BlueWallet is a free and open source project. Crafted by Bitcoin users.</Text>
style={{ <Text style={styles.textBackup}>Always backup your keys!</Text>
width: 102,
height: 124,
}}
/>
<Text style={{ maxWidth: 260, marginVertical: 24, color: '#9AA0AA', fontSize: 15, textAlign: 'center', fontWeight: '500' }}>
BlueWallet is a free and open source project. Crafted by Bitcoin users.
</Text>
<Text style={{ maxWidth: 260, marginBottom: 40, color: '#0C2550', fontSize: 15, textAlign: 'center', fontWeight: '500' }}>
Always backup your keys!
</Text>
<BlueButton onPress={handleOnRatePress} title="help with a review ⭐🙏" /> <BlueButton onPress={handleOnRatePress} title="help with a review ⭐🙏" />
</View> </View>
</BlueCard> </BlueCard>
@ -116,7 +143,7 @@ const About = () => {
title="GitHub" title="GitHub"
/> />
<BlueCard> <BlueCard>
<View style={{ backgroundColor: '#f9f9f9', padding: 16, paddingTop: 0, borderRadius: 8 }}> <View style={styles.buildWith}>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueTextCentered>Built with the awesome 👍</BlueTextCentered> <BlueTextCentered>Built with the awesome 👍</BlueTextCentered>

View file

@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { FlatList, TouchableOpacity, ActivityIndicator, View } from 'react-native'; import { FlatList, TouchableOpacity, ActivityIndicator, View, StyleSheet } from 'react-native';
import { SafeBlueArea, BlueNavigationStyle, BlueListItem, BlueText, BlueCard } from '../../BlueComponents'; import { SafeBlueArea, BlueNavigationStyle, BlueListItem, BlueText, BlueCard } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
@ -9,6 +9,17 @@ let currency = require('../../currency');
const data = Object.values(FiatUnit); const data = Object.values(FiatUnit);
const styles = StyleSheet.create({
flex: {
flex: 1,
},
activity: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
const Currency = () => { const Currency = () => {
const [isSavingNewPreferredCurrency, setIsSavingNewPreferredCurrency] = useState(false); const [isSavingNewPreferredCurrency, setIsSavingNewPreferredCurrency] = useState(false);
const [selectedCurrency, setSelectedCurrency] = useState(null); const [selectedCurrency, setSelectedCurrency] = useState(null);
@ -30,9 +41,9 @@ const Currency = () => {
if (selectedCurrency !== null && selectedCurrency !== undefined) { if (selectedCurrency !== null && selectedCurrency !== undefined) {
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.flex}>
<FlatList <FlatList
style={{ flex: 1 }} style={styles.flex}
keyExtractor={(_item, index) => `${index}`} keyExtractor={(_item, index) => `${index}`}
data={data} data={data}
extraData={data} extraData={data}
@ -63,7 +74,7 @@ const Currency = () => {
); );
} }
return ( return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <View style={styles.activity}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
); );

View file

@ -1,10 +1,16 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { TouchableOpacity, View, TouchableWithoutFeedback } from 'react-native'; import { TouchableOpacity, View, TouchableWithoutFeedback, StyleSheet } from 'react-native';
import { SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle, BlueListItem } from '../../BlueComponents'; import { SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle, BlueListItem } from '../../BlueComponents';
import OnAppLaunch from '../../class/onAppLaunch'; import OnAppLaunch from '../../class/onAppLaunch';
import { useNavigation } from 'react-navigation-hooks'; import { useNavigation } from 'react-navigation-hooks';
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
const styles = StyleSheet.create({
flex: {
flex: 1,
},
});
const DefaultView = () => { const DefaultView = () => {
const [defaultWalletLabel, setDefaultWalletLabel] = useState(''); const [defaultWalletLabel, setDefaultWalletLabel] = useState('');
const [viewAllWalletsEnabled, setViewAllWalletsEnabled] = useState(true); const [viewAllWalletsEnabled, setViewAllWalletsEnabled] = useState(true);
@ -48,7 +54,7 @@ const DefaultView = () => {
}; };
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.flex}>
<View> <View>
<BlueListItem <BlueListItem
title="View All Wallets" title="View All Wallets"

View file

@ -1,6 +1,6 @@
/* global alert */ /* global alert */
import React, { Component } from 'react'; import React, { Component } from 'react';
import { View, TextInput } from 'react-native'; import { View, TextInput, StyleSheet } from 'react-native';
import { AppStorage } from '../../class'; import { AppStorage } from '../../class';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import { ScrollView } from 'react-native-gesture-handler'; import { ScrollView } from 'react-native-gesture-handler';
@ -9,6 +9,72 @@ import PropTypes from 'prop-types';
let loc = require('../../loc'); let loc = require('../../loc');
let BlueElectrum = require('../../BlueElectrum'); let BlueElectrum = require('../../BlueElectrum');
const styles = StyleSheet.create({
root: {
flex: 1,
},
status: {
textAlign: 'center',
color: '#9AA0AA',
marginBottom: 4,
},
connectWrap: {
width: 'auto',
height: 34,
flexWrap: 'wrap',
justifyContent: 'center',
flexDirection: 'row',
},
container: {
paddingTop: 6,
paddingBottom: 6,
paddingLeft: 16,
paddingRight: 16,
borderRadius: 20,
},
connectText: {
fontWeight: '600',
},
containerConnected: {
backgroundColor: '#D2F8D6',
},
containerDisconnected: {
backgroundColor: '#F8D2D2',
},
textConnected: {
color: '#37C0A1',
},
textDisconnected: {
color: '#D0021B',
},
hostname: {
textAlign: 'center',
color: '#0C2550',
},
explain: {
color: '#9AA0AA',
marginBottom: -24,
},
inputWrap: {
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
borderRadius: 4,
},
inputText: {
flex: 1,
marginHorizontal: 8,
minHeight: 36,
height: 36,
},
});
export default class ElectrumSettings extends Component { export default class ElectrumSettings extends Component {
static navigationOptions = () => ({ static navigationOptions = () => ({
...BlueNavigationStyle(), ...BlueNavigationStyle(),
@ -86,106 +152,58 @@ export default class ElectrumSettings extends Component {
render() { render() {
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView> <ScrollView>
<BlueCard> <BlueCard>
<BlueText style={{ textAlign: 'center', color: '#9AA0AA', marginBottom: 4 }}>Status</BlueText> <BlueText style={styles.status}>Status</BlueText>
<View style={{ width: 'auto', height: 34, flexWrap: 'wrap', justifyContent: 'center', flexDirection: 'row' }}> <View style={styles.connectWrap}>
<View <View style={[styles.container, this.state.config.status === 1 ? styles.containerConnected : styles.containerDisconnected]}>
style={{ <BlueText style={[styles.connectText, this.state.config.status === 1 ? styles.textConnected : styles.textDisconnected]}>
backgroundColor: this.state.config.status === 1 ? '#D2F8D6' : '#F8D2D2',
paddingTop: 6,
paddingBottom: 6,
paddingLeft: 16,
paddingRight: 16,
borderRadius: 20,
}}
>
<BlueText style={{ fontWeight: '600', color: this.state.config.status === 1 ? '#37C0A1' : '#D0021B' }}>
{(this.state.config.status === 1 && 'Connected') || 'Not Connected'} {(this.state.config.status === 1 && 'Connected') || 'Not Connected'}
</BlueText> </BlueText>
</View> </View>
</View> </View>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueText style={{ textAlign: 'center', color: '#0C2550' }} onPress={this.checkServer}> <BlueText style={styles.hostname} onPress={this.checkServer}>
{this.state.config.host}:{this.state.config.port} {this.state.config.host}:{this.state.config.port}
</BlueText> </BlueText>
<BlueSpacing20 /> <BlueSpacing20 />
</BlueCard> </BlueCard>
<BlueCard> <BlueCard>
<BlueText style={{ color: '#9AA0AA', marginBottom: -24 }}>{loc.settings.electrum_settings_explain}</BlueText> <BlueText style={styles.explain}>{loc.settings.electrum_settings_explain}</BlueText>
</BlueCard> </BlueCard>
<BlueCard> <BlueCard>
<View <View style={styles.inputWrap}>
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
borderRadius: 4,
}}
>
<TextInput <TextInput
placeholder={'host, for example 111.222.333.444'} placeholder={'host, for example 111.222.333.444'}
value={this.state.host} value={this.state.host}
onChangeText={text => this.setState({ host: text })} onChangeText={text => this.setState({ host: text })}
numberOfLines={1} numberOfLines={1}
style={{ flex: 1, marginHorizontal: 8, minHeight: 36, height: 36 }} style={styles.inputText}
editable={!this.state.isLoading} editable={!this.state.isLoading}
underlineColorAndroid="transparent" underlineColorAndroid="transparent"
/> />
</View> </View>
<BlueSpacing20 /> <BlueSpacing20 />
<View <View style={styles.inputWrap}>
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
borderRadius: 4,
}}
>
<TextInput <TextInput
placeholder={'TCP port, usually 50001'} placeholder={'TCP port, usually 50001'}
value={this.state.port} value={this.state.port}
onChangeText={text => this.setState({ port: text })} onChangeText={text => this.setState({ port: text })}
numberOfLines={1} numberOfLines={1}
style={{ flex: 1, marginHorizontal: 8, minHeight: 36, height: 36 }} style={styles.inputText}
editable={!this.state.isLoading} editable={!this.state.isLoading}
underlineColorAndroid="transparent" underlineColorAndroid="transparent"
/> />
</View> </View>
<BlueSpacing20 /> <BlueSpacing20 />
<View <View style={styles.inputWrap}>
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
borderRadius: 4,
}}
>
<TextInput <TextInput
placeholder={'SSL port, usually 50002'} placeholder={'SSL port, usually 50002'}
value={this.state.sslPort} value={this.state.sslPort}
onChangeText={text => this.setState({ sslPort: text })} onChangeText={text => this.setState({ sslPort: text })}
numberOfLines={1} numberOfLines={1}
style={{ flex: 1, marginHorizontal: 8, minHeight: 36, height: 36 }} style={styles.inputText}
editable={!this.state.isLoading} editable={!this.state.isLoading}
underlineColorAndroid="transparent" underlineColorAndroid="transparent"
/> />

View file

@ -1,6 +1,6 @@
/* global alert */ /* global alert */
import React, { Component } from 'react'; import React, { Component } from 'react';
import { ScrollView, Alert, Platform, TouchableOpacity, TouchableWithoutFeedback } from 'react-native'; import { ScrollView, Alert, Platform, TouchableOpacity, TouchableWithoutFeedback, StyleSheet } from 'react-native';
import { import {
BlueLoading, BlueLoading,
BlueHeaderDefaultSub, BlueHeaderDefaultSub,
@ -19,6 +19,12 @@ let BlueApp: AppStorage = require('../../BlueApp');
let prompt = require('../../prompt'); let prompt = require('../../prompt');
let loc = require('../../loc'); let loc = require('../../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
},
});
export default class EncryptStorage extends Component { export default class EncryptStorage extends Component {
static navigationOptions = () => ({ static navigationOptions = () => ({
...BlueNavigationStyle(), ...BlueNavigationStyle(),
@ -134,7 +140,7 @@ export default class EncryptStorage extends Component {
} }
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView> <ScrollView>
{this.state.biometrics.isDeviceBiometricCapable && ( {this.state.biometrics.isDeviceBiometricCapable && (
<> <>

View file

@ -1,10 +1,16 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { FlatList } from 'react-native'; import { FlatList, StyleSheet } from 'react-native';
import { BlueLoading, BlueText, SafeBlueArea, BlueListItem, BlueCard, BlueNavigationStyle } from '../../BlueComponents'; import { BlueLoading, BlueText, SafeBlueArea, BlueListItem, BlueCard, BlueNavigationStyle } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
let loc = require('../../loc'); let loc = require('../../loc');
const styles = StyleSheet.create({
flex: {
flex: 1,
},
});
export default class Language extends Component { export default class Language extends Component {
static navigationOptions = () => ({ static navigationOptions = () => ({
...BlueNavigationStyle(), ...BlueNavigationStyle(),
@ -78,9 +84,9 @@ export default class Language extends Component {
} }
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.flex}>
<FlatList <FlatList
style={{ flex: 1 }} style={styles.flex}
keyExtractor={(_item, index) => `${index}`} keyExtractor={(_item, index) => `${index}`}
data={this.state.availableLanguages} data={this.state.availableLanguages}
extraData={this.state.availableLanguages} extraData={this.state.availableLanguages}

View file

@ -1,8 +1,14 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { ScrollView } from 'react-native'; import { ScrollView, StyleSheet } from 'react-native';
import { BlueLoading, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle, BlueSpacing20 } from '../../BlueComponents'; import { BlueLoading, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle, BlueSpacing20 } from '../../BlueComponents';
/** @type {AppStorage} */ /** @type {AppStorage} */
const styles = StyleSheet.create({
root: {
flex: 1,
},
});
const Licensing = () => { const Licensing = () => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
@ -11,9 +17,9 @@ const Licensing = () => {
}, []); }, []);
return isLoading ? ( return isLoading ? (
(<BlueLoading />) <BlueLoading />
) : ( ) : (
(<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView> <ScrollView>
<BlueCard> <BlueCard>
<BlueText>MIT License</BlueText> <BlueText>MIT License</BlueText>
@ -41,7 +47,7 @@ const Licensing = () => {
</BlueText> </BlueText>
</BlueCard> </BlueCard>
</ScrollView> </ScrollView>
</SafeBlueArea>) </SafeBlueArea>
); );
}; };

View file

@ -1,6 +1,6 @@
/* global alert */ /* global alert */
import React, { Component } from 'react'; import React, { Component } from 'react';
import { View, TextInput, Linking } from 'react-native'; import { View, TextInput, Linking, StyleSheet } from 'react-native';
import { AppStorage } from '../../class'; import { AppStorage } from '../../class';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import { BlueLoading, BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueNavigationStyle, BlueText } from '../../BlueComponents'; import { BlueLoading, BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueNavigationStyle, BlueText } from '../../BlueComponents';
@ -11,6 +11,30 @@ import { LightningCustodianWallet } from '../../class/lightning-custodian-wallet
let BlueApp = require('../../BlueApp'); let BlueApp = require('../../BlueApp');
let loc = require('../../loc'); let loc = require('../../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
},
uri: {
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
borderRadius: 4,
},
uriText: {
flex: 1,
marginHorizontal: 8,
minHeight: 36,
height: 36,
},
});
export default class LightningSettings extends Component { export default class LightningSettings extends Component {
static navigationOptions = () => ({ static navigationOptions = () => ({
...BlueNavigationStyle(), ...BlueNavigationStyle(),
@ -53,7 +77,7 @@ export default class LightningSettings extends Component {
render() { render() {
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<BlueCard> <BlueCard>
<BlueText>{loc.settings.lightning_settings_explain}</BlueText> <BlueText>{loc.settings.lightning_settings_explain}</BlueText>
</BlueCard> </BlueCard>
@ -77,26 +101,13 @@ export default class LightningSettings extends Component {
/> />
<BlueCard> <BlueCard>
<View <View style={styles.uri}>
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
borderRadius: 4,
}}
>
<TextInput <TextInput
placeholder={LightningCustodianWallet.defaultBaseUri} placeholder={LightningCustodianWallet.defaultBaseUri}
value={this.state.URI} value={this.state.URI}
onChangeText={text => this.setState({ URI: text })} onChangeText={text => this.setState({ URI: text })}
numberOfLines={1} numberOfLines={1}
style={{ flex: 1, marginHorizontal: 8, minHeight: 36, height: 36 }} style={styles.uriText}
editable={!this.state.isLoading} editable={!this.state.isLoading}
underlineColorAndroid="transparent" underlineColorAndroid="transparent"
/> />

View file

@ -1,8 +1,14 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { ScrollView } from 'react-native'; import { ScrollView, StyleSheet } from 'react-native';
import { BlueLoading, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../../BlueComponents'; import { BlueLoading, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../../BlueComponents';
/** @type {AppStorage} */ /** @type {AppStorage} */
const styles = StyleSheet.create({
root: {
flex: 1,
},
});
const ReleaseNotes = () => { const ReleaseNotes = () => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const notes = require('../../release-notes'); const notes = require('../../release-notes');
@ -12,15 +18,15 @@ const ReleaseNotes = () => {
}, []); }, []);
return isLoading ? ( return isLoading ? (
(<BlueLoading />) <BlueLoading />
) : ( ) : (
(<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView> <ScrollView>
<BlueCard> <BlueCard>
<BlueText>{notes}</BlueText> <BlueText>{notes}</BlueText>
</BlueCard> </BlueCard>
</ScrollView> </ScrollView>
</SafeBlueArea>) </SafeBlueArea>
); );
}; };

View file

@ -1,9 +1,15 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ScrollView, TouchableOpacity } from 'react-native'; import { ScrollView, TouchableOpacity, StyleSheet } from 'react-native';
import { BlueNavigationStyle, BlueLoading, SafeBlueArea, BlueHeaderDefaultSub, BlueListItem } from '../../BlueComponents'; import { BlueNavigationStyle, BlueLoading, SafeBlueArea, BlueHeaderDefaultSub, BlueListItem } from '../../BlueComponents';
import { useNavigation } from 'react-navigation-hooks'; import { useNavigation } from 'react-navigation-hooks';
const loc = require('../../loc'); const loc = require('../../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
},
});
const Settings = () => { const Settings = () => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const { navigate } = useNavigation(); const { navigate } = useNavigation();
@ -15,7 +21,7 @@ const Settings = () => {
return isLoading ? ( return isLoading ? (
<BlueLoading /> <BlueLoading />
) : ( ) : (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView> <ScrollView>
<BlueHeaderDefaultSub leftText={loc.settings.header} rightComponent={null} /> <BlueHeaderDefaultSub leftText={loc.settings.header} rightComponent={null} />
<BlueListItem title={'General'} component={TouchableOpacity} onPress={() => navigate('GeneralSettings')} chevron /> <BlueListItem title={'General'} component={TouchableOpacity} onPress={() => navigate('GeneralSettings')} chevron />

View file

@ -1,6 +1,6 @@
/* global alert */ /* global alert */
import React, { Component } from 'react'; import React, { Component } from 'react';
import { ActivityIndicator, View, TextInput, TouchableOpacity, Linking, Clipboard, ScrollView } from 'react-native'; import { ActivityIndicator, View, TextInput, TouchableOpacity, Linking, Clipboard, ScrollView, StyleSheet } from 'react-native';
import { import {
BlueSpacing20, BlueSpacing20,
BlueReplaceFeeSuggestions, BlueReplaceFeeSuggestions,
@ -23,6 +23,60 @@ let loc = require('../../loc');
/** @type {AppStorage} */ /** @type {AppStorage} */
let BlueApp = require('../../BlueApp'); let BlueApp = require('../../BlueApp');
const styles = StyleSheet.create({
root: {
flex: 1,
paddingTop: 20,
},
explain: {
flex: 1,
paddingBottom: 16,
},
center: {
alignItems: 'center',
flex: 1,
},
hex: {
color: '#0c2550',
fontWeight: '500',
},
hexInput: {
borderColor: '#ebebeb',
backgroundColor: '#d2f8d6',
borderRadius: 4,
marginTop: 20,
color: '#37c0a1',
fontWeight: '500',
fontSize: 14,
paddingHorizontal: 16,
paddingBottom: 16,
paddingTop: 16,
},
action: {
marginVertical: 24,
},
actionText: {
color: '#9aa0aa',
fontSize: 15,
fontWeight: '500',
alignSelf: 'center',
},
doneWrap: {
flex: 1,
paddingTop: 19,
},
doneCard: {
flexDirection: 'row',
justifyContent: 'center',
paddingTop: 76,
paddingBottom: 16,
},
blueBigCheckmark: {
marginTop: 43,
marginBottom: 53,
},
});
export default class CPFP extends Component { export default class CPFP extends Component {
static navigationOptions = () => ({ static navigationOptions = () => ({
...BlueNavigationStyle(null, false), ...BlueNavigationStyle(null, false),
@ -116,7 +170,7 @@ export default class CPFP extends Component {
render() { render() {
if (this.state.isLoading) { if (this.state.isLoading) {
return ( return (
<View style={{ flex: 1, paddingTop: 20 }}> <View style={styles.root}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
); );
@ -132,7 +186,7 @@ export default class CPFP extends Component {
if (this.state.nonReplaceable) { if (this.state.nonReplaceable) {
return ( return (
<SafeBlueArea style={{ flex: 1, paddingTop: 20 }}> <SafeBlueArea style={styles.root}>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueSpacing20 /> <BlueSpacing20 />
<BlueSpacing20 /> <BlueSpacing20 />
@ -145,7 +199,7 @@ export default class CPFP extends Component {
} }
return ( return (
<SafeBlueArea style={{ flex: 1, paddingBottom: 16 }}> <SafeBlueArea style={styles.explain}>
<ScrollView> <ScrollView>
{this.renderStage1( {this.renderStage1(
'We will create another transaction that spends your unconfirmed transaction. The total fee will be higher than the original transaction fee, so it should be mined faster. This is called CPFP - Child Pays For Parent.', 'We will create another transaction that spends your unconfirmed transaction. The total fee will be higher than the original transaction fee, so it should be mined faster. This is called CPFP - Child Pays For Parent.',
@ -157,33 +211,16 @@ export default class CPFP extends Component {
renderStage2() { renderStage2() {
return ( return (
<View style={{ flex: 1, paddingTop: 20 }}> <View style={styles.root}>
<BlueCard style={{ alignItems: 'center', flex: 1 }}> <BlueCard style={styles.center}>
<BlueText style={{ color: '#0c2550', fontWeight: '500' }}>{loc.send.create.this_is_hex}</BlueText> <BlueText style={styles.hex}>{loc.send.create.this_is_hex}</BlueText>
<TextInput <TextInput style={styles.hexInput} height={112} multiline editable value={this.state.txhex} />
style={{
borderColor: '#ebebeb',
backgroundColor: '#d2f8d6',
borderRadius: 4,
marginTop: 20,
color: '#37c0a1',
fontWeight: '500',
fontSize: 14,
paddingHorizontal: 16,
paddingBottom: 16,
paddingTop: 16,
}}
height={112}
multiline
editable
value={this.state.txhex}
/>
<TouchableOpacity style={{ marginVertical: 24 }} onPress={() => Clipboard.setString(this.state.txhex)}> <TouchableOpacity style={styles.action} onPress={() => Clipboard.setString(this.state.txhex)}>
<Text style={{ color: '#9aa0aa', fontSize: 15, fontWeight: '500', alignSelf: 'center' }}>Copy and broadcast later</Text> <Text style={styles.actionText}>Copy and broadcast later</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={{ marginVertical: 24 }} onPress={() => Linking.openURL('https://coinb.in/?verify=' + this.state.txhex)}> <TouchableOpacity style={styles.action} onPress={() => Linking.openURL('https://coinb.in/?verify=' + this.state.txhex)}>
<Text style={{ color: '#9aa0aa', fontSize: 15, fontWeight: '500', alignSelf: 'center' }}>Verify on coinb.in</Text> <Text style={styles.actionText}>Verify on coinb.in</Text>
</TouchableOpacity> </TouchableOpacity>
<BlueButton onPress={() => this.broadcast()} title={loc.send.confirm.sendNow} /> <BlueButton onPress={() => this.broadcast()} title={loc.send.confirm.sendNow} />
</BlueCard> </BlueCard>
@ -193,11 +230,11 @@ export default class CPFP extends Component {
renderStage3() { renderStage3() {
return ( return (
<SafeBlueArea style={{ flex: 1, paddingTop: 19 }}> <SafeBlueArea style={styles.doneWrap}>
<BlueCard style={{ alignItems: 'center', flex: 1 }}> <BlueCard style={styles.center}>
<View style={{ flexDirection: 'row', justifyContent: 'center', paddingTop: 76, paddingBottom: 16 }} /> <View style={styles.doneCard} />
</BlueCard> </BlueCard>
<BlueBigCheckmark style={{ marginTop: 43, marginBottom: 53 }} /> <BlueBigCheckmark style={styles.blueBigCheckmark} />
<BlueCard> <BlueCard>
<BlueButton <BlueButton
onPress={() => { onPress={() => {
@ -212,9 +249,9 @@ export default class CPFP extends Component {
renderStage1(text) { renderStage1(text) {
return ( return (
<SafeBlueArea style={{ flex: 1, paddingTop: 20 }}> <SafeBlueArea style={styles.root}>
<BlueSpacing /> <BlueSpacing />
<BlueCard style={{ alignItems: 'center', flex: 1 }}> <BlueCard style={styles.center}>
<BlueText>{text}</BlueText> <BlueText>{text}</BlueText>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueReplaceFeeSuggestions onFeeSelected={fee => this.setState({ newFeeRate: fee })} transactionMinimum={this.state.feeRate} /> <BlueReplaceFeeSuggestions onFeeSelected={fee => this.setState({ newFeeRate: fee })} transactionMinimum={this.state.feeRate} />

View file

@ -1,6 +1,6 @@
/* global alert */ /* global alert */
import React from 'react'; import React from 'react';
import { ActivityIndicator, View, ScrollView } from 'react-native'; import { ActivityIndicator, View, ScrollView, StyleSheet } from 'react-native';
import { BlueSpacing20, SafeBlueArea, BlueText, BlueNavigationStyle } from '../../BlueComponents'; import { BlueSpacing20, SafeBlueArea, BlueText, BlueNavigationStyle } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from '../../class'; import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from '../../class';
@ -8,6 +8,13 @@ import CPFP from './CPFP';
/** @type {AppStorage} */ /** @type {AppStorage} */
let BlueApp = require('../../BlueApp'); let BlueApp = require('../../BlueApp');
const styles = StyleSheet.create({
root: {
flex: 1,
paddingTop: 16,
},
});
export default class RBFBumpFee extends CPFP { export default class RBFBumpFee extends CPFP {
static navigationOptions = () => ({ static navigationOptions = () => ({
...BlueNavigationStyle(null, false), ...BlueNavigationStyle(null, false),
@ -66,7 +73,7 @@ export default class RBFBumpFee extends CPFP {
render() { render() {
if (this.state.isLoading) { if (this.state.isLoading) {
return ( return (
<View style={{ flex: 1, paddingTop: 16 }}> <View style={styles.root}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
); );
@ -82,7 +89,7 @@ export default class RBFBumpFee extends CPFP {
if (this.state.nonReplaceable) { if (this.state.nonReplaceable) {
return ( return (
<SafeBlueArea style={{ flex: 1, paddingTop: 16 }}> <SafeBlueArea style={styles.root}>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueSpacing20 /> <BlueSpacing20 />
<BlueSpacing20 /> <BlueSpacing20 />
@ -95,7 +102,7 @@ export default class RBFBumpFee extends CPFP {
} }
return ( return (
<SafeBlueArea style={{ flex: 1, paddingBottom: 16 }}> <SafeBlueArea style={styles.root}>
<ScrollView> <ScrollView>
{this.renderStage1( {this.renderStage1(
'We will replace this transaction with the one with a higher fee, so it should be mined faster. This is called RBF - Replace By Fee.', 'We will replace this transaction with the one with a higher fee, so it should be mined faster. This is called RBF - Replace By Fee.',

View file

@ -1,6 +1,6 @@
/* global alert */ /* global alert */
import React from 'react'; import React from 'react';
import { ActivityIndicator, View } from 'react-native'; import { ActivityIndicator, View, StyleSheet } from 'react-native';
import { BlueSpacing20, SafeBlueArea, BlueText, BlueNavigationStyle } from '../../BlueComponents'; import { BlueSpacing20, SafeBlueArea, BlueText, BlueNavigationStyle } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from '../../class'; import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from '../../class';
@ -8,6 +8,13 @@ import CPFP from './CPFP';
/** @type {AppStorage} */ /** @type {AppStorage} */
let BlueApp = require('../../BlueApp'); let BlueApp = require('../../BlueApp');
const styles = StyleSheet.create({
common: {
flex: 1,
paddingTop: 20,
},
});
export default class RBFCancel extends CPFP { export default class RBFCancel extends CPFP {
static navigationOptions = () => ({ static navigationOptions = () => ({
...BlueNavigationStyle(null, false), ...BlueNavigationStyle(null, false),
@ -77,7 +84,7 @@ export default class RBFCancel extends CPFP {
render() { render() {
if (this.state.isLoading) { if (this.state.isLoading) {
return ( return (
<View style={{ flex: 1, paddingTop: 20 }}> <View style={styles.root}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
); );
@ -93,7 +100,7 @@ export default class RBFCancel extends CPFP {
if (this.state.nonReplaceable) { if (this.state.nonReplaceable) {
return ( return (
<SafeBlueArea style={{ flex: 1, paddingTop: 20 }}> <SafeBlueArea style={styles.root}>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueSpacing20 /> <BlueSpacing20 />
<BlueSpacing20 /> <BlueSpacing20 />

View file

@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { View, ScrollView, TouchableOpacity, Linking } from 'react-native'; import { View, ScrollView, TouchableOpacity, Linking, StyleSheet } from 'react-native';
import { import {
SafeBlueArea, SafeBlueArea,
BlueCard, BlueCard,
@ -18,6 +18,42 @@ let BlueApp = require('../../BlueApp');
let loc = require('../../loc'); let loc = require('../../loc');
const dayjs = require('dayjs'); const dayjs = require('dayjs');
const styles = StyleSheet.create({
root: {
flex: 1,
},
scroll: {
flex: 1,
},
rowHeader: {
flex: 1,
flexDirection: 'row',
marginBottom: 4,
justifyContent: 'space-between',
},
rowCaption: {
fontSize: 16,
fontWeight: '500',
marginBottom: 4,
},
rowValue: {
marginBottom: 26,
color: 'grey',
},
txId: {
fontSize: 16,
fontWeight: '500',
},
txHash: {
marginBottom: 8,
color: 'grey',
},
txLink: {
marginBottom: 26,
color: '#2f5fb3',
},
});
function onlyUnique(value, index, self) { function onlyUnique(value, index, self) {
return self.indexOf(value) === index; return self.indexOf(value) === index;
} }
@ -90,7 +126,7 @@ export default class TransactionsDetails extends Component {
} }
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
{this.state.isHandOffUseEnabled && ( {this.state.isHandOffUseEnabled && (
<Handoff <Handoff
title={`Bitcoin Transaction ${this.state.tx.hash}`} title={`Bitcoin Transaction ${this.state.tx.hash}`}
@ -99,7 +135,7 @@ export default class TransactionsDetails extends Component {
/> />
)} )}
<BlueHeaderDefaultSub leftText={loc.transactions.details.title} rightComponent={null} /> <BlueHeaderDefaultSub leftText={loc.transactions.details.title} rightComponent={null} />
<ScrollView style={{ flex: 1 }}> <ScrollView style={styles.scroll}>
<BlueCard> <BlueCard>
{(() => { {(() => {
if (BlueApp.tx_metadata[this.state.tx.hash]) { if (BlueApp.tx_metadata[this.state.tx.hash]) {
@ -116,40 +152,38 @@ export default class TransactionsDetails extends Component {
{this.state.hasOwnProperty('from') && ( {this.state.hasOwnProperty('from') && (
<React.Fragment> <React.Fragment>
<View style={{ flex: 1, flexDirection: 'row', marginBottom: 4, justifyContent: 'space-between' }}> <View style={styles.rowHeader}>
<BlueText style={{ fontSize: 16, fontWeight: '500', marginBottom: 4 }}>{loc.transactions.details.from}</BlueText> <BlueText style={styles.rowCaption}>{loc.transactions.details.from}</BlueText>
<BlueCopyToClipboardButton stringToCopy={this.state.from.filter(onlyUnique).join(', ')} /> <BlueCopyToClipboardButton stringToCopy={this.state.from.filter(onlyUnique).join(', ')} />
</View> </View>
<BlueText style={{ marginBottom: 26, color: 'grey' }}>{this.state.from.filter(onlyUnique).join(', ')}</BlueText> <BlueText style={styles.rowValue}>{this.state.from.filter(onlyUnique).join(', ')}</BlueText>
</React.Fragment> </React.Fragment>
)} )}
{this.state.hasOwnProperty('to') && ( {this.state.hasOwnProperty('to') && (
<React.Fragment> <React.Fragment>
<View style={{ flex: 1, flexDirection: 'row', marginBottom: 4, justifyContent: 'space-between' }}> <View style={styles.rowHeader}>
<BlueText style={{ fontSize: 16, fontWeight: '500', marginBottom: 4 }}>{loc.transactions.details.to}</BlueText> <BlueText style={styles.rowCaption}>{loc.transactions.details.to}</BlueText>
<BlueCopyToClipboardButton stringToCopy={this.state.to.filter(onlyUnique).join(', ')} /> <BlueCopyToClipboardButton stringToCopy={this.state.to.filter(onlyUnique).join(', ')} />
</View> </View>
<BlueText style={{ marginBottom: 26, color: 'grey' }}> <BlueText style={styles.rowValue}>{arrDiff(this.state.from, this.state.to.filter(onlyUnique)).join(', ')}</BlueText>
{arrDiff(this.state.from, this.state.to.filter(onlyUnique)).join(', ')}
</BlueText>
</React.Fragment> </React.Fragment>
)} )}
{this.state.tx.hasOwnProperty('fee') && ( {this.state.tx.hasOwnProperty('fee') && (
<React.Fragment> <React.Fragment>
<BlueText style={{ fontSize: 16, fontWeight: '500', marginBottom: 4 }}>{loc.send.create.fee}</BlueText> <BlueText style={styles.rowCaption}>{loc.send.create.fee}</BlueText>
<BlueText style={{ marginBottom: 26, color: 'grey' }}>{this.state.tx.fee + ' sats'}</BlueText> <BlueText style={styles.rowValue}>{this.state.tx.fee + ' sats'}</BlueText>
</React.Fragment> </React.Fragment>
)} )}
{this.state.tx.hasOwnProperty('hash') && ( {this.state.tx.hasOwnProperty('hash') && (
<React.Fragment> <React.Fragment>
<View style={{ flex: 1, flexDirection: 'row', marginBottom: 4, justifyContent: 'space-between' }}> <View style={styles.rowHeader}>
<BlueText style={{ fontSize: 16, fontWeight: '500' }}>Txid</BlueText> <BlueText style={styles.txId}>Txid</BlueText>
<BlueCopyToClipboardButton stringToCopy={this.state.tx.hash} /> <BlueCopyToClipboardButton stringToCopy={this.state.tx.hash} />
</View> </View>
<BlueText style={{ marginBottom: 8, color: 'grey' }}>{this.state.tx.hash}</BlueText> <BlueText style={styles.txHash}>{this.state.tx.hash}</BlueText>
<TouchableOpacity <TouchableOpacity
onPress={() => { onPress={() => {
const url = `https://blockstream.info/tx/${this.state.tx.hash}`; const url = `https://blockstream.info/tx/${this.state.tx.hash}`;
@ -160,36 +194,36 @@ export default class TransactionsDetails extends Component {
}); });
}} }}
> >
<BlueText style={{ marginBottom: 26, color: '#2f5fb3' }}>{loc.transactions.details.show_in_block_explorer}</BlueText> <BlueText style={styles.txLink}>{loc.transactions.details.show_in_block_explorer}</BlueText>
</TouchableOpacity> </TouchableOpacity>
</React.Fragment> </React.Fragment>
)} )}
{this.state.tx.hasOwnProperty('received') && ( {this.state.tx.hasOwnProperty('received') && (
<React.Fragment> <React.Fragment>
<BlueText style={{ fontSize: 16, fontWeight: '500', marginBottom: 4 }}>Received</BlueText> <BlueText style={styles.rowCaption}>Received</BlueText>
<BlueText style={{ marginBottom: 26, color: 'grey' }}>{dayjs(this.state.tx.received).format('MM/DD/YYYY h:mm A')}</BlueText> <BlueText style={styles.rowValue}>{dayjs(this.state.tx.received).format('MM/DD/YYYY h:mm A')}</BlueText>
</React.Fragment> </React.Fragment>
)} )}
{this.state.tx.hasOwnProperty('block_height') && this.state.tx.block_height > 0 && ( {this.state.tx.hasOwnProperty('block_height') && this.state.tx.block_height > 0 && (
<React.Fragment> <React.Fragment>
<BlueText style={{ fontSize: 16, fontWeight: '500', marginBottom: 4 }}>Block Height</BlueText> <BlueText style={styles.rowCaption}>Block Height</BlueText>
<BlueText style={{ marginBottom: 26, color: 'grey' }}>{this.state.tx.block_height}</BlueText> <BlueText style={styles.rowValue}>{this.state.tx.block_height}</BlueText>
</React.Fragment> </React.Fragment>
)} )}
{this.state.tx.hasOwnProperty('inputs') && ( {this.state.tx.hasOwnProperty('inputs') && (
<React.Fragment> <React.Fragment>
<BlueText style={{ fontSize: 16, fontWeight: '500', marginBottom: 4 }}>Inputs</BlueText> <BlueText style={styles.rowCaption}>Inputs</BlueText>
<BlueText style={{ marginBottom: 26, color: 'grey' }}>{this.state.tx.inputs.length}</BlueText> <BlueText style={styles.rowValue}>{this.state.tx.inputs.length}</BlueText>
</React.Fragment> </React.Fragment>
)} )}
{this.state.tx.hasOwnProperty('outputs') && this.state.tx.outputs.length > 0 && ( {this.state.tx.hasOwnProperty('outputs') && this.state.tx.outputs.length > 0 && (
<React.Fragment> <React.Fragment>
<BlueText style={{ fontSize: 16, fontWeight: '500', marginBottom: 4 }}>Outputs</BlueText> <BlueText style={styles.rowCaption}>Outputs</BlueText>
<BlueText style={{ marginBottom: 26, color: 'grey' }}>{this.state.tx.outputs.length}</BlueText> <BlueText style={styles.rowValue}>{this.state.tx.outputs.length}</BlueText>
</React.Fragment> </React.Fragment>
)} )}
</BlueCard> </BlueCard>

View file

@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { View, ActivityIndicator, Text, TouchableOpacity } from 'react-native'; import { View, ActivityIndicator, Text, TouchableOpacity, StyleSheet } from 'react-native';
import { import {
BlueButton, BlueButton,
SafeBlueArea, SafeBlueArea,
@ -28,6 +28,109 @@ const buttonStatus = Object.freeze({
notPossible: 3, notPossible: 3,
}); });
const styles = StyleSheet.create({
root: {
flex: 1,
},
container: {
flex: 1,
justifyContent: 'space-between',
},
center: {
alignItems: 'center',
},
value: {
color: '#2f5fb3',
fontSize: 36,
fontWeight: '600',
},
valueUnit: {
color: '#2f5fb3',
fontSize: 16,
fontWeight: '600',
},
memo: {
alignItems: 'center',
marginVertical: 8,
},
memoText: {
color: '#9aa0aa',
fontSize: 14,
},
iconRoot: {
backgroundColor: '#ccddf9',
width: 120,
height: 120,
borderRadius: 60,
alignSelf: 'center',
justifyContent: 'center',
marginTop: 43,
marginBottom: 53,
},
iconWrap: {
minWidth: 30,
minHeight: 30,
alignItems: 'center',
justifyContent: 'center',
alignSelf: 'flex-end',
borderRadius: 15,
},
margin: {
marginBottom: -40,
},
icon: {
width: 25,
},
fee: {
marginTop: 15,
marginBottom: 13,
},
feeText: {
fontSize: 11,
fontWeight: '500',
marginBottom: 4,
color: '#00c49f',
alignSelf: 'center',
},
confirmations: {
borderRadius: 11,
backgroundColor: '#eef0f4',
width: 109,
height: 21,
alignSelf: 'center',
alignItems: 'center',
justifyContent: 'center',
},
confirmationsText: {
color: '#9aa0aa',
fontSize: 11,
},
actions: {
alignSelf: 'center',
justifyContent: 'center',
},
cancel: {
marginVertical: 16,
},
cancelText: {
color: '#d0021b',
fontSize: 15,
fontWeight: '500',
textAlign: 'center',
},
details: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
marginBottom: 16,
},
detailsText: {
color: '#9aa0aa',
fontSize: 14,
marginRight: 8,
},
});
export default class TransactionsStatus extends Component { export default class TransactionsStatus extends Component {
static navigationOptions = () => ({ static navigationOptions = () => ({
...BlueNavigationStyle(), ...BlueNavigationStyle(),
@ -146,7 +249,7 @@ export default class TransactionsStatus extends Component {
} }
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
{this.state.isHandOffUseEnabled && ( {this.state.isHandOffUseEnabled && (
<Handoff <Handoff
title={`Bitcoin Transaction ${this.state.tx.hash}`} title={`Bitcoin Transaction ${this.state.tx.hash}`}
@ -154,13 +257,13 @@ export default class TransactionsStatus extends Component {
url={`https://blockstream.info/tx/${this.state.tx.hash}`} url={`https://blockstream.info/tx/${this.state.tx.hash}`}
/> />
)} )}
<View style={{ flex: 1, justifyContent: 'space-between' }}> <View style={styles.container}>
<BlueCard> <BlueCard>
<View style={{ alignItems: 'center' }}> <View style={styles.center}>
<Text style={{ color: '#2f5fb3', fontSize: 36, fontWeight: '600' }}> <Text style={styles.value}>
{loc.formatBalanceWithoutSuffix(this.state.tx.value, this.state.wallet.preferredBalanceUnit, true)}{' '} {loc.formatBalanceWithoutSuffix(this.state.tx.value, this.state.wallet.preferredBalanceUnit, true)}{' '}
{this.state.wallet.preferredBalanceUnit !== BitcoinUnit.LOCAL_CURRENCY && ( {this.state.wallet.preferredBalanceUnit !== BitcoinUnit.LOCAL_CURRENCY && (
<Text style={{ color: '#2f5fb3', fontSize: 16, fontWeight: '600' }}>{this.state.wallet.preferredBalanceUnit}</Text> <Text style={styles.valueUnit}>{this.state.wallet.preferredBalanceUnit}</Text>
)} )}
</Text> </Text>
</View> </View>
@ -169,8 +272,8 @@ export default class TransactionsStatus extends Component {
if (BlueApp.tx_metadata[this.state.tx.hash]) { if (BlueApp.tx_metadata[this.state.tx.hash]) {
if (BlueApp.tx_metadata[this.state.tx.hash]['memo']) { if (BlueApp.tx_metadata[this.state.tx.hash]['memo']) {
return ( return (
<View style={{ alignItems: 'center', marginVertical: 8 }}> <View style={styles.memo}>
<Text style={{ color: '#9aa0aa', fontSize: 14 }}>{BlueApp.tx_metadata[this.state.tx.hash]['memo']}</Text> <Text style={styles.memoText}>{BlueApp.tx_metadata[this.state.tx.hash]['memo']}</Text>
<BlueSpacing20 /> <BlueSpacing20 />
</View> </View>
); );
@ -178,48 +281,27 @@ export default class TransactionsStatus extends Component {
} }
})()} })()}
<View <View style={styles.iconRoot}>
style={{
backgroundColor: '#ccddf9',
width: 120,
height: 120,
borderRadius: 60,
alignSelf: 'center',
justifyContent: 'center',
marginTop: 43,
marginBottom: 53,
}}
>
<View> <View>
<Icon name="check" size={50} type="font-awesome" color="#0f5cc0" /> <Icon name="check" size={50} type="font-awesome" color="#0f5cc0" />
</View> </View>
<View <View style={[styles.iconWrap, styles.margin]}>
style={{
marginBottom: -40,
minWidth: 30,
minHeight: 30,
alignItems: 'center',
justifyContent: 'center',
alignSelf: 'flex-end',
borderRadius: 15,
}}
>
{(() => { {(() => {
if (!this.state.tx.confirmations) { if (!this.state.tx.confirmations) {
return ( return (
<View style={{ width: 25 }}> <View style={styles.icon}>
<BlueTransactionPendingIcon /> <BlueTransactionPendingIcon />
</View> </View>
); );
} else if (this.state.tx.value < 0) { } else if (this.state.tx.value < 0) {
return ( return (
<View style={{ width: 25 }}> <View style={styles.icon}>
<BlueTransactionOutgoingIcon /> <BlueTransactionOutgoingIcon />
</View> </View>
); );
} else { } else {
return ( return (
<View style={{ width: 25 }}> <View style={styles.icon}>
<BlueTransactionIncomingIcon /> <BlueTransactionIncomingIcon />
</View> </View>
); );
@ -229,8 +311,8 @@ export default class TransactionsStatus extends Component {
</View> </View>
{this.state.tx.hasOwnProperty('fee') && ( {this.state.tx.hasOwnProperty('fee') && (
<View style={{ marginTop: 15, marginBottom: 13 }}> <View style={styles.fee}>
<BlueText style={{ fontSize: 11, fontWeight: '500', marginBottom: 4, color: '#00c49f', alignSelf: 'center' }}> <BlueText style={styles.feeText}>
{loc.send.create.fee.toLowerCase()}{' '} {loc.send.create.fee.toLowerCase()}{' '}
{loc.formatBalanceWithoutSuffix(this.state.tx.fee, this.state.wallet.preferredBalanceUnit, true)}{' '} {loc.formatBalanceWithoutSuffix(this.state.tx.fee, this.state.wallet.preferredBalanceUnit, true)}{' '}
{this.state.wallet.preferredBalanceUnit !== BitcoinUnit.LOCAL_CURRENCY && this.state.wallet.preferredBalanceUnit} {this.state.wallet.preferredBalanceUnit !== BitcoinUnit.LOCAL_CURRENCY && this.state.wallet.preferredBalanceUnit}
@ -238,24 +320,14 @@ export default class TransactionsStatus extends Component {
</View> </View>
)} )}
<View <View style={styles.confirmations}>
style={{ <Text style={styles.confirmationsText}>
borderRadius: 11,
backgroundColor: '#eef0f4',
width: 109,
height: 21,
alignSelf: 'center',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Text style={{ color: '#9aa0aa', fontSize: 11 }}>
{this.state.tx.confirmations > 6 ? '6+' : this.state.tx.confirmations} confirmations {this.state.tx.confirmations > 6 ? '6+' : this.state.tx.confirmations} confirmations
</Text> </Text>
</View> </View>
</BlueCard> </BlueCard>
<View style={{ alignSelf: 'center', justifyContent: 'center' }}> <View style={styles.actions}>
{(() => { {(() => {
if (this.state.isCPFPpossible === buttonStatus.unknown) { if (this.state.isCPFPpossible === buttonStatus.unknown) {
return ( return (
@ -316,7 +388,7 @@ export default class TransactionsStatus extends Component {
} else if (this.state.isRBFCancelPossible === buttonStatus.possible) { } else if (this.state.isRBFCancelPossible === buttonStatus.possible) {
return ( return (
<React.Fragment> <React.Fragment>
<TouchableOpacity style={{ marginVertical: 16 }}> <TouchableOpacity style={styles.cancel}>
<Text <Text
onPress={() => onPress={() =>
this.props.navigation.navigate('RBFCancel', { this.props.navigation.navigate('RBFCancel', {
@ -324,7 +396,7 @@ export default class TransactionsStatus extends Component {
wallet: this.state.wallet, wallet: this.state.wallet,
}) })
} }
style={{ color: '#d0021b', fontSize: 15, fontWeight: '500', textAlign: 'center' }} style={styles.cancelText}
> >
{'Cancel Transaction'} {'Cancel Transaction'}
</Text> </Text>
@ -335,10 +407,10 @@ export default class TransactionsStatus extends Component {
})()} })()}
<TouchableOpacity <TouchableOpacity
style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center', marginBottom: 16 }} style={styles.details}
onPress={() => this.props.navigation.navigate('TransactionDetails', { hash: this.state.tx.hash })} onPress={() => this.props.navigation.navigate('TransactionDetails', { hash: this.state.tx.hash })}
> >
<Text style={{ color: '#9aa0aa', fontSize: 14, marginRight: 8 }}>{loc.send.create.details.toLowerCase()}</Text> <Text style={styles.detailsText}>{loc.send.create.details.toLowerCase()}</Text>
<Icon name="angle-right" size={18} type="font-awesome" color="#9aa0aa" /> <Icon name="angle-right" size={18} type="font-awesome" color="#9aa0aa" />
</TouchableOpacity> </TouchableOpacity>
</View> </View>

View file

@ -10,6 +10,7 @@ import {
Platform, Platform,
View, View,
TextInput, TextInput,
StyleSheet,
} from 'react-native'; } from 'react-native';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import { import {
@ -35,6 +36,83 @@ let EV = require('../../events');
let A = require('../../analytics'); let A = require('../../analytics');
let BlueApp: AppStorage = require('../../BlueApp'); let BlueApp: AppStorage = require('../../BlueApp');
let loc = require('../../loc'); let loc = require('../../loc');
const styles = StyleSheet.create({
loading: {
flex: 1,
paddingTop: 20,
},
label: {
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 16,
borderRadius: 4,
},
textInputCommon: {
flex: 1,
marginHorizontal: 8,
color: '#81868e',
},
buttons: {
flexDirection: 'row',
justifyContent: 'space-between',
paddingTop: 10,
marginHorizontal: 20,
borderWidth: 0,
minHeight: 100,
},
button: {
width: '45%',
height: 88,
},
or: {
borderWidth: 0,
justifyContent: 'center',
marginHorizontal: 8,
alignSelf: 'center',
},
orCenter: {
color: '#0c2550',
},
advanced: {
marginHorizontal: 20,
},
advancedText: {
color: '#0c2550',
fontWeight: '500',
},
lndUri: {
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
marginVertical: 16,
borderRadius: 4,
},
createButton: {
alignItems: 'center',
flex: 1,
marginTop: 32,
},
import: {
marginBottom: 0,
marginTop: 24,
},
});
export default class WalletsAdd extends Component { export default class WalletsAdd extends Component {
static navigationOptions = ({ navigation }) => ({ static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true), ...BlueNavigationStyle(navigation, true),
@ -85,7 +163,7 @@ export default class WalletsAdd extends Component {
render() { render() {
if (this.state.isLoading) { if (this.state.isLoading) {
return ( return (
<View style={{ flex: 1, paddingTop: 20 }}> <View style={styles.loading}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
); );
@ -96,22 +174,7 @@ export default class WalletsAdd extends Component {
<ScrollView> <ScrollView>
<KeyboardAvoidingView enabled behavior={Platform.OS === 'ios' ? 'padding' : null} keyboardVerticalOffset={62}> <KeyboardAvoidingView enabled behavior={Platform.OS === 'ios' ? 'padding' : null} keyboardVerticalOffset={62}>
<BlueFormLabel>{loc.wallets.add.wallet_name}</BlueFormLabel> <BlueFormLabel>{loc.wallets.add.wallet_name}</BlueFormLabel>
<View <View style={styles.label}>
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 16,
borderRadius: 4,
}}
>
<TextInput <TextInput
testID="WalletNameInput" testID="WalletNameInput"
value={this.state.label} value={this.state.label}
@ -120,23 +183,14 @@ export default class WalletsAdd extends Component {
onChangeText={text => { onChangeText={text => {
this.setLabel(text); this.setLabel(text);
}} }}
style={{ flex: 1, marginHorizontal: 8, color: '#81868e' }} style={styles.textInputCommon}
editable={!this.state.isLoading} editable={!this.state.isLoading}
underlineColorAndroid="transparent" underlineColorAndroid="transparent"
/> />
</View> </View>
<BlueFormLabel>{loc.wallets.add.wallet_type}</BlueFormLabel> <BlueFormLabel>{loc.wallets.add.wallet_type}</BlueFormLabel>
<View <View style={styles.buttons}>
style={{
flexDirection: 'row',
justifyContent: 'space-between',
paddingTop: 10,
marginHorizontal: 20,
borderWidth: 0,
minHeight: 100,
}}
>
<BitcoinButton <BitcoinButton
testID="ActivateBitcoinButton" testID="ActivateBitcoinButton"
active={this.state.activeBitcoin} active={this.state.activeBitcoin}
@ -147,13 +201,10 @@ export default class WalletsAdd extends Component {
activeLightning: false, activeLightning: false,
}); });
}} }}
style={{ style={styles.button}
width: '45%',
height: 88,
}}
/> />
<View style={{ borderWidth: 0, justifyContent: 'center', marginHorizontal: 8, alignSelf: 'center' }}> <View style={styles.or}>
<BlueTextCentered style={{ color: '#0c2550' }}>{loc.wallets.add.or}</BlueTextCentered> <BlueTextCentered style={styles.orCenter}>{loc.wallets.add.or}</BlueTextCentered>
</View> </View>
<LightningButton <LightningButton
active={this.state.activeLightning} active={this.state.activeLightning}
@ -164,20 +215,17 @@ export default class WalletsAdd extends Component {
activeLightning: true, activeLightning: true,
}); });
}} }}
style={{ style={styles.button}
width: '45%',
height: 88,
}}
/> />
</View> </View>
<View style={{ marginHorizontal: 20 }}> <View style={styles.advanced}>
{(() => { {(() => {
if (this.state.activeBitcoin && this.state.isAdvancedOptionsEnabled) { if (this.state.activeBitcoin && this.state.isAdvancedOptionsEnabled) {
return ( return (
<View> <View>
<BlueSpacing20 /> <BlueSpacing20 />
<Text style={{ color: '#0c2550', fontWeight: '500' }}>{loc.settings.advanced_options}</Text> <Text style={styles.advancedText}>{loc.settings.advanced_options}</Text>
<BlueListItem <BlueListItem
onPress={() => { onPress={() => {
this.onSelect(0, HDSegwitBech32Wallet.type); this.onSelect(0, HDSegwitBech32Wallet.type);
@ -217,24 +265,10 @@ export default class WalletsAdd extends Component {
return ( return (
<React.Fragment> <React.Fragment>
<BlueSpacing20 /> <BlueSpacing20 />
<Text style={{ color: '#0c2550', fontWeight: '500' }}>{loc.settings.advanced_options}</Text> <Text style={styles.advancedText}>{loc.settings.advanced_options}</Text>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueText>Connect to your LNDHub</BlueText> <BlueText>Connect to your LNDHub</BlueText>
<View <View style={styles.lndUri}>
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
marginVertical: 16,
borderRadius: 4,
}}
>
<TextInput <TextInput
value={this.state.walletBaseURI} value={this.state.walletBaseURI}
onChangeText={text => { onChangeText={text => {
@ -245,7 +279,7 @@ export default class WalletsAdd extends Component {
clearButtonMode="while-editing" clearButtonMode="while-editing"
autoCapitalize="none" autoCapitalize="none"
placeholderTextColor="#81868e" placeholderTextColor="#81868e"
style={{ flex: 1, marginHorizontal: 8, color: '#81868e' }} style={styles.textInputCommon}
editable={!this.state.isLoading} editable={!this.state.isLoading}
underlineColorAndroid="transparent" underlineColorAndroid="transparent"
/> />
@ -256,13 +290,7 @@ export default class WalletsAdd extends Component {
return <View />; return <View />;
} }
})()} })()}
<View <View style={styles.createButton}>
style={{
alignItems: 'center',
flex: 1,
marginTop: 32,
}}
>
{!this.state.isLoading ? ( {!this.state.isLoading ? (
<BlueButton <BlueButton
testID="Create" testID="Create"
@ -352,7 +380,7 @@ export default class WalletsAdd extends Component {
</View> </View>
<BlueButtonLink <BlueButtonLink
testID="ImportWallet" testID="ImportWallet"
style={{ marginBottom: 0, marginTop: 24 }} style={styles.import}
title={loc.wallets.add.import_wallet} title={loc.wallets.add.import_wallet}
onPress={() => { onPress={() => {
this.props.navigation.navigate('ImportWallet'); this.props.navigation.navigate('ImportWallet');

View file

@ -1,4 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { StyleSheet } from 'react-native';
import { BlueNavigationStyle, BlueLoading, SafeBlueArea } from '../../BlueComponents'; import { BlueNavigationStyle, BlueLoading, SafeBlueArea } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { WebView } from 'react-native-webview'; import { WebView } from 'react-native-webview';
@ -7,6 +8,12 @@ const currency = require('../../currency');
let BlueApp: AppStorage = require('../../BlueApp'); let BlueApp: AppStorage = require('../../BlueApp');
let loc = require('../../loc'); let loc = require('../../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
},
});
export default class BuyBitcoin extends Component { export default class BuyBitcoin extends Component {
static navigationOptions = ({ navigation }) => ({ static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true), ...BlueNavigationStyle(navigation, true),
@ -90,7 +97,7 @@ export default class BuyBitcoin extends Component {
} }
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<WebView <WebView
source={{ source={{
uri, uri,

View file

@ -13,6 +13,7 @@ import {
Switch, Switch,
Platform, Platform,
Linking, Linking,
StyleSheet,
} from 'react-native'; } from 'react-native';
import { BlueButton, SafeBlueArea, BlueCard, BlueSpacing20, BlueNavigationStyle, BlueText } from '../../BlueComponents'; import { BlueButton, SafeBlueArea, BlueCard, BlueSpacing20, BlueNavigationStyle, BlueText } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
@ -30,6 +31,74 @@ const prompt = require('../../prompt');
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
const loc = require('../../loc'); const loc = require('../../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
},
scrollViewContent: {
flexGrow: 1,
},
save: {
marginHorizontal: 16,
justifyContent: 'center',
alignItems: 'center',
},
saveText: {
color: '#0c2550',
},
address: {
alignItems: 'center',
flex: 1,
},
textLabel1: {
color: '#0c2550',
fontWeight: '500',
fontSize: 14,
marginVertical: 12,
},
textLabel2: {
color: '#0c2550',
fontWeight: '500',
fontSize: 14,
marginVertical: 16,
},
textValue: {
color: '#81868e',
fontWeight: '500',
fontSize: 14,
},
input: {
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
borderRadius: 4,
},
inputText: {
flex: 1,
marginHorizontal: 8,
minHeight: 33,
},
hardware: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
center: {
alignItems: 'center',
},
delete: {
color: '#d0021b',
fontSize: 15,
fontWeight: '500',
},
});
export default class WalletDetails extends Component { export default class WalletDetails extends Component {
static navigationOptions = ({ navigation }) => ({ static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(), ...BlueNavigationStyle(),
@ -37,14 +106,14 @@ export default class WalletDetails extends Component {
headerRight: ( headerRight: (
<TouchableOpacity <TouchableOpacity
disabled={navigation.getParam('isLoading') === true} disabled={navigation.getParam('isLoading') === true}
style={{ marginHorizontal: 16, justifyContent: 'center', alignItems: 'center' }} style={styles.save}
onPress={() => { onPress={() => {
if (navigation.state.params.saveAction) { if (navigation.state.params.saveAction) {
navigation.getParam('saveAction')(); navigation.getParam('saveAction')();
} }
}} }}
> >
<Text style={{ color: '#0c2550' }}>{loc.wallets.details.save}</Text> <Text style={styles.saveText}>{loc.wallets.details.save}</Text>
</TouchableOpacity> </TouchableOpacity>
), ),
}); });
@ -143,17 +212,17 @@ export default class WalletDetails extends Component {
render() { render() {
if (this.state.isLoading) { if (this.state.isLoading) {
return ( return (
<View style={{ flex: 1 }}> <View style={styles.root}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
); );
} }
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}> <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<KeyboardAvoidingView behavior="position"> <KeyboardAvoidingView behavior="position">
<ScrollView contentContainerStyle={{ flexGrow: 1 }}> <ScrollView contentContainerStyle={styles.scrollViewContent}>
<BlueCard style={{ alignItems: 'center', flex: 1 }}> <BlueCard style={styles.address}>
{(() => { {(() => {
if ( if (
[LegacyWallet.type, SegwitBech32Wallet.type, SegwitP2SHWallet.type].includes(this.state.wallet.type) || [LegacyWallet.type, SegwitBech32Wallet.type, SegwitP2SHWallet.type].includes(this.state.wallet.type) ||
@ -161,32 +230,15 @@ export default class WalletDetails extends Component {
) { ) {
return ( return (
<React.Fragment> <React.Fragment>
<Text style={{ color: '#0c2550', fontWeight: '500', fontSize: 14, marginVertical: 12 }}> <Text style={styles.textLabel1}>{loc.wallets.details.address.toLowerCase()}</Text>
{loc.wallets.details.address.toLowerCase()} <Text style={styles.textValue}>{this.state.wallet.getAddress()}</Text>
</Text>
<Text style={{ color: '#81868e', fontWeight: '500', fontSize: 14 }}>{this.state.wallet.getAddress()}</Text>
</React.Fragment> </React.Fragment>
); );
} }
})()} })()}
<Text style={{ color: '#0c2550', fontWeight: '500', fontSize: 14, marginVertical: 16 }}> <Text style={styles.textLabel2}>{loc.wallets.add.wallet_name.toLowerCase()}</Text>
{loc.wallets.add.wallet_name.toLowerCase()}
</Text>
<View <View style={styles.input}>
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
borderRadius: 4,
}}
>
<TextInput <TextInput
placeholder={loc.send.details.note_placeholder} placeholder={loc.send.details.note_placeholder}
value={this.state.walletName} value={this.state.walletName}
@ -200,21 +252,17 @@ export default class WalletDetails extends Component {
} }
}} }}
numberOfLines={1} numberOfLines={1}
style={{ flex: 1, marginHorizontal: 8, minHeight: 33 }} style={styles.inputText}
editable={!this.state.isLoading} editable={!this.state.isLoading}
underlineColorAndroid="transparent" underlineColorAndroid="transparent"
/> />
</View> </View>
<BlueSpacing20 /> <BlueSpacing20 />
<Text style={{ color: '#0c2550', fontWeight: '500', fontSize: 14, marginVertical: 12 }}> <Text style={styles.textLabel1}>{loc.wallets.details.type.toLowerCase()}</Text>
{loc.wallets.details.type.toLowerCase()} <Text style={styles.textValue}>{this.state.wallet.typeReadable}</Text>
</Text>
<Text style={{ color: '#81868e', fontWeight: '500', fontSize: 14 }}>{this.state.wallet.typeReadable}</Text>
{this.state.wallet.type === LightningCustodianWallet.type && ( {this.state.wallet.type === LightningCustodianWallet.type && (
<React.Fragment> <React.Fragment>
<Text style={{ color: '#0c2550', fontWeight: '500', fontSize: 14, marginVertical: 12 }}> <Text style={styles.textLabel1}>{loc.wallets.details.connected_to.toLowerCase()}</Text>
{loc.wallets.details.connected_to.toLowerCase()}
</Text>
<BlueText>{this.state.wallet.getBaseURI()}</BlueText> <BlueText>{this.state.wallet.getBaseURI()}</BlueText>
</React.Fragment> </React.Fragment>
)} )}
@ -222,10 +270,8 @@ export default class WalletDetails extends Component {
<BlueSpacing20 /> <BlueSpacing20 />
{this.state.wallet.type === WatchOnlyWallet.type && this.state.wallet.getSecret().startsWith('zpub') && ( {this.state.wallet.type === WatchOnlyWallet.type && this.state.wallet.getSecret().startsWith('zpub') && (
<> <>
<Text style={{ color: '#0c2550', fontWeight: '500', fontSize: 14, marginVertical: 16 }}> <Text style={styles.textLabel2}>{loc.wallets.details.advanced.toLowerCase()}</Text>
{loc.wallets.details.advanced.toLowerCase()} <View style={styles.hardware}>
</Text>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
<BlueText>{loc.wallets.details.use_with_hardware_wallet}</BlueText> <BlueText>{loc.wallets.details.use_with_hardware_wallet}</BlueText>
<Switch <Switch
value={this.state.useWithHardwareWallet} value={this.state.useWithHardwareWallet}
@ -233,12 +279,8 @@ export default class WalletDetails extends Component {
/> />
</View> </View>
<React.Fragment> <React.Fragment>
<Text style={{ color: '#0c2550', fontWeight: '500', fontSize: 14, marginVertical: 12 }}> <Text style={styles.textLabel1}>{loc.wallets.details.master_fingerprint.toLowerCase()}</Text>
{loc.wallets.details.master_fingerprint.toLowerCase()} <Text style={styles.textValue}>{this.state.wallet.getMasterFingerprintHex()}</Text>
</Text>
<Text style={{ color: '#81868e', fontWeight: '500', fontSize: 14 }}>
{this.state.wallet.getMasterFingerprintHex()}
</Text>
</React.Fragment> </React.Fragment>
<BlueSpacing20 /> <BlueSpacing20 />
</> </>
@ -281,7 +323,7 @@ export default class WalletDetails extends Component {
)} )}
<BlueSpacing20 /> <BlueSpacing20 />
<TouchableOpacity <TouchableOpacity
style={{ alignItems: 'center' }} style={styles.center}
onPress={() => { onPress={() => {
ReactNativeHapticFeedback.trigger('notificationWarning', { ignoreAndroidSystemSettings: false }); ReactNativeHapticFeedback.trigger('notificationWarning', { ignoreAndroidSystemSettings: false });
Alert.alert( Alert.alert(
@ -319,7 +361,7 @@ export default class WalletDetails extends Component {
); );
}} }}
> >
<Text style={{ color: '#d0021b', fontSize: 15, fontWeight: '500' }}>{loc.wallets.details.delete}</Text> <Text style={styles.delete}>{loc.wallets.details.delete}</Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</BlueCard> </BlueCard>

View file

@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Dimensions, ScrollView, ActivityIndicator, View } from 'react-native'; import { Dimensions, ScrollView, ActivityIndicator, View, StyleSheet } from 'react-native';
import QRCode from 'react-native-qrcode-svg'; import QRCode from 'react-native-qrcode-svg';
import { BlueSpacing20, SafeBlueArea, BlueNavigationStyle, BlueText, BlueCopyTextToClipboard, BlueCard } from '../../BlueComponents'; import { BlueSpacing20, SafeBlueArea, BlueNavigationStyle, BlueText, BlueCopyTextToClipboard, BlueCard } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
@ -11,6 +11,33 @@ let BlueApp = require('../../BlueApp');
let loc = require('../../loc'); let loc = require('../../loc');
const { height, width } = Dimensions.get('window'); const { height, width } = Dimensions.get('window');
const styles = StyleSheet.create({
loading: {
flex: 1,
paddingTop: 20,
},
root: {
flex: 1,
},
scrollViewContent: {
alignItems: 'center',
justifyContent: 'center',
flexGrow: 1,
},
type: {
fontSize: 17,
fontWeight: '700',
color: '#0c2550',
},
secret: {
alignItems: 'center',
paddingHorizontal: 16,
fontSize: 16,
color: '#0C2550',
lineHeight: 24,
},
});
export default class WalletExport extends Component { export default class WalletExport extends Component {
static navigationOptions = ({ navigation }) => ({ static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true), ...BlueNavigationStyle(navigation, true),
@ -61,17 +88,17 @@ export default class WalletExport extends Component {
render() { render() {
if (this.state.isLoading) { if (this.state.isLoading) {
return ( return (
<View style={{ flex: 1, paddingTop: 20 }} onLayout={this.onLayout}> <View style={styles.loading} onLayout={this.onLayout}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
); );
} }
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<ScrollView contentContainerStyle={{ alignItems: 'center', justifyContent: 'center', flexGrow: 1 }} onLayout={this.onLayout}> <ScrollView contentContainerStyle={styles.scrollViewContent} onLayout={this.onLayout}>
<View> <View>
<BlueText style={{ fontSize: 17, fontWeight: '700', color: '#0c2550' }}>{this.state.wallet.typeReadable}</BlueText> <BlueText style={styles.type}>{this.state.wallet.typeReadable}</BlueText>
</View> </View>
{(() => { {(() => {
@ -99,9 +126,7 @@ export default class WalletExport extends Component {
{this.state.wallet.type === LightningCustodianWallet.type || this.state.wallet.type === WatchOnlyWallet.type ? ( {this.state.wallet.type === LightningCustodianWallet.type || this.state.wallet.type === WatchOnlyWallet.type ? (
<BlueCopyTextToClipboard text={this.state.wallet.getSecret()} /> <BlueCopyTextToClipboard text={this.state.wallet.getSecret()} />
) : ( ) : (
<BlueText style={{ alignItems: 'center', paddingHorizontal: 16, fontSize: 16, color: '#0C2550', lineHeight: 24 }}> <BlueText style={styles.secret}>{this.state.wallet.getSecret()}</BlueText>
{this.state.wallet.getSecret()}
</BlueText>
)} )}
</ScrollView> </ScrollView>
</SafeBlueArea> </SafeBlueArea>

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
/* global alert */ /* global alert */
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Platform, Dimensions, View, Keyboard } from 'react-native'; import { Platform, Dimensions, View, Keyboard, StyleSheet } from 'react-native';
import { import {
BlueFormMultiInput, BlueFormMultiInput,
BlueButtonLink, BlueButtonLink,
@ -18,6 +18,17 @@ import WalletImport from '../../class/walletImport';
let loc = require('../../loc'); let loc = require('../../loc');
const { width } = Dimensions.get('window'); const { width } = Dimensions.get('window');
const styles = StyleSheet.create({
root: {
flex: 1,
paddingTop: 40,
},
center: {
flex: 1,
alignItems: 'center',
},
});
const WalletsImport = () => { const WalletsImport = () => {
const [isToolbarVisibleForAndroid, setIsToolbarVisibleForAndroid] = useState(false); const [isToolbarVisibleForAndroid, setIsToolbarVisibleForAndroid] = useState(false);
const [importText, setImportText] = useState(useNavigationParam('label') || ''); const [importText, setImportText] = useState(useNavigationParam('label') || '');
@ -67,7 +78,7 @@ const WalletsImport = () => {
}; };
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1, paddingTop: 40 }}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<BlueFormLabel>{loc.wallets.import.explanation}</BlueFormLabel> <BlueFormLabel>{loc.wallets.import.explanation}</BlueFormLabel>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueFormMultiInput <BlueFormMultiInput
@ -79,7 +90,7 @@ const WalletsImport = () => {
/> />
<BlueSpacing20 /> <BlueSpacing20 />
<View style={{ flex: 1, alignItems: 'center' }}> <View style={styles.center}>
<BlueButton <BlueButton
testID="DoImport" testID="DoImport"
disabled={importText.trim().length === 0} disabled={importText.trim().length === 0}

View file

@ -257,18 +257,8 @@ export default class WalletsList extends Component {
renderListHeaderComponent = () => { renderListHeaderComponent = () => {
return ( return (
<View style={{ backgroundColor: '#FFFFFF' }}> <View style={styles.listHeader}>
<Text <Text style={styles.listHeaderText}>{loc.transactions.list.title}</Text>
style={{
paddingLeft: 16,
fontWeight: 'bold',
fontSize: 24,
marginVertical: 8,
color: BlueApp.settings.foregroundColor,
}}
>
{loc.transactions.list.title}
</Text>
</View> </View>
); );
}; };
@ -283,7 +273,7 @@ export default class WalletsList extends Component {
renderTransactionListsRow = data => { renderTransactionListsRow = data => {
return ( return (
<View style={{ marginHorizontal: 4 }}> <View style={styles.transaction}>
<BlueTransactionListItem item={data.item} itemPriceUnit={data.item.walletPreferredBalanceUnit} /> <BlueTransactionListItem item={data.item} itemPriceUnit={data.item.walletPreferredBalanceUnit} />
</View> </View>
); );
@ -292,11 +282,7 @@ export default class WalletsList extends Component {
renderNavigationHeader = () => { renderNavigationHeader = () => {
return ( return (
<View style={styles.headerStyle}> <View style={styles.headerStyle}>
<TouchableOpacity <TouchableOpacity testID="SettingsButton" style={styles.headerTouch} onPress={() => this.props.navigation.navigate('Settings')}>
testID="SettingsButton"
style={{ marginHorizontal: 16 }}
onPress={() => this.props.navigation.navigate('Settings')}
>
<Icon size={22} name="kebab-horizontal" type="octicon" color={BlueApp.settings.foregroundColor} /> <Icon size={22} name="kebab-horizontal" type="octicon" color={BlueApp.settings.foregroundColor} />
</TouchableOpacity> </TouchableOpacity>
</View> </View>
@ -310,23 +296,14 @@ export default class WalletsList extends Component {
onPress={() => { onPress={() => {
this.props.navigation.navigate('HodlHodl', { fromWallet: this.state.wallet }); this.props.navigation.navigate('HodlHodl', { fromWallet: this.state.wallet });
}} }}
style={{ style={styles.ltRoot}
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginHorizontal: 16,
marginVertical: 16,
backgroundColor: '#eef0f4',
padding: 16,
borderRadius: 6,
}}
> >
<View style={{ flexDirection: 'column' }}> <View style={styles.ltTextWrap}>
<Text style={{ fontSize: 16, fontWeight: '600', color: '#0C2550' }}>Local Trader</Text> <Text style={styles.ltTextBig}>Local Trader</Text>
<Text style={{ fontSize: 13, fontWeight: '500', color: '#9AA0AA' }}>A p2p exchange</Text> <Text style={styles.ltTextSmall}>A p2p exchange</Text>
</View> </View>
<View style={{ flexDirection: 'column', backgroundColor: '#007AFF', borderRadius: 16 }}> <View style={styles.ltButtonWrap}>
<Text style={{ paddingHorizontal: 16, paddingVertical: 8, fontSize: 13, color: '#fff', fontWeight: '600' }}>New</Text> <Text style={styles.ltButton}>New</Text>
</View> </View>
</TouchableOpacity> </TouchableOpacity>
); );
@ -387,26 +364,9 @@ export default class WalletsList extends Component {
case WalletsListSections.TRANSACTIONS: case WalletsListSections.TRANSACTIONS:
if (this.state.dataSource.length === 0 && !this.state.isLoading) { if (this.state.dataSource.length === 0 && !this.state.isLoading) {
return ( return (
<View style={{ top: 80, height: 160, marginBottom: 80 }}> <View style={styles.footerRoot}>
<Text <Text style={styles.footerEmpty}>{loc.wallets.list.empty_txs1}</Text>
style={{ <Text style={styles.footerStart}>{loc.wallets.list.empty_txs2}</Text>
fontSize: 18,
color: '#9aa0aa',
textAlign: 'center',
}}
>
{loc.wallets.list.empty_txs1}
</Text>
<Text
style={{
fontSize: 18,
color: '#9aa0aa',
textAlign: 'center',
fontWeight: '600',
}}
>
{loc.wallets.list.empty_txs2}
</Text>
</View> </View>
); );
} else { } else {
@ -420,18 +380,7 @@ export default class WalletsList extends Component {
renderScanButton = () => { renderScanButton = () => {
if (BlueApp.getWallets().length > 0 && !BlueApp.getWallets().some(wallet => wallet.type === PlaceholderWallet.type)) { if (BlueApp.getWallets().length > 0 && !BlueApp.getWallets().some(wallet => wallet.type === PlaceholderWallet.type)) {
return ( return (
<View <View style={styles.scanButton}>
style={{
flexDirection: 'row',
alignSelf: 'center',
backgroundColor: 'transparent',
position: 'absolute',
bottom: 30,
borderRadius: 30,
minHeight: 48,
overflow: 'hidden',
}}
>
<BlueScanButton onPress={this.onScanButtonPressed} /> <BlueScanButton onPress={this.onScanButtonPressed} />
</View> </View>
); );
@ -461,7 +410,7 @@ export default class WalletsList extends Component {
render() { render() {
return ( return (
<View style={{ flex: 1 }}> <View style={styles.root}>
<NavigationEvents <NavigationEvents
onDidFocus={() => { onDidFocus={() => {
this.redrawScreen(); this.redrawScreen();
@ -476,7 +425,7 @@ export default class WalletsList extends Component {
renderItem={this.renderSectionItem} renderItem={this.renderSectionItem}
keyExtractor={this.sectionListKeyExtractor} keyExtractor={this.sectionListKeyExtractor}
renderSectionHeader={this.renderSectionHeader} renderSectionHeader={this.renderSectionHeader}
contentInset={{ top: 0, left: 0, bottom: 60, right: 0 }} contentInset={styles.scrollContent}
renderSectionFooter={this.renderSectionFooter} renderSectionFooter={this.renderSectionFooter}
sections={[ sections={[
{ key: WalletsListSections.CAROUSEL, data: [WalletsListSections.CAROUSEL] }, { key: WalletsListSections.CAROUSEL, data: [WalletsListSections.CAROUSEL] },
@ -491,6 +440,15 @@ export default class WalletsList extends Component {
} }
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
root: {
flex: 1,
},
scrollContent: {
top: 0,
left: 0,
bottom: 60,
right: 0,
},
wrapper: { wrapper: {
backgroundColor: '#FFFFFF', backgroundColor: '#FFFFFF',
flex: 1, flex: 1,
@ -515,6 +473,83 @@ const styles = StyleSheet.create({
}, },
}), }),
}, },
headerTouch: {
marginHorizontal: 16,
},
listHeaderText: {
paddingLeft: 16,
fontWeight: 'bold',
fontSize: 24,
marginVertical: 8,
color: BlueApp.settings.foregroundColor,
},
ltRoot: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginHorizontal: 16,
marginVertical: 16,
backgroundColor: '#eef0f4',
padding: 16,
borderRadius: 6,
},
ltTextWrap: {
flexDirection: 'column',
},
ltTextBig: {
fontSize: 16,
fontWeight: '600',
color: '#0C2550',
},
ltTextSmall: {
fontSize: 13,
fontWeight: '500',
color: '#9AA0AA',
},
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,
},
}); });
WalletsList.propTypes = { WalletsList.propTypes = {

View file

@ -1,10 +1,66 @@
import React, { useEffect, useState, useCallback } from 'react'; import React, { useEffect, useState, useCallback } from 'react';
import { ActivityIndicator, View, BackHandler, Text, ScrollView } from 'react-native'; import { ActivityIndicator, View, BackHandler, Text, ScrollView, StyleSheet } from 'react-native';
import { BlueSpacing20, SafeBlueArea, BlueNavigationStyle, BlueText, BlueButton } from '../../BlueComponents'; import { BlueSpacing20, SafeBlueArea, BlueNavigationStyle, BlueText, BlueButton } from '../../BlueComponents';
import Privacy from '../../Privacy'; import Privacy from '../../Privacy';
import { useNavigation, useNavigationParam } from 'react-navigation-hooks'; import { useNavigation, useNavigationParam } from 'react-navigation-hooks';
const loc = require('../../loc'); const loc = require('../../loc');
const styles = StyleSheet.create({
word: {
width: 'auto',
marginRight: 8,
marginBottom: 8,
backgroundColor: '#f5f5f5',
paddingTop: 6,
paddingBottom: 6,
paddingLeft: 8,
paddingRight: 8,
borderRadius: 4,
},
wortText: {
color: '#81868E',
fontWeight: 'bold',
},
loading: {
flex: 1,
paddingTop: 20,
},
flex: {
flex: 1,
},
scrollViewContent: {
justifyContent: 'space-between',
},
please: {
alignItems: 'center',
paddingHorizontal: 16,
},
successText: {
textAlign: 'center',
fontWeight: 'bold',
color: '#0C2550',
},
pleaseText: {
paddingBottom: 10,
paddingRight: 0,
paddingLeft: 0,
color: '#0C2550',
},
secret: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
flexWrap: 'wrap',
marginTop: 14,
},
ok: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
flexWrap: 'wrap',
},
});
const PleaseBackup = () => { const PleaseBackup = () => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const words = useNavigationParam('secret').split(' '); const words = useNavigationParam('secret').split(' ');
@ -28,21 +84,8 @@ const PleaseBackup = () => {
let component = []; let component = [];
for (const [index, secret] of words.entries()) { for (const [index, secret] of words.entries()) {
component.push( component.push(
<View <View style={styles.word} key={`${secret}${index}`}>
style={{ <Text style={styles.wortText}>
width: 'auto',
marginRight: 8,
marginBottom: 8,
backgroundColor: '#f5f5f5',
paddingTop: 6,
paddingBottom: 6,
paddingLeft: 8,
paddingRight: 8,
borderRadius: 4,
}}
key={`${secret}${index}`}
>
<Text style={{ color: '#81868E', fontWeight: 'bold' }}>
{`${index}`}. {secret} {`${index}`}. {secret}
</Text> </Text>
</View>, </View>,
@ -52,30 +95,20 @@ const PleaseBackup = () => {
}; };
return isLoading ? ( return isLoading ? (
<View style={{ flex: 1, paddingTop: 20 }}> <View style={styles.loading}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
) : ( ) : (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.flex}>
<ScrollView contentContainerStyle={{ justifyContent: 'space-between' }} testID="PleaseBackupScrollView"> <ScrollView contentContainerStyle={styles.scrollViewContent} testID="PleaseBackupScrollView">
<View style={{ alignItems: 'center', paddingHorizontal: 16 }}> <View style={styles.please}>
<BlueText style={{ textAlign: 'center', fontWeight: 'bold', color: '#0C2550' }}>{loc.pleasebackup.success}</BlueText> <BlueText style={styles.successText}>{loc.pleasebackup.success}</BlueText>
<BlueText style={{ paddingBottom: 10, paddingRight: 0, paddingLeft: 0, color: '#0C2550' }}>{loc.pleasebackup.text}</BlueText> <BlueText style={styles.pleaseText}>{loc.pleasebackup.text}</BlueText>
<View <View style={styles.secret}>{renderSecret()}</View>
style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
flexWrap: 'wrap',
marginTop: 14,
}}
>
{renderSecret()}
</View>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', flexWrap: 'wrap' }}> <View style={styles.ok}>
<View style={{ flex: 1 }}> <View style={styles.flex}>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueButton testID="PleasebackupOk" onPress={dismiss} title={loc.pleasebackup.ok} /> <BlueButton testID="PleasebackupOk" onPress={dismiss} title={loc.pleasebackup.ok} />
</View> </View>

View file

@ -1,12 +1,21 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useNavigation, useNavigationParam } from 'react-navigation-hooks'; import { useNavigation, useNavigationParam } from 'react-navigation-hooks';
import { View, Dimensions } from 'react-native'; import { View, Dimensions, StyleSheet } from 'react-native';
import { SafeBlueArea, BlueSpacing20, BlueCopyTextToClipboard, BlueButton, BlueCard, BlueTextCentered } from '../../BlueComponents'; import { SafeBlueArea, BlueSpacing20, BlueCopyTextToClipboard, BlueButton, BlueCard, BlueTextCentered } from '../../BlueComponents';
import QRCode from 'react-native-qrcode-svg'; import QRCode from 'react-native-qrcode-svg';
import { ScrollView } from 'react-native-gesture-handler'; import { ScrollView } from 'react-native-gesture-handler';
const { height, width } = Dimensions.get('window'); const { height, width } = Dimensions.get('window');
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
const styles = StyleSheet.create({
root: {
flex: 1,
},
scrollViewContent: {
flexGrow: 1,
},
});
const PleaseBackupLNDHub = () => { const PleaseBackupLNDHub = () => {
const wallet = useNavigationParam('wallet'); const wallet = useNavigationParam('wallet');
const navigation = useNavigation(); const navigation = useNavigation();
@ -18,8 +27,8 @@ const PleaseBackupLNDHub = () => {
}; };
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<ScrollView centerContent contentContainerStyle={{ flexGrow: 1 }} onLayout={onLayout}> <ScrollView centerContent contentContainerStyle={styles.scrollViewContent} onLayout={onLayout}>
<BlueCard> <BlueCard>
<View> <View>
<BlueTextCentered> <BlueTextCentered>

View file

@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { View, ActivityIndicator, Image, Text } from 'react-native'; import { View, ActivityIndicator, Image, Text, StyleSheet } from 'react-native';
import { SafeBlueArea, BlueNavigationStyle } from '../../BlueComponents'; import { SafeBlueArea, BlueNavigationStyle } from '../../BlueComponents';
import SortableList from 'react-native-sortable-list'; import SortableList from 'react-native-sortable-list';
import LinearGradient from 'react-native-linear-gradient'; import LinearGradient from 'react-native-linear-gradient';
@ -12,6 +12,59 @@ let EV = require('../../events');
let BlueApp = require('../../BlueApp'); let BlueApp = require('../../BlueApp');
let loc = require('../../loc/'); let loc = require('../../loc/');
const styles = StyleSheet.create({
loading: {
flex: 1,
paddingTop: 20,
},
root: {
flex: 1,
},
itemRoot: {
backgroundColor: 'transparent',
padding: 10,
marginVertical: 17,
},
gradient: {
padding: 15,
borderRadius: 10,
minHeight: 164,
elevation: 5,
},
image: {
width: 99,
height: 94,
position: 'absolute',
bottom: 0,
right: 0,
},
transparentText: {
backgroundColor: 'transparent',
},
label: {
backgroundColor: 'transparent',
fontSize: 19,
color: '#fff',
},
balance: {
backgroundColor: 'transparent',
fontWeight: 'bold',
fontSize: 36,
color: '#fff',
},
latestTxLabel: {
backgroundColor: 'transparent',
fontSize: 13,
color: '#fff',
},
latestTxValue: {
backgroundColor: 'transparent',
fontWeight: 'bold',
fontSize: 16,
color: '#fff',
},
});
export default class ReorderWallets extends Component { export default class ReorderWallets extends Component {
static navigationOptions = ({ navigation }) => ({ static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle( ...BlueNavigationStyle(
@ -65,78 +118,27 @@ export default class ReorderWallets extends Component {
item = item.data; item = item.data;
return ( return (
<View <View shadowOpacity={40 / 100} shadowOffset={{ width: 0, height: 0 }} shadowRadius={5} style={styles.itemRoot}>
shadowOpacity={40 / 100} <LinearGradient shadowColor="#000000" colors={WalletGradient.gradientsFor(item.type)} style={styles.gradient}>
shadowOffset={{ width: 0, height: 0 }}
shadowRadius={5}
style={{ backgroundColor: 'transparent', padding: 10, marginVertical: 17 }}
>
<LinearGradient
shadowColor="#000000"
colors={WalletGradient.gradientsFor(item.type)}
style={{
padding: 15,
borderRadius: 10,
minHeight: 164,
elevation: 5,
}}
>
<Image <Image
source={ source={
(LightningCustodianWallet.type === item.type && require('../../img/lnd-shape.png')) || require('../../img/btc-shape.png') (LightningCustodianWallet.type === item.type && require('../../img/lnd-shape.png')) || require('../../img/btc-shape.png')
} }
style={{ style={styles.image}
width: 99,
height: 94,
position: 'absolute',
bottom: 0,
right: 0,
}}
/> />
<Text style={{ backgroundColor: 'transparent' }} /> <Text style={styles.transparentText} />
<Text <Text numberOfLines={1} style={styles.label}>
numberOfLines={1}
style={{
backgroundColor: 'transparent',
fontSize: 19,
color: '#fff',
}}
>
{item.getLabel()} {item.getLabel()}
</Text> </Text>
<Text <Text numberOfLines={1} adjustsFontSizeToFit style={styles.balance}>
numberOfLines={1}
adjustsFontSizeToFit
style={{
backgroundColor: 'transparent',
fontWeight: 'bold',
fontSize: 36,
color: '#fff',
}}
>
{loc.formatBalance(Number(item.getBalance()), item.getPreferredBalanceUnit(), true)} {loc.formatBalance(Number(item.getBalance()), item.getPreferredBalanceUnit(), true)}
</Text> </Text>
<Text style={{ backgroundColor: 'transparent' }} /> <Text style={styles.transparentText} />
<Text <Text numberOfLines={1} style={styles.latestTxLabel}>
numberOfLines={1}
style={{
backgroundColor: 'transparent',
fontSize: 13,
color: '#fff',
}}
>
{loc.wallets.list.latest_transaction} {loc.wallets.list.latest_transaction}
</Text> </Text>
<Text <Text numberOfLines={1} style={styles.latestTxValue}>
numberOfLines={1}
style={{
backgroundColor: 'transparent',
fontWeight: 'bold',
fontSize: 16,
color: '#fff',
}}
>
{loc.transactionTimeToReadable(item.getLatestTransactionTime())} {loc.transactionTimeToReadable(item.getLatestTransactionTime())}
</Text> </Text>
</LinearGradient> </LinearGradient>
@ -147,7 +149,7 @@ export default class ReorderWallets extends Component {
render() { render() {
if (this.state.isLoading) { if (this.state.isLoading) {
return ( return (
<View style={{ flex: 1, paddingTop: 20 }}> <View style={styles.loading}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
); );
@ -157,7 +159,7 @@ export default class ReorderWallets extends Component {
<SafeBlueArea> <SafeBlueArea>
<SortableList <SortableList
ref={ref => (this.sortableList = ref)} ref={ref => (this.sortableList = ref)}
style={{ flex: 1 }} style={styles.root}
data={this.state.data} data={this.state.data}
renderRow={this._renderItem} renderRow={this._renderItem}
onChangeOrder={() => { onChangeOrder={() => {

View file

@ -1,6 +1,6 @@
/* eslint-disable react/prop-types */ /* eslint-disable react/prop-types */
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { View, ActivityIndicator, Image, Text, TouchableOpacity, FlatList } from 'react-native'; import { View, ActivityIndicator, Image, Text, TouchableOpacity, FlatList, StyleSheet } from 'react-native';
import { SafeBlueArea, BlueNavigationStyle, BlueText, BlueSpacing20, BluePrivateBalance } from '../../BlueComponents'; import { SafeBlueArea, BlueNavigationStyle, BlueText, BlueSpacing20, BluePrivateBalance } from '../../BlueComponents';
import LinearGradient from 'react-native-linear-gradient'; import LinearGradient from 'react-native-linear-gradient';
import { LightningCustodianWallet } from '../../class/lightning-custodian-wallet'; import { LightningCustodianWallet } from '../../class/lightning-custodian-wallet';
@ -11,6 +11,70 @@ import { useNavigationParam } from 'react-navigation-hooks';
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
const loc = require('../../loc'); const loc = require('../../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
},
loading: {
flex: 1,
justifyContent: 'center',
alignContent: 'center',
paddingTop: 20,
},
itemRoot: {
backgroundColor: 'transparent',
padding: 10,
marginVertical: 17,
},
gradient: {
padding: 15,
borderRadius: 10,
minHeight: 164,
elevation: 5,
},
image: {
width: 99,
height: 94,
position: 'absolute',
bottom: 0,
right: 0,
},
transparentText: {
backgroundColor: 'transparent',
},
label: {
backgroundColor: 'transparent',
fontSize: 19,
color: '#fff',
},
balance: {
backgroundColor: 'transparent',
fontWeight: 'bold',
fontSize: 36,
color: '#fff',
},
latestTxLabel: {
backgroundColor: 'transparent',
fontSize: 13,
color: '#fff',
},
latestTxValue: {
backgroundColor: 'transparent',
fontWeight: 'bold',
fontSize: 16,
color: '#fff',
},
noWallets: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingTop: 20,
},
center: {
textAlign: 'center',
},
});
const SelectWallet = () => { const SelectWallet = () => {
const chainType = useNavigationParam('chainType'); const chainType = useNavigationParam('chainType');
const onWalletSelect = useNavigationParam('onWalletSelect'); const onWalletSelect = useNavigationParam('onWalletSelect');
@ -31,82 +95,31 @@ const SelectWallet = () => {
onWalletSelect(item); onWalletSelect(item);
}} }}
> >
<View <View shadowOpacity={40 / 100} shadowOffset={{ width: 0, height: 0 }} shadowRadius={5} style={styles.itemRoot}>
shadowOpacity={40 / 100} <LinearGradient shadowColor="#000000" colors={WalletGradient.gradientsFor(item.type)} style={styles.gradient}>
shadowOffset={{ width: 0, height: 0 }}
shadowRadius={5}
style={{ backgroundColor: 'transparent', padding: 10, marginVertical: 17 }}
>
<LinearGradient
shadowColor="#000000"
colors={WalletGradient.gradientsFor(item.type)}
style={{
padding: 15,
borderRadius: 10,
minHeight: 164,
elevation: 5,
}}
>
<Image <Image
source={ source={
(LightningCustodianWallet.type === item.type && require('../../img/lnd-shape.png')) || require('../../img/btc-shape.png') (LightningCustodianWallet.type === item.type && require('../../img/lnd-shape.png')) || require('../../img/btc-shape.png')
} }
style={{ style={styles.image}
width: 99,
height: 94,
position: 'absolute',
bottom: 0,
right: 0,
}}
/> />
<Text style={{ backgroundColor: 'transparent' }} /> <Text style={styles.transparentText} />
<Text <Text numberOfLines={1} style={styles.label}>
numberOfLines={1}
style={{
backgroundColor: 'transparent',
fontSize: 19,
color: '#fff',
}}
>
{item.getLabel()} {item.getLabel()}
</Text> </Text>
{item.hideBalance ? ( {item.hideBalance ? (
<BluePrivateBalance /> <BluePrivateBalance />
) : ( ) : (
<Text <Text numberOfLines={1} adjustsFontSizeToFit style={styles.balance}>
numberOfLines={1}
adjustsFontSizeToFit
style={{
backgroundColor: 'transparent',
fontWeight: 'bold',
fontSize: 36,
color: '#fff',
}}
>
{loc.formatBalance(Number(item.getBalance()), item.getPreferredBalanceUnit(), true)} {loc.formatBalance(Number(item.getBalance()), item.getPreferredBalanceUnit(), true)}
</Text> </Text>
)} )}
<Text style={{ backgroundColor: 'transparent' }} /> <Text style={styles.transparentText} />
<Text <Text numberOfLines={1} style={styles.latestTxLabel}>
numberOfLines={1}
style={{
backgroundColor: 'transparent',
fontSize: 13,
color: '#fff',
}}
>
{loc.wallets.list.latest_transaction} {loc.wallets.list.latest_transaction}
</Text> </Text>
<Text <Text numberOfLines={1} style={styles.latestTxValue}>
numberOfLines={1}
style={{
backgroundColor: 'transparent',
fontWeight: 'bold',
fontSize: 16,
color: '#fff',
}}
>
{loc.transactionTimeToReadable(item.getLatestTransactionTime())} {loc.transactionTimeToReadable(item.getLatestTransactionTime())}
</Text> </Text>
</LinearGradient> </LinearGradient>
@ -117,25 +130,23 @@ const SelectWallet = () => {
if (isLoading) { if (isLoading) {
return ( return (
<View style={{ flex: 1, justifyContent: 'center', alignContent: 'center', paddingTop: 20 }}> <View style={styles.loading}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
); );
} else if (data.length <= 0) { } else if (data.length <= 0) {
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', paddingTop: 20 }}> <View style={styles.noWallets}>
<BlueText style={{ textAlign: 'center' }}>There are currently no Bitcoin wallets available.</BlueText> <BlueText style={styles.center}>There are currently no Bitcoin wallets available.</BlueText>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueText style={{ textAlign: 'center' }}> <BlueText style={styles.center}>A Bitcoin wallet is required to refill Lightning wallets. Please, create or import one.</BlueText>
A Bitcoin wallet is required to refill Lightning wallets. Please, create or import one.
</BlueText>
</View> </View>
</SafeBlueArea> </SafeBlueArea>
); );
} else { } else {
return ( return (
<SafeBlueArea style={{ flex: 1 }}> <SafeBlueArea style={styles.root}>
<FlatList extraData={data} data={data} renderItem={renderItem} keyExtractor={(_item, index) => `${index}`} /> <FlatList extraData={data} data={data} renderItem={renderItem} keyExtractor={(_item, index) => `${index}`} />
</SafeBlueArea> </SafeBlueArea>
); );

View file

@ -45,13 +45,144 @@ let EV = require('../../events');
let BlueElectrum = require('../../BlueElectrum'); let BlueElectrum = require('../../BlueElectrum');
const LocalQRCode = require('@remobile/react-native-qrcode-local-image'); const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
const styles = StyleSheet.create({
flex: {
flex: 1,
},
scrollViewContent: {
flex: 1,
justifyContent: 'center',
paddingHorizontal: 16,
paddingVertical: 40,
},
modalContent: {
backgroundColor: '#FFFFFF',
padding: 22,
justifyContent: 'center',
alignItems: 'center',
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)',
minHeight: 200,
height: 200,
},
advancedTransactionOptionsModalContent: {
backgroundColor: '#FFFFFF',
padding: 22,
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)',
minHeight: 130,
},
bottomModal: {
justifyContent: 'flex-end',
margin: 0,
},
walletDetails: {
marginHorizontal: 16,
minWidth: 150,
justifyContent: 'center',
alignItems: 'flex-end',
},
activityIndicator: {
marginVertical: 20,
},
listHeader: {
flexDirection: 'row',
margin: 16,
justifyContent: 'space-evenly',
},
listHeaderText: {
flex: 1,
marginLeft: 16,
marginTop: 8,
marginBottom: 8,
fontWeight: 'bold',
fontSize: 24,
color: BlueApp.settings.foregroundColor,
},
marketplaceButton1: {
backgroundColor: '#f2f2f2',
borderRadius: 9,
minHeight: 49,
flex: 1,
paddingHorizontal: 8,
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
},
marketplaceButton2: {
marginLeft: 5,
backgroundColor: '#f2f2f2',
borderRadius: 9,
minHeight: 49,
flex: 1,
paddingHorizontal: 8,
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
},
marketpalceText1: {
color: '#062453',
fontSize: 18,
},
marketpalceText2: {
color: '#062453',
fontSize: 18,
marginHorizontal: 8,
},
item: {
marginHorizontal: 4,
},
list: {
backgroundColor: '#FFFFFF',
flex: 1,
},
emptyTxs: {
fontSize: 18,
color: '#9aa0aa',
textAlign: 'center',
marginVertical: 16,
},
emptyTxsLightning: {
fontSize: 18,
color: '#9aa0aa',
textAlign: 'center',
fontWeight: '600',
},
buyBitcoin: {
backgroundColor: '#007AFF',
minWidth: 260,
borderRadius: 8,
alignSelf: 'center',
paddingVertical: 14,
paddingHorizontal: 32,
},
buyBitcoinText: {
fontSize: 15,
color: '#fff',
textAlign: 'center',
fontWeight: '600',
},
floatButtons: {
flexDirection: 'row',
alignSelf: 'center',
backgroundColor: 'transparent',
position: 'absolute',
bottom: 30,
borderRadius: 30,
minHeight: 48,
overflow: 'hidden',
},
});
export default class WalletTransactions extends Component { export default class WalletTransactions extends Component {
static navigationOptions = ({ navigation }) => { static navigationOptions = ({ navigation }) => {
return { return {
headerRight: ( headerRight: (
<TouchableOpacity <TouchableOpacity
disabled={navigation.getParam('isLoading') === true} disabled={navigation.getParam('isLoading') === true}
style={{ marginHorizontal: 16, minWidth: 150, justifyContent: 'center', alignItems: 'flex-end' }} style={styles.walletDetails}
onPress={() => onPress={() =>
navigation.navigate('WalletDetails', { navigation.navigate('WalletDetails', {
wallet: navigation.state.params.wallet, wallet: navigation.state.params.wallet,
@ -211,13 +342,13 @@ export default class WalletTransactions extends Component {
renderListFooterComponent = () => { renderListFooterComponent = () => {
// if not all txs rendered - display indicator // if not all txs rendered - display indicator
return (this.getTransactions(Infinity).length > this.state.limit && <ActivityIndicator style={{ marginVertical: 20 }} />) || <View />; return (this.getTransactions(Infinity).length > this.state.limit && <ActivityIndicator style={styles.activityIndicator} />) || <View />;
}; };
renderListHeaderComponent = () => { renderListHeaderComponent = () => {
return ( return (
<View style={{ flex: 1 }}> <View style={styles.flex}>
<View style={{ flexDirection: 'row', margin: 16, justifyContent: 'space-evenly' }}> <View style={styles.listHeader}>
{/* {/*
Current logic - Onchain: Current logic - Onchain:
- Shows buy button on middle when empty - Shows buy button on middle when empty
@ -238,19 +369,7 @@ export default class WalletTransactions extends Component {
{this.state.wallet.type === LightningCustodianWallet.type && this.renderMarketplaceButton()} {this.state.wallet.type === LightningCustodianWallet.type && this.renderMarketplaceButton()}
{this.state.wallet.type === LightningCustodianWallet.type && Platform.OS === 'ios' && this.renderLappBrowserButton()} {this.state.wallet.type === LightningCustodianWallet.type && Platform.OS === 'ios' && this.renderLappBrowserButton()}
</View> </View>
<Text <Text style={styles.listHeaderText}>{loc.transactions.list.title}</Text>
style={{
flex: 1,
marginLeft: 16,
marginTop: 8,
marginBottom: 8,
fontWeight: 'bold',
fontSize: 24,
color: BlueApp.settings.foregroundColor,
}}
>
{loc.transactions.list.title}
</Text>
</View> </View>
); );
}; };
@ -333,18 +452,9 @@ export default class WalletTransactions extends Component {
this.props.navigation.navigate('Marketplace', { fromWallet: this.state.wallet }); this.props.navigation.navigate('Marketplace', { fromWallet: this.state.wallet });
} }
}} }}
style={{ style={styles.marketplaceButton1}
backgroundColor: '#f2f2f2',
borderRadius: 9,
minHeight: 49,
flex: 1,
paddingHorizontal: 8,
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
}}
> >
<Text style={{ color: '#062453', fontSize: 18 }}>marketplace</Text> <Text style={styles.marketpalceText1}>marketplace</Text>
</TouchableOpacity> </TouchableOpacity>
), ),
ios: ios:
@ -353,19 +463,10 @@ export default class WalletTransactions extends Component {
onPress={async () => { onPress={async () => {
Linking.openURL('https://bluewallet.io/marketplace/'); Linking.openURL('https://bluewallet.io/marketplace/');
}} }}
style={{ style={styles.marketplaceButton1}
backgroundColor: '#f2f2f2',
borderRadius: 9,
minHeight: 49,
flex: 1,
paddingHorizontal: 8,
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
}}
> >
<Icon name="external-link" size={18} type="font-awesome" color="#9aa0aa" /> <Icon name="external-link" size={18} type="font-awesome" color="#9aa0aa" />
<Text style={{ color: '#062453', fontSize: 18, marginHorizontal: 8 }}>marketplace</Text> <Text style={styles.marketpalceText2}>marketplace</Text>
</TouchableOpacity> </TouchableOpacity>
) : null, ) : null,
}); });
@ -381,19 +482,9 @@ export default class WalletTransactions extends Component {
url: 'https://duckduckgo.com', url: 'https://duckduckgo.com',
}); });
}} }}
style={{ style={styles.marketplaceButton2}
marginLeft: 5,
backgroundColor: '#f2f2f2',
borderRadius: 9,
minHeight: 49,
flex: 1,
paddingHorizontal: 8,
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
}}
> >
<Text style={{ color: '#062453', fontSize: 18 }}>LApp Browser</Text> <Text style={styles.marketpalceText1}>LApp Browser</Text>
</TouchableOpacity> </TouchableOpacity>
); );
}; };
@ -405,26 +496,9 @@ export default class WalletTransactions extends Component {
wallet: this.state.wallet, wallet: this.state.wallet,
}) })
} }
style={{ style={styles.marketplaceButton2}
marginLeft: 5,
backgroundColor: '#f2f2f2',
borderRadius: 9,
minHeight: 49,
flex: 1,
paddingHorizontal: 8,
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
}}
> >
<Text <Text style={styles.marketpalceText1}>{loc.wallets.list.tap_here_to_buy}</Text>
style={{
color: '#062453',
fontSize: 18,
}}
>
{loc.wallets.list.tap_here_to_buy}
</Text>
</TouchableOpacity> </TouchableOpacity>
); );
}; };
@ -471,7 +545,7 @@ export default class WalletTransactions extends Component {
renderItem = item => { renderItem = item => {
return ( return (
<View style={{ marginHorizontal: 4 }}> <View style={styles.item}>
<BlueTransactionListItem <BlueTransactionListItem
item={item.item} item={item.item}
itemPriceUnit={this.state.wallet.getPreferredBalanceUnit()} itemPriceUnit={this.state.wallet.getPreferredBalanceUnit()}
@ -574,7 +648,7 @@ export default class WalletTransactions extends Component {
render() { render() {
const { navigate } = this.props.navigation; const { navigate } = this.props.navigation;
return ( return (
<View style={{ flex: 1 }}> <View style={styles.flex}>
{this.state.wallet.chain === Chain.ONCHAIN && this.state.isHandOffUseEnabled && ( {this.state.wallet.chain === Chain.ONCHAIN && this.state.isHandOffUseEnabled && (
<Handoff <Handoff
title={`Bitcoin Wallet ${this.state.wallet.getLabel()}`} title={`Bitcoin Wallet ${this.state.wallet.getLabel()}`}
@ -615,7 +689,7 @@ export default class WalletTransactions extends Component {
} }
}} }}
/> />
<View style={{ backgroundColor: '#FFFFFF', flex: 1 }}> <View style={styles.list}>
<FlatList <FlatList
ListHeaderComponent={this.renderListHeaderComponent} ListHeaderComponent={this.renderListHeaderComponent}
onEndReachedThreshold={0.3} onEndReachedThreshold={0.3}
@ -636,33 +710,11 @@ export default class WalletTransactions extends Component {
}} }}
ListFooterComponent={this.renderListFooterComponent} ListFooterComponent={this.renderListFooterComponent}
ListEmptyComponent={ ListEmptyComponent={
<ScrollView <ScrollView style={styles.flex} contentContainerStyle={styles.scrollViewContent}>
style={{ flex: 1 }} <Text numberOfLines={0} style={styles.emptyTxs}>
contentContainerStyle={{ flex: 1, justifyContent: 'center', paddingHorizontal: 16, paddingVertical: 40 }}
>
<Text
numberOfLines={0}
style={{
fontSize: 18,
color: '#9aa0aa',
textAlign: 'center',
marginVertical: 16,
}}
>
{(this.isLightning() && loc.wallets.list.empty_txs1_lightning) || loc.wallets.list.empty_txs1} {(this.isLightning() && loc.wallets.list.empty_txs1_lightning) || loc.wallets.list.empty_txs1}
</Text> </Text>
{this.isLightning() && ( {this.isLightning() && <Text style={styles.emptyTxsLightning}>{loc.wallets.list.empty_txs2_lightning}</Text>}
<Text
style={{
fontSize: 18,
color: '#9aa0aa',
textAlign: 'center',
fontWeight: '600',
}}
>
{loc.wallets.list.empty_txs2_lightning}
</Text>
)}
{!this.isLightning() && ( {!this.isLightning() && (
<TouchableOpacity <TouchableOpacity
@ -671,25 +723,9 @@ export default class WalletTransactions extends Component {
wallet: this.state.wallet, wallet: this.state.wallet,
}) })
} }
style={{ style={styles.buyBitcoin}
backgroundColor: '#007AFF',
minWidth: 260,
borderRadius: 8,
alignSelf: 'center',
paddingVertical: 14,
paddingHorizontal: 32,
}}
> >
<Text <Text style={styles.buyBitcoinText}>{loc.wallets.list.tap_here_to_buy}</Text>
style={{
fontSize: 15,
color: '#fff',
textAlign: 'center',
fontWeight: '600',
}}
>
{loc.wallets.list.tap_here_to_buy}
</Text>
</TouchableOpacity> </TouchableOpacity>
)} )}
</ScrollView> </ScrollView>
@ -705,18 +741,7 @@ export default class WalletTransactions extends Component {
/> />
{this.renderManageFundsModal()} {this.renderManageFundsModal()}
</View> </View>
<View <View style={styles.floatButtons}>
style={{
flexDirection: 'row',
alignSelf: 'center',
backgroundColor: 'transparent',
position: 'absolute',
bottom: 30,
borderRadius: 30,
minHeight: 48,
overflow: 'hidden',
}}
>
{(() => { {(() => {
if (this.state.wallet.allowReceive()) { if (this.state.wallet.allowReceive()) {
return ( return (
@ -792,32 +817,6 @@ export default class WalletTransactions extends Component {
} }
} }
const styles = StyleSheet.create({
modalContent: {
backgroundColor: '#FFFFFF',
padding: 22,
justifyContent: 'center',
alignItems: 'center',
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)',
minHeight: 200,
height: 200,
},
advancedTransactionOptionsModalContent: {
backgroundColor: '#FFFFFF',
padding: 22,
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)',
minHeight: 130,
},
bottomModal: {
justifyContent: 'flex-end',
margin: 0,
},
});
WalletTransactions.propTypes = { WalletTransactions.propTypes = {
navigation: PropTypes.shape({ navigation: PropTypes.shape({
navigate: PropTypes.func, navigate: PropTypes.func,

View file

@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Dimensions, ActivityIndicator, View } from 'react-native'; import { Dimensions, ActivityIndicator, View, StyleSheet } from 'react-native';
import QRCode from 'react-native-qrcode-svg'; import QRCode from 'react-native-qrcode-svg';
import { BlueSpacing20, SafeBlueArea, BlueText, BlueNavigationStyle, BlueCopyTextToClipboard } from '../../BlueComponents'; import { BlueSpacing20, SafeBlueArea, BlueText, BlueNavigationStyle, BlueCopyTextToClipboard } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
@ -10,6 +10,18 @@ let BlueApp = require('../../BlueApp');
let loc = require('../../loc'); let loc = require('../../loc');
const { height, width } = Dimensions.get('window'); const { height, width } = Dimensions.get('window');
const styles = StyleSheet.create({
root: {
flex: 1,
paddingTop: 20,
},
container: {
alignItems: 'center',
flex: 1,
justifyContent: 'center',
},
});
export default class WalletXpub extends Component { export default class WalletXpub extends Component {
static navigationOptions = ({ navigation }) => ({ static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true), ...BlueNavigationStyle(navigation, true),
@ -66,15 +78,15 @@ export default class WalletXpub extends Component {
render() { render() {
if (this.state.isLoading) { if (this.state.isLoading) {
return ( return (
<View style={{ flex: 1, paddingTop: 20 }}> <View style={styles.root}>
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
); );
} }
return ( return (
<SafeBlueArea style={{ flex: 1, paddingTop: 20 }}> <SafeBlueArea style={styles.root}>
<View style={{ alignItems: 'center', flex: 1, justifyContent: 'center' }} onLayout={this.onLayout}> <View style={styles.container} onLayout={this.onLayout}>
<View> <View>
<BlueText>{this.state.wallet.typeReadable}</BlueText> <BlueText>{this.state.wallet.typeReadable}</BlueText>
</View> </View>