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 { 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 { BlueNavigationStyle, SafeBlueArea } from '../../BlueComponents';
import Ionicons from 'react-native-vector-icons/Ionicons';
@ -30,9 +30,9 @@ var webln = {
window.ReactNativeWebView.postMessage(JSON.stringify({ sendPayment: paymentRequest }));
return new Promise(function(resolve, reject) {
/* nop. intentionally, forever hang promise.
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.
might change in future */
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.
might change in future */
});
},
makeInvoice: function(RequestInvoiceArgs) {
@ -90,51 +90,51 @@ bluewalletResponses = {};
webln = {
enable : function () {
window.ReactNativeWebView.postMessage(JSON.stringify({'enable': true}));
return new Promise(function(resolve, reject){
resolve(true);
})
},
getInfo : function () {
window.ReactNativeWebView.postMessage('getInfo');
return new Promise(function(resolve, reject){
reject('not implemented');
})
},
sendPayment: function(paymentRequest) {
window.ReactNativeWebView.postMessage(JSON.stringify({ sendPayment: paymentRequest }));
return new Promise(function(resolve, reject) {
/* nop. intentionally, forever hang promise.
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.
might change in future */
});
},
makeInvoice: function (RequestInvoiceArgs) {
var id = Math.random();
window.ReactNativeWebView.postMessage(JSON.stringify({makeInvoice: RequestInvoiceArgs, id: id}));
return new Promise(function(resolve, reject) {
var interval = setInterval(function () {
if (bluewalletResponses[id]) {
clearInterval(interval);
resolve(bluewalletResponses[id]);
}
}, 1000);
});
},
signMessage: function () {
window.ReactNativeWebView.postMessage('signMessage');
return new Promise(function(resolve, reject){
reject('not implemented');
})
},
verifyMessage: function () {
window.ReactNativeWebView.postMessage('verifyMessage');
return new Promise(function(resolve, reject){
reject('not implemented');
})
},
enable : function () {
window.ReactNativeWebView.postMessage(JSON.stringify({'enable': true}));
return new Promise(function(resolve, reject){
resolve(true);
})
},
getInfo : function () {
window.ReactNativeWebView.postMessage('getInfo');
return new Promise(function(resolve, reject){
reject('not implemented');
})
},
sendPayment: function(paymentRequest) {
window.ReactNativeWebView.postMessage(JSON.stringify({ sendPayment: paymentRequest }));
return new Promise(function(resolve, reject) {
/* nop. intentionally, forever hang promise.
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.
might change in future */
});
},
makeInvoice: function (RequestInvoiceArgs) {
var id = Math.random();
window.ReactNativeWebView.postMessage(JSON.stringify({makeInvoice: RequestInvoiceArgs, id: id}));
return new Promise(function(resolve, reject) {
var interval = setInterval(function () {
if (bluewalletResponses[id]) {
clearInterval(interval);
resolve(bluewalletResponses[id]);
}
}, 1000);
});
},
signMessage: function () {
window.ReactNativeWebView.postMessage('signMessage');
return new Promise(function(resolve, reject){
reject('not implemented');
})
},
verifyMessage: function () {
window.ReactNativeWebView.postMessage('verifyMessage');
return new Promise(function(resolve, reject){
reject('not implemented');
})
},
};
@ -142,17 +142,17 @@ webln = {
/* listening to events that might come from RN: */
document.addEventListener("message", function(event) {
window.ReactNativeWebView.postMessage("inside webview, received post message: " + event.detail);
var json;
try {
json = JSON.parse(event.detail);
} catch (_) {}
window.ReactNativeWebView.postMessage("inside webview, received post message: " + event.detail);
var json;
try {
json = JSON.parse(event.detail);
} catch (_) {}
if (json && json.bluewalletResponse) {
/* this is an answer to one of our inside-webview calls.
we store it in answers hashmap for someone who cares about it */
bluewalletResponses[json.id] = json.bluewalletResponse
}
if (json && json.bluewalletResponse) {
/* this is an answer to one of our inside-webview calls.
we store it in answers hashmap for someone who cares about it */
bluewalletResponses[json.id] = json.bluewalletResponse
}
}, false);
@ -160,50 +160,119 @@ document.addEventListener("message", function(event) {
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,
searching for all bolt11 manually */
searching for all bolt11 manually */
setInterval(function() {
window.ReactNativeWebView.postMessage('interval');
var searchText = "lnbc";
var searchText = "lnbc";
var aTags = document.getElementsByTagName("span");
var i;
for (i = 0; i < aTags.length; i++) {
if (aTags[i].textContent.indexOf(searchText) === 0) {
tryToPay(aTags[i].textContent);
}
}
var aTags = document.getElementsByTagName("span");
var i;
for (i = 0; i < aTags.length; i++) {
if (aTags[i].textContent.indexOf(searchText) === 0) {
tryToPay(aTags[i].textContent);
}
}
/* ------------------------- */
/* ------------------------- */
aTags = document.getElementsByTagName("input");
for (i = 0; i < aTags.length; i++) {
if (aTags[i].value.indexOf(searchText) === 0) {
tryToPay(aTags[i].value);
}
}
aTags = document.getElementsByTagName("input");
for (i = 0; i < aTags.length; i++) {
if (aTags[i].value.indexOf(searchText) === 0) {
tryToPay(aTags[i].value);
}
}
/* ------------------------- */
/* ------------------------- */
aTags = document.getElementsByTagName("a");
searchText = "lightning:lnbc";
aTags = document.getElementsByTagName("a");
searchText = "lightning:lnbc";
for (i = 0; i < aTags.length; i++) {
var href = aTags[i].getAttribute('href') + '';
if (href.indexOf(searchText) === 0) {
tryToPay(href.replace('lightning:', ''));
}
}
for (i = 0; i < aTags.length; i++) {
var href = aTags[i].getAttribute('href') + '';
if (href.indexOf(searchText) === 0) {
tryToPay(href.replace('lightning:', ''));
}
}
}, 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 {
static navigationOptions = ({ navigation }) => ({
@ -353,46 +422,28 @@ export default class Browser extends Component {
render() {
return (
<SafeBlueArea>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', minHeight: 44 }}>
<View style={styles.safeRoot}>
<TouchableOpacity
disabled={!this.state.canGoBack}
onPress={() => {
this.webview.goBack();
}}
style={{ marginHorizontal: 8 }}
style={styles.safeBack}
>
<Ionicons
name={'ios-arrow-round-back'}
name="ios-arrow-round-back"
size={36}
style={{
color: this.state.canGoBack ? 'red' : 'gray',
backgroundColor: 'transparent',
paddingLeft: 10,
}}
style={[styles.goBack, this.state.canGoBack ? styles.colorRed : styles.colorGray]}
/>
</TouchableOpacity>
<View style={{ flex: 1, marginHorizontal: 8, alignItems: 'center', justifyContent: 'center' }}>
<View
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,
}}
>
<View style={styles.safeURL}>
<View style={styles.safeURLTextWrap}>
<TextInput
onChangeText={text => this.setState({ stateURL: text })}
value={this.state.stateURL}
numberOfLines={1}
style={{ flex: 1, marginLeft: 4, minHeight: 33 }}
style={styles.safeURLText}
editable
onSubmitEditing={() => {
Keyboard.dismiss();
@ -405,7 +456,7 @@ export default class Browser extends Component {
/>
</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
<TouchableOpacity
onPress={() => {
@ -414,12 +465,9 @@ export default class Browser extends Component {
}}
>
<Ionicons
name={'ios-home'}
name="ios-home"
size={36}
style={{
color: this.state.weblnEnabled ? 'green' : 'red',
backgroundColor: 'transparent',
}}
style={[styles.transparent, this.state.weblnEnabled ? styles.colorGreen : styles.colorRed]}
/>
</TouchableOpacity>
)}
@ -434,17 +482,9 @@ export default class Browser extends Component {
}}
>
{!this.state.pageIsLoading ? (
<Ionicons
name={'ios-sync'}
size={36}
style={{
color: 'red',
backgroundColor: 'transparent',
paddingLeft: 15,
}}
/>
<Ionicons name="ios-sync" size={36} style={styles.sync} />
) : (
<View style={{ flex: 1, justifyContent: 'center', paddingLeft: 20, alignContent: 'center' }}>
<View style={styles.activity}>
<ActivityIndicator />
</View>
)}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -133,28 +133,13 @@ const ReceiveDetails = () => {
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'position' : null}>
<View style={styles.modalContent}>
<BlueBitcoinAmount amount={customAmount || ''} onChangeText={setCustomAmount} />
<View
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,
}}
>
<View style={styles.customAmount}>
<TextInput
onChangeText={setCustomLabel}
placeholder={loc.receive.details.label}
value={customLabel || ''}
numberOfLines={1}
style={{ flex: 1, marginHorizontal: 8, minHeight: 33 }}
style={styles.customAmountText}
/>
</View>
<BlueSpacing20 />
@ -187,7 +172,7 @@ const ReceiveDetails = () => {
};
return (
<SafeBlueArea style={{ flex: 1 }}>
<SafeBlueArea style={styles.root}>
{isHandOffUseEnabled && address !== undefined && (
<Handoff
title={`Bitcoin Transaction ${address}`}
@ -195,23 +180,20 @@ const ReceiveDetails = () => {
url={`https://blockstream.info/address/${address}`}
/>
)}
<ScrollView contentContainerStyle={{ justifyContent: 'space-between' }}>
<View style={{ marginTop: 32, alignItems: 'center', paddingHorizontal: 16 }}>
<ScrollView contentContainerStyle={styles.scroll}>
<View style={styles.scrollBody}>
{isCustom && (
<>
<BlueText
style={{ color: '#0c2550', fontWeight: '600', fontSize: 36, textAlign: 'center', paddingBottom: 24 }}
numberOfLines={1}
>
<BlueText style={styles.amount} numberOfLines={1}>
{customAmount} {BitcoinUnit.BTC}
</BlueText>
<BlueText style={{ color: '#0c2550', fontWeight: '600', textAlign: 'center', paddingBottom: 24 }} numberOfLines={1}>
<BlueText style={styles.label} numberOfLines={1}>
{customLabel}
</BlueText>
</>
)}
{bip21encoded === undefined ? (
<View style={{ alignItems: 'center', width: 300, height: 300 }}>
<View style={styles.loading}>
<BlueLoading />
</View>
) : (
@ -228,7 +210,7 @@ const ReceiveDetails = () => {
)}
<BlueCopyTextToClipboard text={isCustom ? bip21encoded : address} />
</View>
<View style={{ alignItems: 'center', alignContent: 'flex-end', marginBottom: 24 }}>
<View style={styles.share}>
<BlueButtonLink title={loc.receive.details.setAmount} onPress={showCustomAmountModal} />
<View>
<BlueButton
@ -272,4 +254,57 @@ const styles = StyleSheet.create({
justifyContent: 'flex-end',
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 { ScrollView, View } from 'react-native';
import { ScrollView, View, StyleSheet } from 'react-native';
import { BlueLoading, BlueSpacing20, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../BlueComponents';
import PropTypes from 'prop-types';
import { SegwitP2SHWallet, LegacyWallet, HDSegwitP2SHWallet, HDSegwitBech32Wallet } from '../class';
@ -8,6 +8,15 @@ const BlueCrypto = require('react-native-blue-crypto');
let encryption = require('../encryption');
let BlueElectrum = require('../BlueElectrum');
const styles = StyleSheet.create({
root: {
flex: 1,
},
center: {
alignItems: 'center',
},
});
export default class Selftest extends Component {
static navigationOptions = () => ({
...BlueNavigationStyle(),
@ -208,7 +217,7 @@ export default class Selftest extends Component {
}
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<BlueCard>
<ScrollView>
<BlueSpacing20 />
@ -216,7 +225,7 @@ export default class Selftest extends Component {
{(() => {
if (this.state.isOk) {
return (
<View style={{ alignItems: 'center' }}>
<View style={styles.center}>
<BlueText testID="SelfTestOk" h4>
OK
</BlueText>
@ -224,7 +233,7 @@ export default class Selftest extends Component {
);
} else {
return (
<View style={{ alignItems: 'center' }}>
<View style={styles.center}>
<BlueText h4 numberOfLines={0}>
{this.state.errorMessage}
</BlueText>

View file

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

View file

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

View file

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

View file

@ -32,7 +32,7 @@ export default class SendCreate extends Component {
...BlueNavigationStyle,
title: loc.send.create.details,
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} />
</TouchableOpacity>
) : null,
@ -110,7 +110,7 @@ export default class SendCreate extends Component {
{BitcoinUnit.BTC}
</Text>
{this.state.recipients.length > 1 && (
<BlueText style={{ alignSelf: 'flex-end' }}>
<BlueText style={styles.itemOf}>
{index + 1} of {this.state.recipients.length}
</BlueText>
)}
@ -120,41 +120,23 @@ export default class SendCreate extends Component {
};
renderSeparator = () => {
return <View style={{ backgroundColor: BlueApp.settings.inputBorderColor, height: 0.5, marginVertical: 16 }} />;
return <View style={styles.separator} />;
};
render() {
return (
<SafeBlueArea style={{ flex: 1, paddingTop: 19 }}>
<SafeBlueArea style={styles.root}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<ScrollView>
<BlueCard style={{ alignItems: 'center', flex: 1 }}>
<BlueText style={{ color: '#0c2550', fontWeight: '500' }}>{loc.send.create.this_is_hex}</BlueText>
<TextInput
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}
/>
<BlueCard style={styles.card}>
<BlueText style={styles.cardText}>{loc.send.create.this_is_hex}</BlueText>
<TextInput testID={'TxhexInput'} style={styles.cardTx} height={72} multiline editable value={this.state.tx} />
<TouchableOpacity style={{ marginVertical: 24 }} onPress={() => Clipboard.setString(this.state.tx)}>
<Text style={{ color: '#9aa0aa', fontSize: 15, fontWeight: '500', alignSelf: 'center' }}>Copy and broadcast later</Text>
<TouchableOpacity style={styles.actionTouch} onPress={() => Clipboard.setString(this.state.tx)}>
<Text style={styles.actionText}>Copy and broadcast later</Text>
</TouchableOpacity>
<TouchableOpacity style={{ marginVertical: 24 }} 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>
<TouchableOpacity style={styles.actionTouch} onPress={() => Linking.openURL('https://coinb.in/?verify=' + this.state.tx)}>
<Text style={styles.actionText}>Verify on coinb.in</Text>
</TouchableOpacity>
</BlueCard>
<BlueCard>
@ -203,6 +185,50 @@ const styles = StyleSheet.create({
fontSize: 15,
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 = {

View file

@ -49,6 +49,174 @@ let loc = require('../../loc');
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 {
static navigationOptions = ({ navigation }) => ({
...BlueCreateTxNavigationStyle(
@ -527,7 +695,7 @@ export default class SendDetails extends Component {
>
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'position' : null}>
<View style={styles.modalContent}>
<TouchableOpacity style={styles.satoshisTextInput} onPress={() => this.textInput.focus()}>
<TouchableOpacity style={styles.feeSliderInput} onPress={() => this.textInput.focus()}>
<TextInput
keyboardType="numeric"
ref={ref => {
@ -547,25 +715,13 @@ export default class SendDetails extends Component {
editable={!this.state.isLoading}
placeholderTextColor="#37c0a1"
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}
/>
<Text
style={{
fontWeight: '600',
color: '#37c0a1',
paddingRight: 4,
textAlign: 'left',
fontSize: 16,
alignSelf: 'flex-end',
marginBottom: 14,
}}
>
sat/b
</Text>
<Text style={styles.feeSliderUnit}>sat/b</Text>
</TouchableOpacity>
{this.state.networkTransactionFees.fastestFee > 1 && (
<View style={{ flex: 1, marginTop: 32, minWidth: 240, width: 240 }}>
<View style={styles.sliderContainer}>
<Slider
onValueChange={value => this.setState({ feeSliderValue: value.toFixed(0), fee: value.toFixed(0) })}
minimumValue={1}
@ -573,11 +729,11 @@ export default class SendDetails extends Component {
value={Number(this.state.feeSliderValue)}
maximumTrackTintColor="#d8d8d8"
minimumTrackTintColor="#37c0a1"
style={{ flex: 1 }}
style={styles.slider}
/>
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', marginTop: 14 }}>
<Text style={{ fontWeight: '500', fontSize: 13, color: '#37c0a1' }}>slow</Text>
<Text style={{ fontWeight: '500', fontSize: 13, color: '#37c0a1' }}>fast</Text>
<View style={styles.sliderLabels}>
<Text style={styles.sliderLabel}>slow</Text>
<Text style={styles.sliderLabel}>fast</Text>
</View>
</View>
)}
@ -720,7 +876,7 @@ export default class SendDetails extends Component {
renderCreateButton = () => {
return (
<View style={{ marginHorizontal: 56, marginVertical: 16, alignContent: 'center', backgroundColor: '#FFFFFF', minHeight: 44 }}>
<View style={styles.createButton}>
{this.state.isLoading ? (
<ActivityIndicator />
) : (
@ -733,26 +889,26 @@ export default class SendDetails extends Component {
renderWalletSelectionButton = () => {
if (this.state.renderWalletSelectionButtonHidden) return;
return (
<View style={{ marginBottom: 24, alignItems: 'center' }}>
<View style={styles.select}>
{!this.state.isLoading && (
<TouchableOpacity
style={{ flexDirection: 'row', alignItems: 'center' }}
style={styles.selectTouch}
onPress={() =>
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" />
</TouchableOpacity>
)}
<View style={{ flexDirection: 'row', alignItems: 'center', marginVertical: 4 }}>
<View style={styles.selectWrap}>
<TouchableOpacity
style={{ flexDirection: 'row', alignItems: 'center' }}
style={styles.selectTouch}
onPress={() =>
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>
</View>
</View>
@ -784,7 +940,13 @@ export default class SendDetails extends Component {
let rows = [];
for (let [index, item] of this.state.addresses.entries()) {
rows.push(
<View style={{ minWidth: width, maxWidth: width, width: width }}>
<View
style={{
minWidth: width,
maxWidth: width,
width: width,
}}
>
<BlueBitcoinAmount
isLoading={this.state.isLoading}
amount={item.amount ? item.amount.toString() : null}
@ -825,7 +987,7 @@ export default class SendDetails extends Component {
launchedBy={this.props.navigation.state.routeName}
/>
{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}
</BlueText>
)}
@ -862,20 +1024,20 @@ export default class SendDetails extends Component {
render() {
if (this.state.isLoading || typeof this.state.fromWallet === 'undefined') {
return (
<View style={{ flex: 1, paddingTop: 20 }}>
<View style={styles.loading}>
<BlueLoading />
</View>
);
}
return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View style={{ flex: 1, justifyContent: 'space-between' }}>
<View style={styles.root}>
<View>
<KeyboardAvoidingView behavior="position">
<ScrollView
pagingEnabled
horizontal
contentContainerStyle={{ flexWrap: 'wrap', flexDirection: 'row' }}
contentContainerStyle={styles.scrollViewContent}
ref={ref => (this.scrollView = ref)}
onContentSizeChange={() => this.scrollView.scrollToEnd()}
onLayout={() => this.scrollView.scrollToEnd()}
@ -885,29 +1047,13 @@ export default class SendDetails extends Component {
>
{this.renderBitcoinTransactionInfoFields()}
</ScrollView>
<View
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,
}}
>
<View hide={!this.state.showMemoRow} style={styles.memo}>
<TextInput
onChangeText={text => this.setState({ memo: text })}
placeholder={loc.send.details.note_placeholder}
value={this.state.memo}
numberOfLines={1}
style={{ flex: 1, marginHorizontal: 8, minHeight: 33 }}
style={styles.memoText}
editable={!this.state.isLoading}
onSubmitEditing={Keyboard.dismiss}
inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}
@ -916,23 +1062,12 @@ export default class SendDetails extends Component {
<TouchableOpacity
onPress={() => this.setState({ isFeeSelectionModalVisible: true })}
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>
<View
style={{
backgroundColor: '#d2f8d6',
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>
<Text style={styles.feeLabel}>Fee</Text>
<View style={styles.feeRow}>
<Text style={styles.feeValue}>{this.state.fee}</Text>
<Text style={styles.feeUnit}>sat/b</Text>
</View>
</TouchableOpacity>
{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 = {
navigation: PropTypes.shape({
pop: PropTypes.func,

View file

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

View file

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

View file

@ -1,5 +1,5 @@
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 PropTypes from 'prop-types';
import { AppStorage } from '../../class';
@ -8,6 +8,12 @@ import HandoffSettings from '../../class/handoff';
let BlueApp: AppStorage = require('../../BlueApp');
let loc = require('../../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
},
});
const GeneralSettings = () => {
const [isLoading, setIsLoading] = useState(true);
const [isAdancedModeEnabled, setIsAdancedModeEnabled] = useState(false);
@ -34,7 +40,7 @@ const GeneralSettings = () => {
return isLoading ? (
<BlueLoading />
) : (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView>
{BlueApp.getWallets().length > 1 && (
<>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
/* global alert */
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 {
BlueSpacing20,
BlueReplaceFeeSuggestions,
@ -23,6 +23,60 @@ let loc = require('../../loc');
/** @type {AppStorage} */
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 {
static navigationOptions = () => ({
...BlueNavigationStyle(null, false),
@ -116,7 +170,7 @@ export default class CPFP extends Component {
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, paddingTop: 20 }}>
<View style={styles.root}>
<ActivityIndicator />
</View>
);
@ -132,7 +186,7 @@ export default class CPFP extends Component {
if (this.state.nonReplaceable) {
return (
<SafeBlueArea style={{ flex: 1, paddingTop: 20 }}>
<SafeBlueArea style={styles.root}>
<BlueSpacing20 />
<BlueSpacing20 />
<BlueSpacing20 />
@ -145,7 +199,7 @@ export default class CPFP extends Component {
}
return (
<SafeBlueArea style={{ flex: 1, paddingBottom: 16 }}>
<SafeBlueArea style={styles.explain}>
<ScrollView>
{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.',
@ -157,33 +211,16 @@ export default class CPFP extends Component {
renderStage2() {
return (
<View style={{ flex: 1, paddingTop: 20 }}>
<BlueCard style={{ alignItems: 'center', flex: 1 }}>
<BlueText style={{ color: '#0c2550', fontWeight: '500' }}>{loc.send.create.this_is_hex}</BlueText>
<TextInput
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}
/>
<View style={styles.root}>
<BlueCard style={styles.center}>
<BlueText style={styles.hex}>{loc.send.create.this_is_hex}</BlueText>
<TextInput style={styles.hexInput} height={112} multiline editable value={this.state.txhex} />
<TouchableOpacity style={{ marginVertical: 24 }} onPress={() => Clipboard.setString(this.state.txhex)}>
<Text style={{ color: '#9aa0aa', fontSize: 15, fontWeight: '500', alignSelf: 'center' }}>Copy and broadcast later</Text>
<TouchableOpacity style={styles.action} onPress={() => Clipboard.setString(this.state.txhex)}>
<Text style={styles.actionText}>Copy and broadcast later</Text>
</TouchableOpacity>
<TouchableOpacity style={{ marginVertical: 24 }} 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>
<TouchableOpacity style={styles.action} onPress={() => Linking.openURL('https://coinb.in/?verify=' + this.state.txhex)}>
<Text style={styles.actionText}>Verify on coinb.in</Text>
</TouchableOpacity>
<BlueButton onPress={() => this.broadcast()} title={loc.send.confirm.sendNow} />
</BlueCard>
@ -193,11 +230,11 @@ export default class CPFP extends Component {
renderStage3() {
return (
<SafeBlueArea style={{ flex: 1, paddingTop: 19 }}>
<BlueCard style={{ alignItems: 'center', flex: 1 }}>
<View style={{ flexDirection: 'row', justifyContent: 'center', paddingTop: 76, paddingBottom: 16 }} />
<SafeBlueArea style={styles.doneWrap}>
<BlueCard style={styles.center}>
<View style={styles.doneCard} />
</BlueCard>
<BlueBigCheckmark style={{ marginTop: 43, marginBottom: 53 }} />
<BlueBigCheckmark style={styles.blueBigCheckmark} />
<BlueCard>
<BlueButton
onPress={() => {
@ -212,9 +249,9 @@ export default class CPFP extends Component {
renderStage1(text) {
return (
<SafeBlueArea style={{ flex: 1, paddingTop: 20 }}>
<SafeBlueArea style={styles.root}>
<BlueSpacing />
<BlueCard style={{ alignItems: 'center', flex: 1 }}>
<BlueCard style={styles.center}>
<BlueText>{text}</BlueText>
<BlueSpacing20 />
<BlueReplaceFeeSuggestions onFeeSelected={fee => this.setState({ newFeeRate: fee })} transactionMinimum={this.state.feeRate} />

View file

@ -1,6 +1,6 @@
/* global alert */
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 PropTypes from 'prop-types';
import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from '../../class';
@ -8,6 +8,13 @@ import CPFP from './CPFP';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
const styles = StyleSheet.create({
root: {
flex: 1,
paddingTop: 16,
},
});
export default class RBFBumpFee extends CPFP {
static navigationOptions = () => ({
...BlueNavigationStyle(null, false),
@ -66,7 +73,7 @@ export default class RBFBumpFee extends CPFP {
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, paddingTop: 16 }}>
<View style={styles.root}>
<ActivityIndicator />
</View>
);
@ -82,7 +89,7 @@ export default class RBFBumpFee extends CPFP {
if (this.state.nonReplaceable) {
return (
<SafeBlueArea style={{ flex: 1, paddingTop: 16 }}>
<SafeBlueArea style={styles.root}>
<BlueSpacing20 />
<BlueSpacing20 />
<BlueSpacing20 />
@ -95,7 +102,7 @@ export default class RBFBumpFee extends CPFP {
}
return (
<SafeBlueArea style={{ flex: 1, paddingBottom: 16 }}>
<SafeBlueArea style={styles.root}>
<ScrollView>
{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.',

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because one or more lines are too long

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -45,13 +45,144 @@ let EV = require('../../events');
let BlueElectrum = require('../../BlueElectrum');
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 {
static navigationOptions = ({ navigation }) => {
return {
headerRight: (
<TouchableOpacity
disabled={navigation.getParam('isLoading') === true}
style={{ marginHorizontal: 16, minWidth: 150, justifyContent: 'center', alignItems: 'flex-end' }}
style={styles.walletDetails}
onPress={() =>
navigation.navigate('WalletDetails', {
wallet: navigation.state.params.wallet,
@ -211,13 +342,13 @@ export default class WalletTransactions extends Component {
renderListFooterComponent = () => {
// 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 = () => {
return (
<View style={{ flex: 1 }}>
<View style={{ flexDirection: 'row', margin: 16, justifyContent: 'space-evenly' }}>
<View style={styles.flex}>
<View style={styles.listHeader}>
{/*
Current logic - Onchain:
- Shows buy button on middle when empty
@ -230,7 +361,7 @@ export default class WalletTransactions extends Component {
- Shows Marketplace button to open in browser (iOS)
The idea is to avoid showing on iOS an appstore/market style app that goes against the TOS.
*/}
{this.state.wallet.getTransactions().length > 0 &&
this.state.wallet.type !== LightningCustodianWallet.type &&
@ -238,19 +369,7 @@ export default class WalletTransactions extends Component {
{this.state.wallet.type === LightningCustodianWallet.type && this.renderMarketplaceButton()}
{this.state.wallet.type === LightningCustodianWallet.type && Platform.OS === 'ios' && this.renderLappBrowserButton()}
</View>
<Text
style={{
flex: 1,
marginLeft: 16,
marginTop: 8,
marginBottom: 8,
fontWeight: 'bold',
fontSize: 24,
color: BlueApp.settings.foregroundColor,
}}
>
{loc.transactions.list.title}
</Text>
<Text style={styles.listHeaderText}>{loc.transactions.list.title}</Text>
</View>
);
};
@ -333,18 +452,9 @@ export default class WalletTransactions extends Component {
this.props.navigation.navigate('Marketplace', { fromWallet: this.state.wallet });
}
}}
style={{
backgroundColor: '#f2f2f2',
borderRadius: 9,
minHeight: 49,
flex: 1,
paddingHorizontal: 8,
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
}}
style={styles.marketplaceButton1}
>
<Text style={{ color: '#062453', fontSize: 18 }}>marketplace</Text>
<Text style={styles.marketpalceText1}>marketplace</Text>
</TouchableOpacity>
),
ios:
@ -353,19 +463,10 @@ export default class WalletTransactions extends Component {
onPress={async () => {
Linking.openURL('https://bluewallet.io/marketplace/');
}}
style={{
backgroundColor: '#f2f2f2',
borderRadius: 9,
minHeight: 49,
flex: 1,
paddingHorizontal: 8,
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
}}
style={styles.marketplaceButton1}
>
<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>
) : null,
});
@ -381,19 +482,9 @@ export default class WalletTransactions extends Component {
url: 'https://duckduckgo.com',
});
}}
style={{
marginLeft: 5,
backgroundColor: '#f2f2f2',
borderRadius: 9,
minHeight: 49,
flex: 1,
paddingHorizontal: 8,
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
}}
style={styles.marketplaceButton2}
>
<Text style={{ color: '#062453', fontSize: 18 }}>LApp Browser</Text>
<Text style={styles.marketpalceText1}>LApp Browser</Text>
</TouchableOpacity>
);
};
@ -405,26 +496,9 @@ export default class WalletTransactions extends Component {
wallet: this.state.wallet,
})
}
style={{
marginLeft: 5,
backgroundColor: '#f2f2f2',
borderRadius: 9,
minHeight: 49,
flex: 1,
paddingHorizontal: 8,
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
}}
style={styles.marketplaceButton2}
>
<Text
style={{
color: '#062453',
fontSize: 18,
}}
>
{loc.wallets.list.tap_here_to_buy}
</Text>
<Text style={styles.marketpalceText1}>{loc.wallets.list.tap_here_to_buy}</Text>
</TouchableOpacity>
);
};
@ -471,7 +545,7 @@ export default class WalletTransactions extends Component {
renderItem = item => {
return (
<View style={{ marginHorizontal: 4 }}>
<View style={styles.item}>
<BlueTransactionListItem
item={item.item}
itemPriceUnit={this.state.wallet.getPreferredBalanceUnit()}
@ -574,7 +648,7 @@ export default class WalletTransactions extends Component {
render() {
const { navigate } = this.props.navigation;
return (
<View style={{ flex: 1 }}>
<View style={styles.flex}>
{this.state.wallet.chain === Chain.ONCHAIN && this.state.isHandOffUseEnabled && (
<Handoff
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
ListHeaderComponent={this.renderListHeaderComponent}
onEndReachedThreshold={0.3}
@ -636,33 +710,11 @@ export default class WalletTransactions extends Component {
}}
ListFooterComponent={this.renderListFooterComponent}
ListEmptyComponent={
<ScrollView
style={{ flex: 1 }}
contentContainerStyle={{ flex: 1, justifyContent: 'center', paddingHorizontal: 16, paddingVertical: 40 }}
>
<Text
numberOfLines={0}
style={{
fontSize: 18,
color: '#9aa0aa',
textAlign: 'center',
marginVertical: 16,
}}
>
<ScrollView style={styles.flex} contentContainerStyle={styles.scrollViewContent}>
<Text numberOfLines={0} style={styles.emptyTxs}>
{(this.isLightning() && loc.wallets.list.empty_txs1_lightning) || loc.wallets.list.empty_txs1}
</Text>
{this.isLightning() && (
<Text
style={{
fontSize: 18,
color: '#9aa0aa',
textAlign: 'center',
fontWeight: '600',
}}
>
{loc.wallets.list.empty_txs2_lightning}
</Text>
)}
{this.isLightning() && <Text style={styles.emptyTxsLightning}>{loc.wallets.list.empty_txs2_lightning}</Text>}
{!this.isLightning() && (
<TouchableOpacity
@ -671,25 +723,9 @@ export default class WalletTransactions extends Component {
wallet: this.state.wallet,
})
}
style={{
backgroundColor: '#007AFF',
minWidth: 260,
borderRadius: 8,
alignSelf: 'center',
paddingVertical: 14,
paddingHorizontal: 32,
}}
style={styles.buyBitcoin}
>
<Text
style={{
fontSize: 15,
color: '#fff',
textAlign: 'center',
fontWeight: '600',
}}
>
{loc.wallets.list.tap_here_to_buy}
</Text>
<Text style={styles.buyBitcoinText}>{loc.wallets.list.tap_here_to_buy}</Text>
</TouchableOpacity>
)}
</ScrollView>
@ -705,18 +741,7 @@ export default class WalletTransactions extends Component {
/>
{this.renderManageFundsModal()}
</View>
<View
style={{
flexDirection: 'row',
alignSelf: 'center',
backgroundColor: 'transparent',
position: 'absolute',
bottom: 30,
borderRadius: 30,
minHeight: 48,
overflow: 'hidden',
}}
>
<View style={styles.floatButtons}>
{(() => {
if (this.state.wallet.allowReceive()) {
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 = {
navigation: PropTypes.shape({
navigate: PropTypes.func,

View file

@ -1,5 +1,5 @@
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 { BlueSpacing20, SafeBlueArea, BlueText, BlueNavigationStyle, BlueCopyTextToClipboard } from '../../BlueComponents';
import PropTypes from 'prop-types';
@ -10,6 +10,18 @@ let BlueApp = require('../../BlueApp');
let loc = require('../../loc');
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 {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
@ -66,15 +78,15 @@ export default class WalletXpub extends Component {
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, paddingTop: 20 }}>
<View style={styles.root}>
<ActivityIndicator />
</View>
);
}
return (
<SafeBlueArea style={{ flex: 1, paddingTop: 20 }}>
<View style={{ alignItems: 'center', flex: 1, justifyContent: 'center' }} onLayout={this.onLayout}>
<SafeBlueArea style={styles.root}>
<View style={styles.container} onLayout={this.onLayout}>
<View>
<BlueText>{this.state.wallet.typeReadable}</BlueText>
</View>