Browse Source

Merge branch 'master' into settingsui

settingsui
Marcos Rodriguez 5 years ago
parent
commit
c8c32a11cb
  1. 276
      screen/settings/about.js
  2. 116
      screen/settings/defaultView.js
  3. 67
      screen/settings/releasenotes.js
  4. 8
      screen/wallets/list.js
  5. 43
      screen/wallets/transactions.js

276
screen/settings/about.js

@ -1,5 +1,6 @@
import React, { Component } from 'react';
import React, { useEffect, useState } from 'react';
import { ScrollView, Linking, Dimensions } from 'react-native';
import { useNavigation } from 'react-navigation-hooks';
import {
BlueTextCentered,
BlueLoading,
@ -10,156 +11,145 @@ import {
BlueText,
BlueNavigationStyle,
} from '../../BlueComponents';
import PropTypes from 'prop-types';
import { getApplicationName, getVersion, getBundleId, getBuildNumber } from 'react-native-device-info';
import Rate, { AndroidMarket } from 'react-native-rate';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
const BlueApp = require('../../BlueApp');
const { width, height } = Dimensions.get('window');
const loc = require('../../loc/');
export default class About extends Component {
static navigationOptions = () => ({
...BlueNavigationStyle(),
title: loc.settings.about,
const About = () => {
const [isLoading, setIsLoading] = useState(true);
const { navigate } = useNavigation();
useEffect(() => {
setIsLoading(false);
});
constructor(props) {
super(props);
this.state = {
isLoading: true,
};
}
const handleOnReleaseNotesPress = () => {
navigate('ReleaseNotes');
};
const handleOnSelfTestPress = () => {
navigate('Selftest');
};
const handleOnTwitterPress = () => {
Linking.openURL('https://twitter.com/bluewalletio');
};
const handleOnGithubPress = () => {
Linking.openURL('https://github.com/BlueWallet/BlueWallet');
};
async componentDidMount() {
this.setState({
isLoading: false,
const handleOnTelegramPress = () => {
Linking.openURL('https://t.me/bluewallet');
};
const handleOnRatePress = () => {
const options = {
AppleAppID: '1376878040',
GooglePackageName: 'io.bluewallet.bluewallet',
preferredAndroidMarket: AndroidMarket.Google,
preferInApp: true,
openAppStoreIfInAppFails: true,
fallbackPlatformURL: 'https://bluewallet.io',
};
Rate.rate(options, success => {
if (success) {
console.log('User Rated.');
}
});
}
render() {
if (this.state.isLoading) {
return <BlueLoading />;
}
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<ScrollView>
<BlueCard>
<BlueTextCentered h4>BlueWallet is a free and open source Bitcoin wallet. Licensed MIT.</BlueTextCentered>
<BlueSpacing20 />
<BlueTextCentered h4>Always backup your keys</BlueTextCentered>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'github',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => {
Linking.openURL('https://github.com/BlueWallet/BlueWallet');
}}
title="github.com/BlueWallet/BlueWallet"
/>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'twitter',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => {
Linking.openURL('https://twitter.com/bluewalletio');
}}
title="Follow us on Twitter"
/>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'telegram',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => {
Linking.openURL('https://t.me/bluewallet');
}}
title="Join Telegram chat"
/>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'thumbs-up',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => {
let options = {
AppleAppID: '1376878040',
GooglePackageName: 'io.bluewallet.bluewallet',
preferredAndroidMarket: AndroidMarket.Google,
preferInApp: true,
openAppStoreIfInAppFails: true,
fallbackPlatformURL: 'https://bluewallet.io',
};
Rate.rate(options, success => {
if (success) {
console.log('User Rated.');
}
});
}}
title="Rate BlueWallet"
/>
<BlueSpacing20 />
<BlueText h3>Built with awesome:</BlueText>
<BlueSpacing20 />
<BlueText h4>* React Native</BlueText>
<BlueText h4>* Bitcoinjs-lib</BlueText>
<BlueText h4>* blockcypher.com API</BlueText>
<BlueText h4>* Nodejs</BlueText>
<BlueText h4>* react-native-elements</BlueText>
<BlueText h4>* rn-nodeify</BlueText>
<BlueText h4>* bignumber.js</BlueText>
<BlueSpacing20 />
<BlueButton
onPress={() => {
this.props.navigation.navigate('ReleaseNotes');
}}
title="Release notes"
/>
<BlueSpacing20 />
<BlueButton
onPress={() => {
this.props.navigation.navigate('Selftest');
}}
title="Run self test"
/>
<BlueTextCentered />
<BlueTextCentered>
{getApplicationName()} ver {getVersion()} (build {getBuildNumber()})
</BlueTextCentered>
<BlueTextCentered>{new Date(getBuildNumber() * 1000).toGMTString()}</BlueTextCentered>
<BlueTextCentered>{getBundleId()}</BlueTextCentered>
<BlueTextCentered>
w, h = {width}, {height}
</BlueTextCentered>
</BlueCard>
</ScrollView>
</SafeBlueArea>
);
}
}
About.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
goBack: PropTypes.func,
}),
};
return isLoading ? (
<BlueLoading />
) : (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<ScrollView>
<BlueCard>
<BlueTextCentered h4>BlueWallet is a free and open source Bitcoin wallet. Licensed MIT.</BlueTextCentered>
<BlueSpacing20 />
<BlueTextCentered h4>Always backup your keys</BlueTextCentered>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'github',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={handleOnGithubPress}
title="github.com/BlueWallet/BlueWallet"
/>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'twitter',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={handleOnTwitterPress}
title="Follow us on Twitter"
/>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'telegram',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={handleOnTelegramPress}
title="Join Telegram chat"
/>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'thumbs-up',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={handleOnRatePress}
title="Rate BlueWallet"
/>
<BlueSpacing20 />
<BlueText h3>Built with awesome:</BlueText>
<BlueSpacing20 />
<BlueText h4>* React Native</BlueText>
<BlueText h4>* Bitcoinjs-lib</BlueText>
<BlueText h4>* blockcypher.com API</BlueText>
<BlueText h4>* Nodejs</BlueText>
<BlueText h4>* react-native-elements</BlueText>
<BlueText h4>* rn-nodeify</BlueText>
<BlueText h4>* bignumber.js</BlueText>
<BlueSpacing20 />
<BlueButton onPress={handleOnReleaseNotesPress} title="Release notes" />
<BlueSpacing20 />
<BlueButton onPress={handleOnSelfTestPress} title="Run self test" />
<BlueTextCentered />
<BlueTextCentered>
{getApplicationName()} ver {getVersion()} (build {getBuildNumber()})
</BlueTextCentered>
<BlueTextCentered>{new Date(getBuildNumber() * 1000).toGMTString()}</BlueTextCentered>
<BlueTextCentered>{getBundleId()}</BlueTextCentered>
<BlueTextCentered>
w, h = {width}, {height}
</BlueTextCentered>
</BlueCard>
</ScrollView>
</SafeBlueArea>
);
};
About.navigationOptions = () => ({
...BlueNavigationStyle(),
title: loc.settings.about,
});
export default About;

116
screen/settings/defaultView.js

@ -1,80 +1,74 @@
import React, { Component } from 'react';
import React, { useEffect, useState } from 'react';
import { TouchableOpacity, View } from 'react-native';
import { SafeBlueArea, BlueNavigationStyle, BlueListItem } from '../../BlueComponents';
import PropTypes from 'prop-types';
import OnAppLaunch from '../../class/onAppLaunch';
import { useNavigation } from 'react-navigation-hooks';
const BlueApp = require('../../BlueApp');
export default class DefaultView extends Component {
static navigationOptions = () => ({
...BlueNavigationStyle(),
title: 'On Launch',
});
constructor(props) {
super(props);
this.state = { defaultWalletLabel: '', viewAllWalletsEnabled: true };
}
async componentDidMount() {
const viewAllWalletsEnabled = await OnAppLaunch.isViewAllWalletsEnabled();
let defaultWalletLabel = '';
const wallet = await OnAppLaunch.getSelectedDefaultWallet();
if (wallet) {
defaultWalletLabel = wallet.getLabel();
}
this.setState({ viewAllWalletsEnabled, defaultWalletLabel });
}
const DefaultView = () => {
const [defaultWalletLabel, setDefaultWalletLabel] = useState('');
const [viewAllWalletsEnabled, setViewAllWalletsEnabled] = useState(true);
const { navigate, pop } = useNavigation();
selectWallet = () => {
this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelectValueChanged });
};
useEffect(() => {
(async () => {
const viewAllWalletsEnabled = await OnAppLaunch.isViewAllWalletsEnabled();
let defaultWalletLabel = '';
const wallet = await OnAppLaunch.getSelectedDefaultWallet();
if (wallet) {
defaultWalletLabel = wallet.getLabel();
}
setDefaultWalletLabel(defaultWalletLabel);
setViewAllWalletsEnabled(viewAllWalletsEnabled);
})();
});
onViewAllWalletsSwitchValueChanged = async value => {
const onViewAllWalletsSwitchValueChanged = async value => {
await OnAppLaunch.setViewAllWalletsEnabled(value);
if (value) {
return this.setState({ viewAllWalletsEnabled: true, defaultWalletLabel: '' });
setViewAllWalletsEnabled(true);
setDefaultWalletLabel('');
} else {
const selectedWallet = await OnAppLaunch.getSelectedDefaultWallet();
return this.setState({ viewAllWalletsEnabled: false, defaultWalletLabel: selectedWallet.getLabel() });
setDefaultWalletLabel(selectedWallet.getLabel());
setViewAllWalletsEnabled(false);
}
};
onWalletSelectValueChanged = async wallet => {
const selectWallet = () => {
navigate('SelectWallet', { onWalletSelect: onWalletSelectValueChanged });
};
const onWalletSelectValueChanged = async wallet => {
await OnAppLaunch.setViewAllWalletsEnabled(false);
await OnAppLaunch.setSelectedDefaultWallet(wallet.getID());
this.setState({ defaultWalletLabel: wallet.getLabel(), viewAllWalletsEnabled: false }, () => this.props.navigation.pop());
setDefaultWalletLabel(wallet.getLabel());
setViewAllWalletsEnabled(false);
pop();
};
render() {
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<View>
<BlueListItem
title="View All Wallets"
hideChevron
switchButton
swithchEnabled={BlueApp.getWallets().length > 0}
switched={this.state.viewAllWalletsEnabled}
onSwitch={this.onViewAllWalletsSwitchValueChanged}
/>
{!this.state.viewAllWalletsEnabled && (
<BlueListItem
title="Default into"
component={TouchableOpacity}
onPress={this.selectWallet}
rightTitle={this.state.defaultWalletLabel}
/>
)}
</View>
</SafeBlueArea>
);
}
}
DefaultView.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
pop: PropTypes.func,
}),
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<View>
<BlueListItem
title="View All Wallets"
hideChevron
switchButton
swithchEnabled={BlueApp.getWallets().length > 0}
switched={viewAllWalletsEnabled}
onSwitch={onViewAllWalletsSwitchValueChanged}
/>
{!viewAllWalletsEnabled && (
<BlueListItem title="Default into" component={TouchableOpacity} onPress={selectWallet} rightTitle={defaultWalletLabel} />
)}
</View>
</SafeBlueArea>
);
};
DefaultView.navigationOptions = () => ({
...BlueNavigationStyle(),
title: 'On Launch',
});
export default DefaultView;

67
screen/settings/releasenotes.js

@ -1,51 +1,32 @@
import React, { Component } from 'react';
import React, { useState, useEffect } from 'react';
import { ScrollView } from 'react-native';
import { BlueLoading, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../../BlueComponents';
import PropTypes from 'prop-types';
/** @type {AppStorage} */
const notes = require('../../release-notes');
export default class ReleaseNotes extends Component {
static navigationOptions = () => ({
...BlueNavigationStyle(),
title: 'Release notes',
});
constructor(props) {
super(props);
this.state = {
isLoading: true,
};
}
const ReleaseNotes = () => {
const [isLoading, setIsLoading] = useState(true);
const notes = require('../../release-notes');
async componentDidMount() {
console.log(notes);
this.setState({
isLoading: false,
notes: notes,
});
}
useEffect(() => {
setIsLoading(false);
});
render() {
if (this.state.isLoading) {
return <BlueLoading />;
}
return isLoading ? (
(<BlueLoading />)
) : (
(<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<ScrollView>
<BlueCard>
<BlueText>{notes}</BlueText>
</BlueCard>
</ScrollView>
</SafeBlueArea>)
);
};
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<ScrollView>
<BlueCard>
<BlueText>{this.state.notes}</BlueText>
</BlueCard>
</ScrollView>
</SafeBlueArea>
);
}
}
ReleaseNotes.navigationOptions = () => ({
...BlueNavigationStyle(),
title: 'Release notes',
});
ReleaseNotes.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
goBack: PropTypes.func,
}),
};
export default ReleaseNotes;

8
screen/wallets/list.js

@ -1,3 +1,4 @@
/* global alert */
import React, { Component } from 'react';
import { View, TouchableOpacity, Text, FlatList, InteractionManager, RefreshControl, ScrollView } from 'react-native';
import { BlueLoading, SafeBlueArea, WalletsCarousel, BlueList, BlueHeaderDefaultMain, BlueTransactionListItem } from '../../BlueComponents';
@ -63,8 +64,9 @@ export default class WalletsList extends Component {
await BlueApp.fetchWalletTransactions();
let end = +new Date();
console.log('fetch all wallet txs took', (end - start) / 1000, 'sec');
} catch (_) {
} catch (error) {
noErr = false;
alert(error);
}
if (noErr) this.redrawScreen();
});
@ -100,6 +102,7 @@ export default class WalletsList extends Component {
console.log('fetch tx took', (end - start) / 1000, 'sec');
} catch (err) {
noErr = false;
alert(err);
console.warn(err);
}
if (noErr) await BlueApp.saveToDisk(); // caching
@ -217,6 +220,7 @@ export default class WalletsList extends Component {
}
} catch (Err) {
noErr = false;
alert(Err);
console.warn(Err);
}
@ -283,7 +287,7 @@ export default class WalletsList extends Component {
onSnapToItem={index => {
this.onSnapToItem(index);
}}
ref={c => this.walletsCarousel = c}
ref={c => (this.walletsCarousel = c)}
/>
<BlueList>
<FlatList

43
screen/wallets/transactions.js

@ -107,6 +107,7 @@ export default class WalletTransactions extends Component {
*/
getTransactions(limit = Infinity) {
let wallet = this.props.navigation.getParam('wallet');
let txs = wallet.getTransactions();
for (let tx of txs) {
tx.sort_ts = +new Date(tx.received);
@ -131,7 +132,7 @@ export default class WalletTransactions extends Component {
isLightning() {
let w = this.state.wallet;
if (w && w.type === LightningCustodianWallet.type) {
if (w && w.chain === Chain.OFFCHAIN) {
return true;
}
@ -201,7 +202,21 @@ export default class WalletTransactions extends Component {
renderListHeaderComponent = () => {
return (
<View style={{ flex: 1, flexDirection: 'row' }}>
<View style={{ flex: 1 }}>
<View style={{ flexDirection: 'row', margin: 16, justifyContent: 'space-evenly' }}>
{/*
So the idea here, due to Apple banning native Lapp marketplace, is:
On Android everythins works as it worked before. Single "Marketplace" button that leads to LappBrowser that
opens /marketplace/ url of offchain wallet type, and /marketplace-btc/ for onchain.
On iOS its more complicated - we have one button that opens same page _externally_ (in Safari), and second
button that opens actual LappBrowser but with _blank_ page. This is important to not trigger Apple.
Blank page is also the way Trust Wallet does it with Dapp Browser.
For ONCHAIN wallet type no LappBrowser button should be displayed, its Lightning-network specific.
*/}
{this.renderMarketplaceButton()}
{this.state.wallet.type === LightningCustodianWallet.type && Platform.OS === 'ios' && this.renderLappBrowserButton()}
</View>
<Text
style={{
flex: 1,
@ -420,24 +435,11 @@ export default class WalletTransactions extends Component {
}
onManageFundsPressed={() => this.setState({ isManageFundsModalVisible: true })}
/>
<View style={{ backgroundColor: '#FFFFFF' }}>
<View style={{ flexDirection: 'row', margin: 16, justifyContent: 'space-evenly' }}>
{/*
So the idea here, due to Apple banning native Lapp marketplace, is:
On Android everythins works as it worked before. Single "Marketplace" button that leads to LappBrowser that
opens /marketplace/ url of offchain wallet type, and /marketplace-btc/ for onchain.
On iOS its more complicated - we have one button that opens same page _externally_ (in Safari), and second
button that opens actual LappBrowser but with _blank_ page. This is important to not trigger Apple.
Blank page is also the way Trust Wallet does it with Dapp Browser.
For ONCHAIN wallet type no LappBrowser button should be displayed, its Lightning-network specific.
*/}
{this.renderMarketplaceButton()}
{this.state.wallet.type === LightningCustodianWallet.type && Platform.OS === 'ios' && this.renderLappBrowserButton()}
</View>
<View style={{ backgroundColor: '#FFFFFF', flex: 1 }}>
<FlatList
ListHeaderComponent={this.renderListHeaderComponent}
onEndReachedThreshold={0.3}
onEndReached={() => {
onEndReached={async () => {
// pagination in works. in this block we will add more txs to flatlist
// so as user scrolls closer to bottom it will render mode transactions
@ -452,7 +454,6 @@ export default class WalletTransactions extends Component {
pageSize: this.state.pageSize * 2,
});
}}
ListHeaderComponent={this.renderListHeaderComponent}
ListFooterComponent={this.renderListFooterComponent}
ListEmptyComponent={
<ScrollView style={{ minHeight: 100 }} contentContainerStyle={{ flex: 1, justifyContent: 'center', paddingHorizontal: 16 }}>
@ -527,7 +528,7 @@ export default class WalletTransactions extends Component {
return (
<BlueReceiveButtonIcon
onPress={() => {
if (this.state.wallet.type === LightningCustodianWallet.type) {
if (this.state.wallet.chain === Chain.OFFCHAIN) {
navigate('LNDCreateInvoice', { fromWallet: this.state.wallet });
} else {
navigate('ReceiveDetails', { secret: this.state.wallet.getSecret() });
@ -543,7 +544,7 @@ export default class WalletTransactions extends Component {
return (
<BlueSendButtonIcon
onPress={() => {
if (this.state.wallet.type === LightningCustodianWallet.type) {
if (this.state.wallet.chain === Chain.OFFCHAIN) {
navigate('ScanLndInvoice', { fromSecret: this.state.wallet.getSecret() });
} else {
navigate('SendDetails', {

Loading…
Cancel
Save