ADD: Dark Mode

This commit is contained in:
Marcos Rodriguez Vélez 2020-07-15 13:32:59 -04:00 committed by GitHub
parent 8e0fc159e2
commit 2ce7111687
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
62 changed files with 2071 additions and 1769 deletions

22
App.js
View file

@ -3,18 +3,20 @@ import React from 'react';
import { Linking, Appearance, DeviceEventEmitter, AppState, StyleSheet, KeyboardAvoidingView, Platform, View } from 'react-native'; import { Linking, Appearance, DeviceEventEmitter, AppState, StyleSheet, KeyboardAvoidingView, Platform, View } from 'react-native';
import Clipboard from '@react-native-community/clipboard'; import Clipboard from '@react-native-community/clipboard';
import Modal from 'react-native-modal'; import Modal from 'react-native-modal';
import { NavigationContainer, CommonActions, DefaultTheme, DarkTheme } from '@react-navigation/native'; import { NavigationContainer, CommonActions } from '@react-navigation/native';
import { SafeAreaProvider } from 'react-native-safe-area-context'; import { SafeAreaProvider } from 'react-native-safe-area-context';
import Navigation from './Navigation'; import Navigation from './Navigation';
import { navigationRef } from './NavigationService'; import { navigationRef } from './NavigationService';
import * as NavigationService from './NavigationService'; import * as NavigationService from './NavigationService';
import { BlueTextCentered, BlueButton } from './BlueComponents'; import { BlueTextCentered, BlueButton, SecondButton } from './BlueComponents';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { Chain } from './models/bitcoinUnits'; import { Chain } from './models/bitcoinUnits';
import QuickActions from 'react-native-quick-actions'; import QuickActions from 'react-native-quick-actions';
import * as Sentry from '@sentry/react-native'; import * as Sentry from '@sentry/react-native';
import OnAppLaunch from './class/on-app-launch'; import OnAppLaunch from './class/on-app-launch';
import DeeplinkSchemaMatch from './class/deeplink-schema-match'; import DeeplinkSchemaMatch from './class/deeplink-schema-match';
import { BlueDefaultTheme, BlueDarkTheme, BlueCurrentTheme } from './components/themes';
const A = require('./blue_modules/analytics'); const A = require('./blue_modules/analytics');
if (process.env.NODE_ENV !== 'development') { if (process.env.NODE_ENV !== 'development') {
@ -35,12 +37,21 @@ export default class App extends React.Component {
isClipboardContentModalVisible: false, isClipboardContentModalVisible: false,
clipboardContentModalAddressType: bitcoinModalString, clipboardContentModalAddressType: bitcoinModalString,
clipboardContent: '', clipboardContent: '',
theme: Appearance.getColorScheme(),
}; };
componentDidMount() { componentDidMount() {
EV(EV.enum.WALLETS_INITIALIZED, this.addListeners); EV(EV.enum.WALLETS_INITIALIZED, this.addListeners);
Appearance.addChangeListener(this.appearanceChanged);
} }
appearanceChanged = () => {
const appearance = Appearance.getColorScheme();
if (appearance) {
this.setState({ theme: appearance });
}
};
addListeners = () => { addListeners = () => {
Linking.addEventListener('url', this.handleOpenURL); Linking.addEventListener('url', this.handleOpenURL);
AppState.addEventListener('change', this._handleAppStateChange); AppState.addEventListener('change', this._handleAppStateChange);
@ -104,6 +115,7 @@ export default class App extends React.Component {
componentWillUnmount() { componentWillUnmount() {
Linking.removeEventListener('url', this.handleOpenURL); Linking.removeEventListener('url', this.handleOpenURL);
AppState.removeEventListener('change', this._handleAppStateChange); AppState.removeEventListener('change', this._handleAppStateChange);
Appearance.removeChangeListener(this.appearanceChanged);
} }
_handleAppStateChange = async nextAppState => { _handleAppStateChange = async nextAppState => {
@ -192,7 +204,7 @@ export default class App extends React.Component {
You have a {this.state.clipboardContentModalAddressType} on your clipboard. Would you like to use it for a transaction? You have a {this.state.clipboardContentModalAddressType} on your clipboard. Would you like to use it for a transaction?
</BlueTextCentered> </BlueTextCentered>
<View style={styles.modelContentButtonLayout}> <View style={styles.modelContentButtonLayout}>
<BlueButton <SecondButton
noMinWidth noMinWidth
title={loc.send.details.cancel} title={loc.send.details.cancel}
onPress={() => this.setState({ isClipboardContentModalVisible: false })} onPress={() => this.setState({ isClipboardContentModalVisible: false })}
@ -219,7 +231,7 @@ export default class App extends React.Component {
return ( return (
<SafeAreaProvider> <SafeAreaProvider>
<View style={styles.root}> <View style={styles.root}>
<NavigationContainer ref={navigationRef} theme={Appearance.getColorScheme() === 'dark' ? { ...DarkTheme } : DefaultTheme} tr> <NavigationContainer ref={navigationRef} theme={this.state.theme === 'dark' ? BlueDarkTheme : BlueDefaultTheme}>
<Navigation /> <Navigation />
</NavigationContainer> </NavigationContainer>
{this.renderClipboardContentModal()} {this.renderClipboardContentModal()}
@ -237,7 +249,7 @@ const styles = StyleSheet.create({
marginHorizontal: 8, marginHorizontal: 8,
}, },
modalContent: { modalContent: {
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.elevated,
padding: 22, padding: 22,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',

File diff suppressed because it is too large Load diff

View file

@ -62,8 +62,7 @@ import LNDViewInvoice from './screen/lnd/lndViewInvoice';
import LNDViewAdditionalInvoiceInformation from './screen/lnd/lndViewAdditionalInvoiceInformation'; import LNDViewAdditionalInvoiceInformation from './screen/lnd/lndViewAdditionalInvoiceInformation';
import LoadingScreen from './LoadingScreen'; import LoadingScreen from './LoadingScreen';
import UnlockWith from './UnlockWith'; import UnlockWith from './UnlockWith';
const BlueApp = require('./BlueApp'); import { BlueNavigationStyle } from './BlueComponents';
const loc = require('./loc');
const SCREEN_HEIGHT = Dimensions.get('window').height; const SCREEN_HEIGHT = Dimensions.get('window').height;
const defaultScreenOptions = const defaultScreenOptions =
@ -103,15 +102,9 @@ const WalletsRoot = () => (
name="Settings" name="Settings"
component={Settings} component={Settings}
options={{ options={{
headerStyle: { ...BlueNavigationStyle(),
backgroundColor: '#FFFFFF',
borderBottomWidth: 0, headerTitle: '',
elevation: 0,
shadowColor: 'transparent',
},
title: '',
headerBackTitleVisible: false,
headerTintColor: '#0c2550',
}} }}
/> />
<WalletsStack.Screen name="SelectWallet" component={SelectWallet} options={SelectWallet.navigationOptions} /> <WalletsStack.Screen name="SelectWallet" component={SelectWallet} options={SelectWallet.navigationOptions} />
@ -140,18 +133,8 @@ const WalletsRoot = () => (
component={LNDViewAdditionalInvoiceInformation} component={LNDViewAdditionalInvoiceInformation}
options={LNDViewAdditionalInvoiceInformation.navigationOptions} options={LNDViewAdditionalInvoiceInformation.navigationOptions}
/> />
<WalletsStack.Screen <WalletsStack.Screen name="HodlHodlViewOffer" component={HodlHodlViewOffer} options={HodlHodlViewOffer.navigationOptions} />
name="Broadcast" <WalletsStack.Screen name="Broadcast" component={Broadcast} options={Broadcast.navigationOptions} />
component={Broadcast}
options={{
title: 'Broadcast',
headerStyle: {
backgroundColor: '#FFFFFF',
borderBottomWidth: 0,
},
headerTintColor: '#0c2550',
}}
/>
</WalletsStack.Navigator> </WalletsStack.Navigator>
); );
@ -189,16 +172,7 @@ const SendDetailsRoot = () => (
}} }}
/> />
<SendDetailsStack.Screen name="Success" component={Success} options={Success.navigationOptions} /> <SendDetailsStack.Screen name="Success" component={Success} options={Success.navigationOptions} />
<SendDetailsStack.Screen <SendDetailsStack.Screen name="SelectWallet" component={SelectWallet} options={SelectWallet.navigationOptions} />
name="SelectWallet"
component={SelectWallet}
options={{
headerTitle: loc.wallets.select_wallet,
headerRight: null,
headerBackTitleVisible: false,
headerTintColor: BlueApp.settings.foregroundColor,
}}
/>
</SendDetailsStack.Navigator> </SendDetailsStack.Navigator>
); );
@ -206,16 +180,7 @@ const LNDCreateInvoiceStack = createStackNavigator();
const LNDCreateInvoiceRoot = () => ( const LNDCreateInvoiceRoot = () => (
<LNDCreateInvoiceStack.Navigator screenOptions={defaultStackScreenOptions}> <LNDCreateInvoiceStack.Navigator screenOptions={defaultStackScreenOptions}>
<LNDCreateInvoiceStack.Screen name="LNDCreateInvoice" component={LNDCreateInvoice} options={LNDCreateInvoice.navigationOptions} /> <LNDCreateInvoiceStack.Screen name="LNDCreateInvoice" component={LNDCreateInvoice} options={LNDCreateInvoice.navigationOptions} />
<LNDCreateInvoiceStack.Screen <LNDCreateInvoiceStack.Screen name="SelectWallet" component={SelectWallet} options={SelectWallet.navigationOptions} />
name="SelectWallet"
component={SelectWallet}
options={{
headerTitle: loc.wallets.select_wallet,
headerRight: null,
headerBackTitleVisible: false,
headerTintColor: BlueApp.settings.foregroundColor,
}}
/>
<LNDCreateInvoiceStack.Screen <LNDCreateInvoiceStack.Screen
name="LNDViewInvoice" name="LNDViewInvoice"
component={LNDViewInvoice} component={LNDViewInvoice}
@ -231,32 +196,12 @@ const LNDCreateInvoiceRoot = () => (
</LNDCreateInvoiceStack.Navigator> </LNDCreateInvoiceStack.Navigator>
); );
const HodlHodlStack = createStackNavigator();
const HodlHodlRoot = () => (
<HodlHodlStack.Navigator>
<HodlHodlStack.Screen name="HodlHodl" component={HodlHodl} options={HodlHodl.navigationOptions} />
<HodlHodlStack.Screen name="HodlHodlViewOffer" component={HodlHodlViewOffer} options={HodlHodlViewOffer.navigationOptions} />
<HodlHodlStack.Screen name="HodlHodlLogin" component={HodlHodlLogin} options={HodlHodlLogin.navigationOptions} />
<HodlHodlStack.Screen name="HodlHodlMyContracts" component={HodlHodlMyContracts} options={HodlHodlMyContracts.navigationOptions} />
<HodlHodlStack.Screen name="HodlHodlWebview" component={HodlHodlWebview} options={HodlHodlWebview.navigationOptions} />
</HodlHodlStack.Navigator>
);
// LightningScanInvoiceStackNavigator === ScanLndInvoiceStack // LightningScanInvoiceStackNavigator === ScanLndInvoiceStack
const ScanLndInvoiceStack = createStackNavigator(); const ScanLndInvoiceStack = createStackNavigator();
const ScanLndInvoiceRoot = () => ( const ScanLndInvoiceRoot = () => (
<ScanLndInvoiceStack.Navigator screenOptions={defaultStackScreenOptions}> <ScanLndInvoiceStack.Navigator screenOptions={defaultStackScreenOptions}>
<ScanLndInvoiceStack.Screen name="ScanLndInvoice" component={ScanLndInvoice} options={ScanLndInvoice.navigationOptions} /> <ScanLndInvoiceStack.Screen name="ScanLndInvoice" component={ScanLndInvoice} options={ScanLndInvoice.navigationOptions} />
<ScanLndInvoiceStack.Screen <ScanLndInvoiceStack.Screen name="SelectWallet" component={SelectWallet} options={SelectWallet.navigationOptions} />
name="SelectWallet"
component={SelectWallet}
options={{
headerTitle: loc.wallets.select_wallet,
headerRight: null,
headerBackTitleVisible: false,
headerTintColor: BlueApp.settings.foregroundColor,
}}
/>
<ScanLndInvoiceStack.Screen name="Success" component={Success} options={Success.navigationOptions} /> <ScanLndInvoiceStack.Screen name="Success" component={Success} options={Success.navigationOptions} />
</ScanLndInvoiceStack.Navigator> </ScanLndInvoiceStack.Navigator>
); );
@ -290,6 +235,13 @@ const UnlockWithScreenRoot = () => (
</UnlockWithScreenStack.Navigator> </UnlockWithScreenStack.Navigator>
); );
const HodlHodlLoginStack = createStackNavigator();
const HodlHodlLoginRoot = () => (
<HodlHodlLoginStack.Navigator name="HodlHodlLoginRoot" screenOptions={defaultStackScreenOptions}>
<HodlHodlLoginStack.Screen name="HodlHodlLogin" component={HodlHodlLogin} options={HodlHodlLogin.navigationOptions} />
</HodlHodlLoginStack.Navigator>
);
const RootStack = createStackNavigator(); const RootStack = createStackNavigator();
const Navigation = () => ( const Navigation = () => (
<RootStack.Navigator mode="modal" screenOptions={defaultScreenOptions} initialRouteName="LoadingScreenRoot"> <RootStack.Navigator mode="modal" screenOptions={defaultScreenOptions} initialRouteName="LoadingScreenRoot">
@ -306,7 +258,9 @@ const Navigation = () => (
<RootStack.Screen name="LNDCreateInvoiceRoot" component={LNDCreateInvoiceRoot} options={{ headerShown: false }} /> <RootStack.Screen name="LNDCreateInvoiceRoot" component={LNDCreateInvoiceRoot} options={{ headerShown: false }} />
<RootStack.Screen name="ScanLndInvoiceRoot" component={ScanLndInvoiceRoot} options={{ headerShown: false }} /> <RootStack.Screen name="ScanLndInvoiceRoot" component={ScanLndInvoiceRoot} options={{ headerShown: false }} />
<RootStack.Screen name="AztecoRedeemRoot" component={AztecoRedeemRoot} options={{ headerShown: false }} /> <RootStack.Screen name="AztecoRedeemRoot" component={AztecoRedeemRoot} options={{ headerShown: false }} />
<RootStack.Screen name="HodlHodlRoot" component={HodlHodlRoot} options={{ headerShown: false }} /> <RootStack.Screen name="HodlHodlLoginRoot" component={HodlHodlLoginRoot} options={{ headerShown: false }} />
<RootStack.Screen name="HodlHodlMyContracts" component={HodlHodlMyContracts} options={HodlHodlMyContracts.navigationOptions} />
<RootStack.Screen name="HodlHodlWebview" component={HodlHodlWebview} options={HodlHodlWebview.navigationOptions} />
<RootStack.Screen <RootStack.Screen
name="ScanQRCodeRoot" name="ScanQRCodeRoot"
component={ScanQRCodeRoot} component={ScanQRCodeRoot}

View file

@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { View, Image, TouchableOpacity, StyleSheet, Appearance } from 'react-native'; import { View, Image, TouchableOpacity, StyleSheet, Appearance, StatusBar } from 'react-native';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import Biometric from './class/biometrics'; import Biometric from './class/biometrics';
import { SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaView } from 'react-native-safe-area-context';
@ -48,9 +48,10 @@ const styles = StyleSheet.create({
}); });
export default class UnlockWith extends Component { export default class UnlockWith extends Component {
state = { biometricType: false, isStorageEncrypted: false, isAuthenticating: false }; state = { biometricType: false, isStorageEncrypted: false, isAuthenticating: false, appearance: Appearance.getColorScheme() };
async componentDidMount() { async componentDidMount() {
Appearance.addChangeListener(this.appearanceChanged);
let biometricType = false; let biometricType = false;
if (await Biometric.isBiometricUseCapableAndEnabled()) { if (await Biometric.isBiometricUseCapableAndEnabled()) {
biometricType = await Biometric.biometricType(); biometricType = await Biometric.biometricType();
@ -63,6 +64,17 @@ export default class UnlockWith extends Component {
}); });
} }
componentWillUnmount() {
Appearance.removeChangeListener();
}
appearanceChanged = () => {
const appearance = Appearance.getColorScheme();
if (appearance) {
this.setState({ appearance });
}
};
successfullyAuthenticated = () => { successfullyAuthenticated = () => {
EV(EV.enum.WALLETS_INITIALIZED); EV(EV.enum.WALLETS_INITIALIZED);
NavigationService.dispatch(StackActions.replace('WalletsRoot')); NavigationService.dispatch(StackActions.replace('WalletsRoot'));
@ -94,9 +106,10 @@ export default class UnlockWith extends Component {
return <View />; return <View />;
} }
const color = Appearance.getColorScheme() === 'dark' ? '#FFFFFF' : '#000000'; const color = this.state.appearance === 'dark' ? '#FFFFFF' : '#000000';
return ( return (
<SafeAreaView style={styles.root}> <SafeAreaView style={styles.root}>
<StatusBar barStyle="default" />
<View style={styles.container}> <View style={styles.container}>
<View style={styles.qrCode}> <View style={styles.qrCode}>
<Image source={require('./img/qr-code.png')} style={styles.qrCodeImage} /> <Image source={require('./img/qr-code.png')} style={styles.qrCodeImage} />
@ -115,9 +128,7 @@ export default class UnlockWith extends Component {
<> <>
<TouchableOpacity disabled={this.state.isAuthenticating} onPress={this.unlockWithBiometrics}> <TouchableOpacity disabled={this.state.isAuthenticating} onPress={this.unlockWithBiometrics}>
<Image <Image
source={ source={this.state.appearance === 'dark' ? require('./img/faceid-default.png') : require('./img/faceid-dark.png')}
Appearance.getColorScheme() === 'dark' ? require('./img/faceid-default.png') : require('./img/faceid-dark.png')
}
style={styles.icon} style={styles.icon}
/> />
</TouchableOpacity> </TouchableOpacity>

View file

@ -39,32 +39,6 @@ export class AppStorage {
this.wallets = []; this.wallets = [];
this.tx_metadata = {}; this.tx_metadata = {};
this.cachedPassword = false; this.cachedPassword = false;
this.settings = {
brandingColor: '#ffffff',
foregroundColor: '#0c2550',
buttonBackgroundColor: '#ccddf9',
buttonTextColor: '#0c2550',
buttonAlternativeTextColor: '#2f5fb3',
buttonDisabledBackgroundColor: '#eef0f4',
buttonDisabledTextColor: '#9aa0aa',
inputBorderColor: '#d2d2d2',
inputBackgroundColor: '#f5f5f5',
alternativeTextColor: '#9aa0aa',
alternativeTextColor2: '#0f5cc0',
buttonBlueBackgroundColor: '#ccddf9',
incomingBackgroundColor: '#d2f8d6',
incomingForegroundColor: '#37c0a1',
outgoingBackgroundColor: '#f8d2d2',
outgoingForegroundColor: '#d0021b',
successColor: '#37c0a1',
failedColor: '#ff0000',
shadowColor: '#000000',
inverseForegroundColor: '#ffffff',
hdborderColor: '#68BBE1',
hdbackgroundColor: '#ECF9FF',
lnborderColor: '#F7C056',
lnbackgroundColor: '#FFFAEF',
};
} }
/** /**

View file

@ -9,6 +9,7 @@ import { PlaceholderWallet } from './wallets/placeholder-wallet';
import { SegwitBech32Wallet } from './wallets/segwit-bech32-wallet'; import { SegwitBech32Wallet } from './wallets/segwit-bech32-wallet';
import { HDLegacyElectrumSeedP2PKHWallet } from './wallets/hd-legacy-electrum-seed-p2pkh-wallet'; import { HDLegacyElectrumSeedP2PKHWallet } from './wallets/hd-legacy-electrum-seed-p2pkh-wallet';
import { HDSegwitElectrumSeedP2WPKHWallet } from './wallets/hd-segwit-electrum-seed-p2wpkh-wallet'; import { HDSegwitElectrumSeedP2WPKHWallet } from './wallets/hd-segwit-electrum-seed-p2wpkh-wallet';
import { BlueCurrentTheme } from '../components/themes';
export default class WalletGradient { export default class WalletGradient {
static hdSegwitP2SHWallet = ['#65ceef', '#68bbe1']; static hdSegwitP2SHWallet = ['#65ceef', '#68bbe1'];
@ -20,7 +21,7 @@ export default class WalletGradient {
static hdLegacyBreadWallet = ['#fe6381', '#f99c42']; static hdLegacyBreadWallet = ['#fe6381', '#f99c42'];
static defaultGradients = ['#c65afb', '#9053fe']; static defaultGradients = ['#c65afb', '#9053fe'];
static lightningCustodianWallet = ['#f1be07', '#f79056']; static lightningCustodianWallet = ['#f1be07', '#f79056'];
static createWallet = '#eef0f4'; static createWallet = BlueCurrentTheme.colors.lightButton;
static gradientsFor(type) { static gradientsFor(type) {
let gradient; let gradient;

105
components/themes.js Normal file
View file

@ -0,0 +1,105 @@
import { DefaultTheme, DarkTheme } from '@react-navigation/native';
import { Appearance } from 'react-native';
export const BlueDefaultTheme = {
...DefaultTheme,
closeImage: require('../img/close.png'),
scanImage: require('../img/scan.png'),
colors: {
...DefaultTheme.colors,
brandingColor: '#ffffff',
foregroundColor: '#0c2550',
borderTopColor: 'rgba(0, 0, 0, 0.1)',
buttonBackgroundColor: '#ccddf9',
buttonTextColor: '#0c2550',
buttonAlternativeTextColor: '#2f5fb3',
buttonDisabledBackgroundColor: '#eef0f4',
buttonDisabledTextColor: '#9aa0aa',
inputBorderColor: '#d2d2d2',
inputBackgroundColor: '#f5f5f5',
alternativeTextColor: '#9aa0aa',
alternativeTextColor2: '#0f5cc0',
buttonBlueBackgroundColor: '#ccddf9',
incomingBackgroundColor: '#d2f8d6',
incomingForegroundColor: '#37c0a1',
outgoingBackgroundColor: '#f8d2d2',
outgoingForegroundColor: '#d0021b',
successColor: '#37c0a1',
failedColor: '#ff0000',
shadowColor: '#000000',
inverseForegroundColor: '#ffffff',
hdborderColor: '#68BBE1',
hdbackgroundColor: '#ECF9FF',
lnborderColor: '#F7C056',
lnbackgroundColor: '#FFFAEF',
background: '#FFFFFF',
customHeader: 'rgba(0,0,0,0)',
lightButton: '#eef0f4',
ballReceive: '#d2f8d6',
ballOutgoing: '#f8d2d2',
lightBorder: '#ededed',
ballOutgoingExpired: '#EEF0F4',
modal: '#ffffff',
formBorder: '#d2d2d2',
modalButton: '#ccddf9',
darkGray: '#9AA0AA',
scanLabel: '#9AA0AA',
feeText: '#81868e',
feeLabel: '#d2f8d6',
feeValue: '#37c0a1',
labelText: '#81868e',
cta2: '#062453',
outputValue: '#13244D',
elevated: '#ffffff',
mainColor: '#CFDCF6',
success: '#ccddf9',
successCheck: '#0f5cc0',
},
};
export const BlueDarkTheme = {
...DarkTheme,
closeImage: require('../img/close-white.png'),
scanImage: require('../img/scan-white.png'),
colors: {
...BlueDefaultTheme.colors,
...DarkTheme.colors,
brandingColor: '#000000',
borderTopColor: '#9aa0aa',
foregroundColor: '#ffffff',
buttonDisabledBackgroundColor: '#3A3A3C',
buttonBackgroundColor: '#3A3A3C',
customHeader: '#000000',
buttonTextColor: '#ffffff',
lightButton: 'rgba(255,255,255,.1)',
buttonAlternativeTextColor: '#ffffff',
alternativeTextColor: '#9aa0aa',
alternativeTextColor2: '#0A84FF',
ballReceive: '#202020',
ballOutgoing: '#202020',
lightBorder: '#313030',
ballOutgoingExpired: '#202020',
modal: '#202020',
formBorder: '#202020',
inputBackgroundColor: '#262626',
modalButton: '#000000',
darkGray: '#3A3A3C',
feeText: '#81868e',
feeLabel: '#8EFFE5',
feeValue: '#000000',
cta2: '#ffffff',
outputValue: '#ffffff',
elevated: '#121212',
mainColor: '#0A84FF',
success: '#202020',
successCheck: '#0A84FF',
buttonBlueBackgroundColor: '#202020',
scanLabel: 'rgba(255,255,255,.2)',
labelText: '#ffffff',
},
};
export class BlueCurrentTheme {}
BlueCurrentTheme.colors = Appearance.getColorScheme() === 'dark' ? BlueDarkTheme.colors : BlueDefaultTheme.colors;
BlueCurrentTheme.closeImage = Appearance.getColorScheme() === 'dark' ? BlueDarkTheme.closeImage : BlueDefaultTheme.closeImage;
BlueCurrentTheme.scanImage = Appearance.getColorScheme() === 'dark' ? BlueDarkTheme.scanImage : BlueDefaultTheme.scanImage;

BIN
img/scan-white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

BIN
img/scan-white@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 B

BIN
img/scan-white@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

View file

@ -60,14 +60,14 @@
] ]
}, },
"dependencies": { "dependencies": {
"@babel/preset-env": "7.10.2", "@babel/preset-env": "7.10.3",
"@react-native-community/async-storage": "1.11.0", "@react-native-community/async-storage": "1.11.0",
"@react-native-community/blur": "3.6.0", "@react-native-community/blur": "3.6.0",
"@react-native-community/clipboard": "1.2.2", "@react-native-community/clipboard": "1.2.2",
"@react-native-community/masked-view": "0.1.10", "@react-native-community/masked-view": "0.1.10",
"@react-native-community/slider": "3.0.0", "@react-native-community/slider": "3.0.0",
"@react-navigation/native": "5.5.1", "@react-navigation/native": "5.6.1",
"@react-navigation/stack": "5.5.1", "@react-navigation/stack": "5.6.2",
"@remobile/react-native-qrcode-local-image": "git+https://github.com/BlueWallet/react-native-qrcode-local-image.git", "@remobile/react-native-qrcode-local-image": "git+https://github.com/BlueWallet/react-native-qrcode-local-image.git",
"@sentry/react-native": "1.4.5", "@sentry/react-native": "1.4.5",
"amplitude-js": "5.11.0", "amplitude-js": "5.11.0",

View file

@ -287,12 +287,6 @@ const styles = StyleSheet.create({
}); });
export default class Browser extends Component { export default class Browser extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: 'Lapp Browser',
headerLeft: null,
});
constructor(props) { constructor(props) {
super(props); super(props);
if (!props.route.params.fromSecret) throw new Error('Invalid param'); if (!props.route.params.fromSecret) throw new Error('Invalid param');
@ -435,7 +429,7 @@ export default class Browser extends Component {
return ( return (
<SafeBlueArea> <SafeBlueArea>
<View style={styles.safeRoot}> <View style={styles.safeRoot}>
<StatusBar barStyle="light-content" /> <StatusBar barStyle="default" />
<TouchableOpacity <TouchableOpacity
disabled={!this.state.canGoBack} disabled={!this.state.canGoBack}
onPress={() => { onPress={() => {
@ -516,3 +510,9 @@ Browser.propTypes = {
params: PropTypes.object, params: PropTypes.object,
}), }),
}; };
Browser.navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: 'Lapp Browser',
headerLeft: null,
});

View file

@ -11,6 +11,7 @@ import {
TouchableOpacity, TouchableOpacity,
Text, Text,
StyleSheet, StyleSheet,
Image,
} from 'react-native'; } from 'react-native';
import { import {
BlueNavigationStyle, BlueNavigationStyle,
@ -26,6 +27,7 @@ import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
import * as NavigationService from '../../NavigationService'; import * as NavigationService from '../../NavigationService';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import { BlueCurrentTheme } from '../../components/themes';
const currency = require('../../blue_modules/currency'); const currency = require('../../blue_modules/currency');
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
const EV = require('../../blue_modules/events'); const EV = require('../../blue_modules/events');
@ -37,14 +39,13 @@ const styles = StyleSheet.create({
marginVertical: 16, marginVertical: 16,
minHeight: 45, minHeight: 45,
alignContent: 'center', alignContent: 'center',
backgroundColor: '#FFFFFF',
}, },
scanRoot: { scanRoot: {
height: 36, height: 36,
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
justifyContent: 'space-between', justifyContent: 'space-between',
backgroundColor: '#9AA0AA', backgroundColor: BlueCurrentTheme.colors.scanLabel,
borderRadius: 4, borderRadius: 4,
paddingVertical: 4, paddingVertical: 4,
paddingHorizontal: 8, paddingHorizontal: 8,
@ -52,7 +53,7 @@ const styles = StyleSheet.create({
}, },
scanClick: { scanClick: {
marginLeft: 4, marginLeft: 4,
color: BlueApp.settings.inverseForegroundColor, color: BlueCurrentTheme.colors.inverseForegroundColor,
}, },
walletRoot: { walletRoot: {
marginBottom: 16, marginBottom: 16,
@ -78,18 +79,18 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
}, },
walletNameText: { walletNameText: {
color: '#0c2550', color: BlueCurrentTheme.colors.buttonAlternativeTextColor,
fontSize: 14, fontSize: 14,
}, },
walletNameBalance: { walletNameBalance: {
color: '#0c2550', color: BlueCurrentTheme.colors.buttonAlternativeTextColor,
fontSize: 14, fontSize: 14,
fontWeight: '600', fontWeight: '600',
marginLeft: 8, marginLeft: 8,
marginRight: 4, marginRight: 4,
}, },
walletNameSats: { walletNameSats: {
color: '#0c2550', color: BlueCurrentTheme.colors.buttonAlternativeTextColor,
fontSize: 11, fontSize: 11,
fontWeight: '600', fontWeight: '600',
textAlignVertical: 'bottom', textAlignVertical: 'bottom',
@ -102,19 +103,19 @@ const styles = StyleSheet.create({
root: { root: {
flex: 1, flex: 1,
justifyContent: 'space-between', justifyContent: 'space-between',
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
amount: { amount: {
flex: 1, flex: 1,
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
fiat: { fiat: {
flexDirection: 'row', flexDirection: 'row',
borderColor: '#d2d2d2', borderColor: BlueCurrentTheme.colors.formBorder,
borderBottomColor: '#d2d2d2', borderBottomColor: BlueCurrentTheme.colors.formBorder,
borderWidth: 1.0, borderWidth: 1.0,
borderBottomWidth: 0.5, borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
minHeight: 44, minHeight: 44,
height: 44, height: 44,
marginHorizontal: 20, marginHorizontal: 20,
@ -131,11 +132,6 @@ const styles = StyleSheet.create({
}); });
export default class LNDCreateInvoice extends Component { export default class LNDCreateInvoice extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: loc.receive.header,
});
constructor(props) { constructor(props) {
super(props); super(props);
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow); this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow);
@ -356,7 +352,7 @@ export default class LNDCreateInvoice extends Component {
}} }}
style={styles.scanRoot} style={styles.scanRoot}
> >
<Icon name="qrcode" size={22} type="font-awesome" color={BlueApp.settings.inverseForegroundColor} /> <Image style={{}} source={require('../../img/scan-white.png')} />
<Text style={styles.scanClick}>{loc.send.details.scan}</Text> <Text style={styles.scanClick}>{loc.send.details.scan}</Text>
</TouchableOpacity> </TouchableOpacity>
); );
@ -478,3 +474,8 @@ LNDCreateInvoice.propTypes = {
}), }),
}), }),
}; };
LNDCreateInvoice.navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
headerTitle: loc.receive.header,
headerLeft: null,
});

View file

@ -13,7 +13,7 @@ import {
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import QRCode from 'react-native-qrcode-svg'; import QRCode from 'react-native-qrcode-svg';
/** @type {AppStorage} */ /** @type {AppStorage} */
const BlueApp = require('../../BlueApp'); import { BlueCurrentTheme } from '../../components/themes';
const loc = require('../../loc'); const loc = require('../../loc');
const styles = StyleSheet.create({ const styles = StyleSheet.create({
@ -21,9 +21,11 @@ const styles = StyleSheet.create({
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
root: { root: {
flex: 1, flex: 1,
backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
wrapper: { wrapper: {
flex: 1, flex: 1,
@ -42,11 +44,6 @@ const styles = StyleSheet.create({
}); });
export default class LNDViewAdditionalInvoiceInformation extends Component { export default class LNDViewAdditionalInvoiceInformation extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(),
title: 'Additional Information',
});
state = { walletInfo: undefined }; state = { walletInfo: undefined };
async componentDidMount() { async componentDidMount() {
@ -78,8 +75,9 @@ export default class LNDViewAdditionalInvoiceInformation extends Component {
logo={require('../../img/qr-code.png')} logo={require('../../img/qr-code.png')}
size={300} size={300}
logoSize={90} logoSize={90}
color={BlueApp.settings.foregroundColor} color={BlueCurrentTheme.colors.foregroundColor}
logoBackgroundColor={BlueApp.settings.brandingColor} logoBackgroundColor={BlueCurrentTheme.colors.brandingColor}
backgroundColor={BlueCurrentTheme.colors.background}
/> />
<BlueSpacing20 /> <BlueSpacing20 />
<BlueText>{loc.lndViewInvoice.open_direct_channel}</BlueText> <BlueText>{loc.lndViewInvoice.open_direct_channel}</BlueText>
@ -90,7 +88,7 @@ export default class LNDViewAdditionalInvoiceInformation extends Component {
icon={{ icon={{
name: 'share-alternative', name: 'share-alternative',
type: 'entypo', type: 'entypo',
color: BlueApp.settings.buttonTextColor, color: BlueCurrentTheme.colors.buttonTextColor,
}} }}
onPress={async () => { onPress={async () => {
Share.share({ Share.share({
@ -111,3 +109,8 @@ LNDViewAdditionalInvoiceInformation.propTypes = {
params: PropTypes.object, params: PropTypes.object,
}), }),
}; };
LNDViewAdditionalInvoiceInformation.navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(),
title: 'Additional Information',
});

View file

@ -1,11 +1,12 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { View, Text, Dimensions, ScrollView, BackHandler, TouchableOpacity, StyleSheet } from 'react-native'; import { View, Text, Dimensions, StatusBar, ScrollView, BackHandler, TouchableOpacity, StyleSheet } from 'react-native';
import Share from 'react-native-share'; import Share from 'react-native-share';
import { import {
BlueLoading, BlueLoading,
BlueText, BlueText,
SafeBlueArea, SafeBlueArea,
BlueButton, BlueButton,
SecondButton,
BlueCopyTextToClipboard, BlueCopyTextToClipboard,
BlueNavigationStyle, BlueNavigationStyle,
BlueSpacing20, BlueSpacing20,
@ -16,7 +17,7 @@ import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import QRCode from 'react-native-qrcode-svg'; import QRCode from 'react-native-qrcode-svg';
/** @type {AppStorage} */ /** @type {AppStorage} */
const BlueApp = require('../../BlueApp'); import { BlueCurrentTheme } from '../../components/themes';
const loc = require('../../loc'); const loc = require('../../loc');
const EV = require('../../blue_modules/events'); const EV = require('../../blue_modules/events');
const { width, height } = Dimensions.get('window'); const { width, height } = Dimensions.get('window');
@ -41,12 +42,12 @@ const styles = StyleSheet.create({
paddingBottom: 8, paddingBottom: 8,
}, },
valueText: { valueText: {
color: '#0f5cc0', color: BlueCurrentTheme.colors.alternativeTextColor2,
fontSize: 32, fontSize: 32,
fontWeight: '600', fontWeight: '600',
}, },
valueSats: { valueSats: {
color: '#0f5cc0', color: BlueCurrentTheme.colors.alternativeTextColor2,
fontSize: 16, fontSize: 16,
marginHorizontal: 4, marginHorizontal: 4,
paddingBottom: 3, paddingBottom: 3,
@ -69,6 +70,7 @@ const styles = StyleSheet.create({
paidMark: { paidMark: {
marginTop: -100, marginTop: -100,
marginBottom: 16, marginBottom: 16,
backgroundColor: BlueCurrentTheme.colors.success,
}, },
detailsRoot: { detailsRoot: {
flex: 1, flex: 1,
@ -81,12 +83,12 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
}, },
detailsText: { detailsText: {
color: '#9aa0aa', color: BlueCurrentTheme.colors.alternativeTextColor,
fontSize: 14, fontSize: 14,
marginRight: 8, marginRight: 8,
}, },
expired: { expired: {
backgroundColor: '#ccddf9', backgroundColor: BlueCurrentTheme.colors.success,
width: 120, width: 120,
height: 120, height: 120,
borderRadius: 60, borderRadius: 60,
@ -108,20 +110,11 @@ const styles = StyleSheet.create({
paddingHorizontal: 16, paddingHorizontal: 16,
}, },
additionalInfo: { additionalInfo: {
backgroundColor: BlueApp.settings.brandingColor, backgroundColor: BlueCurrentTheme.colors.brandingColor,
}, },
}); });
export default class LNDViewInvoice extends Component { export default class LNDViewInvoice extends Component {
static navigationOptions = ({ navigation, route }) =>
route.params.isModal === true
? {
...BlueNavigationStyle(navigation, true, () => navigation.dangerouslyGetParent().pop()),
title: 'Lightning Invoice',
headerLeft: null,
}
: { ...BlueNavigationStyle(), title: 'Lightning Invoice' };
constructor(props) { constructor(props) {
super(props); super(props);
const invoice = props.route.params.invoice; const invoice = props.route.params.invoice;
@ -212,6 +205,7 @@ export default class LNDViewInvoice extends Component {
if (this.state.showPreimageQr) { if (this.state.showPreimageQr) {
return ( return (
<SafeBlueArea style={styles.root}> <SafeBlueArea style={styles.root}>
<StatusBar barStyle="default" />
<View style={styles.center}> <View style={styles.center}>
<BlueText>Preimage:</BlueText> <BlueText>Preimage:</BlueText>
<BlueSpacing20 /> <BlueSpacing20 />
@ -220,8 +214,9 @@ export default class LNDViewInvoice extends Component {
logo={require('../../img/qr-code.png')} logo={require('../../img/qr-code.png')}
size={this.state.qrCodeHeight} size={this.state.qrCodeHeight}
logoSize={90} logoSize={90}
color={BlueApp.settings.foregroundColor} color={BlueCurrentTheme.colors.foregroundColor}
logoBackgroundColor={BlueApp.settings.brandingColor} backgroundColor={BlueCurrentTheme.colors.background}
logoBackgroundColor={BlueCurrentTheme.colors.brandingColor}
/> />
<BlueSpacing20 /> <BlueSpacing20 />
<BlueCopyTextToClipboard <BlueCopyTextToClipboard
@ -235,6 +230,7 @@ export default class LNDViewInvoice extends Component {
if (invoice.ispaid || invoice.type === 'paid_invoice') { if (invoice.ispaid || invoice.type === 'paid_invoice') {
return ( return (
<SafeBlueArea style={styles.root}> <SafeBlueArea style={styles.root}>
<StatusBar barStyle="default" />
<View style={styles.valueRoot}> <View style={styles.valueRoot}>
{invoice.type === 'paid_invoice' && invoice.value && ( {invoice.type === 'paid_invoice' && invoice.value && (
<View style={styles.valueAmount}> <View style={styles.valueAmount}>
@ -259,7 +255,7 @@ export default class LNDViewInvoice extends Component {
{invoice.payment_preimage && typeof invoice.payment_preimage === 'string' ? ( {invoice.payment_preimage && typeof invoice.payment_preimage === 'string' ? (
<TouchableOpacity style={styles.detailsTouch} onPress={() => this.setState({ showPreimageQr: true })}> <TouchableOpacity style={styles.detailsTouch} onPress={() => this.setState({ showPreimageQr: true })}>
<Text style={styles.detailsText}>{loc.send.create.details}</Text> <Text style={styles.detailsText}>{loc.send.create.details}</Text>
<Icon name="angle-right" size={18} type="font-awesome" color="#9aa0aa" /> <Icon name="angle-right" size={18} type="font-awesome" color={BlueCurrentTheme.colors.alternativeTextColor} />
</TouchableOpacity> </TouchableOpacity>
) : ( ) : (
<View /> <View />
@ -271,9 +267,10 @@ export default class LNDViewInvoice extends Component {
if (invoiceExpiration < now && !invoice.ispaid) { if (invoiceExpiration < now && !invoice.ispaid) {
return ( return (
<SafeBlueArea style={styles.root}> <SafeBlueArea style={styles.root}>
<StatusBar barStyle="default" />
<View style={styles.center}> <View style={styles.center}>
<View style={styles.expired}> <View style={styles.expired}>
<Icon name="times" size={50} type="font-awesome" color="#0f5cc0" /> <Icon name="times" size={50} type="font-awesome" color={BlueCurrentTheme.colors.successCheck} />
</View> </View>
<BlueText>{loc.lndViewInvoice.wasnt_paid_and_expired}</BlueText> <BlueText>{loc.lndViewInvoice.wasnt_paid_and_expired}</BlueText>
</View> </View>
@ -294,6 +291,7 @@ export default class LNDViewInvoice extends Component {
// Invoice has not expired, nor has it been paid for. // Invoice has not expired, nor has it been paid for.
return ( return (
<SafeBlueArea> <SafeBlueArea>
<StatusBar barStyle="default" />
<ScrollView> <ScrollView>
<View style={styles.activeRoot} onLayout={this.onLayout}> <View style={styles.activeRoot} onLayout={this.onLayout}>
<View style={styles.activeQrcode}> <View style={styles.activeQrcode}>
@ -302,8 +300,9 @@ export default class LNDViewInvoice extends Component {
logo={require('../../img/qr-code.png')} logo={require('../../img/qr-code.png')}
size={this.state.qrCodeHeight} size={this.state.qrCodeHeight}
logoSize={90} logoSize={90}
color={BlueApp.settings.foregroundColor} color={BlueCurrentTheme.colors.foregroundColor}
logoBackgroundColor={BlueApp.settings.brandingColor} logoBackgroundColor={BlueCurrentTheme.colors.brandingColor}
backgroundColor={BlueCurrentTheme.colors.background}
/> />
</View> </View>
@ -318,15 +317,9 @@ export default class LNDViewInvoice extends Component {
)} )}
<BlueCopyTextToClipboard text={this.state.invoice.payment_request} /> <BlueCopyTextToClipboard text={this.state.invoice.payment_request} />
<BlueButton <SecondButton
icon={{
name: 'share-alternative',
type: 'entypo',
size: 10,
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => { onPress={() => {
Share.open({ message: `lightning://${invoice.payment_request}` }).catch(error => console.log(error)); Share.open({ message: `lightning:${invoice.payment_request}` }).catch(error => console.log(error));
}} }}
title={loc.receive.details.share} title={loc.receive.details.share}
/> />
@ -354,3 +347,21 @@ LNDViewInvoice.propTypes = {
params: PropTypes.object, params: PropTypes.object,
}), }),
}; };
LNDViewInvoice.navigationOptions = ({ navigation, route }) =>
route.params.isModal === true
? {
...BlueNavigationStyle(navigation, true, () => navigation.dangerouslyGetParent().pop()),
title: 'Lightning Invoice',
headerLeft: null,
headerStyle: {
backgroundColor: BlueCurrentTheme.colors.customHeader,
},
}
: {
...BlueNavigationStyle(),
title: 'Lightning Invoice',
headerStyle: {
backgroundColor: BlueCurrentTheme.colors.customHeader,
},
};

View file

@ -27,6 +27,7 @@ import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import Biometric from '../../class/biometrics'; import Biometric from '../../class/biometrics';
import { BlueCurrentTheme } from '../../components/themes';
/** @type {AppStorage} */ /** @type {AppStorage} */
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
const EV = require('../../blue_modules/events'); const EV = require('../../blue_modules/events');
@ -58,18 +59,18 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
}, },
walletWrapLabel: { walletWrapLabel: {
color: '#0c2550', color: BlueCurrentTheme.colors.buttonAlternativeTextColor,
fontSize: 14, fontSize: 14,
}, },
walletWrapBalance: { walletWrapBalance: {
color: '#0c2550', color: BlueCurrentTheme.colors.buttonAlternativeTextColor,
fontSize: 14, fontSize: 14,
fontWeight: '600', fontWeight: '600',
marginLeft: 4, marginLeft: 4,
marginRight: 4, marginRight: 4,
}, },
walletWrapSats: { walletWrapSats: {
color: '#0c2550', color: BlueCurrentTheme.colors.buttonAlternativeTextColor,
fontSize: 11, fontSize: 11,
fontWeight: '600', fontWeight: '600',
textAlignVertical: 'bottom', textAlignVertical: 'bottom',
@ -77,6 +78,7 @@ const styles = StyleSheet.create({
}, },
root: { root: {
flex: 1, flex: 1,
backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
scroll: { scroll: {
flex: 1, flex: 1,
@ -106,12 +108,6 @@ const styles = StyleSheet.create({
}); });
export default class ScanLndInvoice extends React.Component { export default class ScanLndInvoice extends React.Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: loc.send.header,
headerLeft: null,
});
state = { state = {
isLoading: false, isLoading: false,
isAmountInitiallyEmpty: false, isAmountInitiallyEmpty: false,
@ -465,3 +461,9 @@ ScanLndInvoice.propTypes = {
}), }),
}), }),
}; };
ScanLndInvoice.navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: loc.send.header,
headerLeft: null,
});

View file

@ -17,10 +17,6 @@ const styles = StyleSheet.create({
}); });
export default class PlausibleDeniability extends Component { export default class PlausibleDeniability extends Component {
static navigationOptions = {
...BlueNavigationStyle(),
title: loc.plausibledeniability.title,
};
constructor(props) { constructor(props) {
super(props); super(props);
@ -92,3 +88,8 @@ PlausibleDeniability.propTypes = {
popToTop: PropTypes.func, popToTop: PropTypes.func,
}), }),
}; };
PlausibleDeniability.navigationOptions = ({ navigation, route }) => ({
...BlueNavigationStyle(),
title: loc.plausibledeniability.title,
});

View file

@ -51,11 +51,6 @@ const styles = StyleSheet.create({
}); });
export default class AztecoRedeem extends Component { export default class AztecoRedeem extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueCreateTxNavigationStyle(navigation),
title: 'Redeem Azte.co voucher',
});
state = { isLoading: true }; state = { isLoading: true };
constructor(props) { constructor(props) {
@ -156,7 +151,7 @@ export default class AztecoRedeem extends Component {
return ( return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}> <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View> <View>
<StatusBar barStyle="light-content" /> <StatusBar barStyle="default" />
<View style={styles.root}> <View style={styles.root}>
<Text>Your voucher code is</Text> <Text>Your voucher code is</Text>
<BlueText style={styles.code}> <BlueText style={styles.code}>
@ -187,3 +182,8 @@ AztecoRedeem.propTypes = {
}), }),
}), }),
}; };
AztecoRedeem.navigationOptions = ({ navigation }) => ({
...BlueCreateTxNavigationStyle(navigation),
title: 'Redeem Azte.co voucher',
});

View file

@ -11,19 +11,19 @@ import {
ScrollView, ScrollView,
} from 'react-native'; } from 'react-native';
import QRCode from 'react-native-qrcode-svg'; import QRCode from 'react-native-qrcode-svg';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
import { import {
BlueLoading, BlueLoadingHook,
SafeBlueArea,
BlueCopyTextToClipboard, BlueCopyTextToClipboard,
BlueButton, BlueButton,
BlueButtonLink, SecondButton,
BlueNavigationStyle, BlueButtonLinkHook,
is, is,
BlueBitcoinAmount, BlueBitcoinAmount,
BlueText, BlueText,
BlueSpacing20, BlueSpacing20,
BlueAlertWalletExportReminder, BlueAlertWalletExportReminder,
BlueNavigationStyle,
} from '../../BlueComponents'; } from '../../BlueComponents';
import Privacy from '../../Privacy'; import Privacy from '../../Privacy';
import Share from 'react-native-share'; import Share from 'react-native-share';
@ -32,6 +32,7 @@ import Modal from 'react-native-modal';
import HandoffSettings from '../../class/handoff'; import HandoffSettings from '../../class/handoff';
import DeeplinkSchemaMatch from '../../class/deeplink-schema-match'; import DeeplinkSchemaMatch from '../../class/deeplink-schema-match';
import Handoff from 'react-native-handoff'; import Handoff from 'react-native-handoff';
import { BlueCurrentTheme } from '../../components/themes';
/** @type {AppStorage} */ /** @type {AppStorage} */
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
const loc = require('../../loc'); const loc = require('../../loc');
@ -49,6 +50,89 @@ const ReceiveDetails = () => {
const [isCustom, setIsCustom] = useState(false); const [isCustom, setIsCustom] = useState(false);
const [isCustomModalVisible, setIsCustomModalVisible] = useState(false); const [isCustomModalVisible, setIsCustomModalVisible] = useState(false);
const { navigate, goBack } = useNavigation(); const { navigate, goBack } = useNavigation();
const { colors } = useTheme();
const styles = StyleSheet.create({
modalContent: {
backgroundColor: BlueCurrentTheme.colors.modal,
padding: 22,
justifyContent: 'center',
alignItems: 'center',
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
borderTopColor: colors.foregroundColor,
borderWidth: colors.borderWidth,
minHeight: 350,
height: 350,
},
bottomModal: {
justifyContent: 'flex-end',
margin: 0,
},
customAmount: {
flexDirection: 'row',
borderColor: BlueCurrentTheme.colors.formBorder,
borderBottomColor: BlueCurrentTheme.colors.formBorder,
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
},
customAmountText: {
flex: 1,
marginHorizontal: 8,
color: BlueCurrentTheme.colors.foregroundColor,
minHeight: 33,
},
root: {
flex: 1,
backgroundColor: BlueCurrentTheme.colors.elevated,
},
scroll: {
justifyContent: 'space-between',
},
scrollBody: {
marginTop: 32,
alignItems: 'center',
paddingHorizontal: 16,
},
amount: {
color: BlueCurrentTheme.colors.foregroundColor,
fontWeight: '600',
fontSize: 36,
textAlign: 'center',
paddingBottom: 24,
},
label: {
color: BlueCurrentTheme.colors.foregroundColor,
fontWeight: '600',
textAlign: 'center',
paddingBottom: 24,
},
loading: {
alignItems: 'center',
width: 300,
height: 300,
backgroundColor: BlueCurrentTheme.colors.elevated,
},
share: {
alignItems: 'center',
alignContent: 'flex-end',
marginBottom: 24,
},
modalButton: {
backgroundColor: BlueCurrentTheme.colors.modalButton,
paddingVertical: 14,
paddingHorizontal: 70,
maxWidth: '80%',
borderRadius: 50,
fontWeight: '700',
},
});
const renderReceiveDetails = useCallback(async () => { const renderReceiveDetails = useCallback(async () => {
console.log('receive/details - componentDidMount'); console.log('receive/details - componentDidMount');
@ -144,14 +228,6 @@ const ReceiveDetails = () => {
setBip21encoded(DeeplinkSchemaMatch.bip21encode(address, { amount, label: customLabel })); setBip21encoded(DeeplinkSchemaMatch.bip21encode(address, { amount, label: customLabel }));
}; };
const clearCustomAmount = () => {
setIsCustom(false);
setIsCustomModalVisible(false);
setCustomAmount('');
setCustomLabel('');
setBip21encoded(DeeplinkSchemaMatch.bip21encode(address));
};
const renderCustomAmountModal = () => { const renderCustomAmountModal = () => {
return ( return (
<Modal isVisible={isCustomModalVisible} style={styles.bottomModal} onBackdropPress={dismissCustomAmountModal}> <Modal isVisible={isCustomModalVisible} style={styles.bottomModal} onBackdropPress={dismissCustomAmountModal}>
@ -175,9 +251,8 @@ const ReceiveDetails = () => {
</View> </View>
<BlueSpacing20 /> <BlueSpacing20 />
<View> <View>
<BlueButton title={loc.receive.details.create} onPress={createCustomAmountAddress} /> <BlueButton style={styles.modalButton} title={loc.receive.details.create} onPress={createCustomAmountAddress} />
<BlueSpacing20 /> <BlueSpacing20 />
<BlueButtonLink title="Reset" onPress={clearCustomAmount} />
</View> </View>
<BlueSpacing20 /> <BlueSpacing20 />
</View> </View>
@ -206,7 +281,7 @@ const ReceiveDetails = () => {
}; };
return ( return (
<SafeBlueArea style={styles.root}> <View style={styles.root}>
<StatusBar barStyle="light-content" /> <StatusBar barStyle="light-content" />
{isHandOffUseEnabled && address !== undefined && ( {isHandOffUseEnabled && address !== undefined && (
<Handoff <Handoff
@ -215,7 +290,7 @@ const ReceiveDetails = () => {
url={`https://blockstream.info/address/${address}`} url={`https://blockstream.info/address/${address}`}
/> />
)} )}
<ScrollView contentContainerStyle={styles.scroll} keyboardShouldPersistTaps="always"> <ScrollView style={styles.root} contentContainerStyle={styles.scroll} keyboardShouldPersistTaps="always">
<View style={styles.scrollBody}> <View style={styles.scrollBody}>
{isCustom && ( {isCustom && (
<> <>
@ -229,7 +304,7 @@ const ReceiveDetails = () => {
)} )}
{bip21encoded === undefined ? ( {bip21encoded === undefined ? (
<View style={styles.loading}> <View style={styles.loading}>
<BlueLoading /> <BlueLoadingHook />
</View> </View>
) : ( ) : (
<QRCode <QRCode
@ -237,30 +312,23 @@ const ReceiveDetails = () => {
logo={require('../../img/qr-code.png')} logo={require('../../img/qr-code.png')}
size={(is.ipad() && 300) || 300} size={(is.ipad() && 300) || 300}
logoSize={90} logoSize={90}
color={BlueApp.settings.foregroundColor} color={colors.foregroundColor}
logoBackgroundColor={BlueApp.settings.brandingColor} logoBackgroundColor={colors.brandingColor}
backgroundColor={colors.background}
ecl="H" ecl="H"
/> />
)} )}
<BlueCopyTextToClipboard text={isCustom ? bip21encoded : address} /> <BlueCopyTextToClipboard text={isCustom ? bip21encoded : address} />
</View> </View>
<View style={styles.share}> <View style={styles.share}>
<BlueButtonLink title={loc.receive.details.setAmount} onPress={showCustomAmountModal} /> <BlueButtonLinkHook title={loc.receive.details.setAmount} onPress={showCustomAmountModal} />
<View> <View>
<BlueButton <SecondButton onPress={handleShareButtonPressed} title={loc.receive.details.share} />
icon={{
name: 'share-alternative',
type: 'entypo',
color: BlueApp.settings.buttonTextColor,
}}
onPress={handleShareButtonPressed}
title={loc.receive.details.share}
/>
</View> </View>
</View> </View>
{renderCustomAmountModal()}
</ScrollView> </ScrollView>
</SafeBlueArea> {renderCustomAmountModal()}
</View>
); );
}; };
@ -271,75 +339,3 @@ ReceiveDetails.navigationOptions = ({ navigation }) => ({
}); });
export default ReceiveDetails; export default ReceiveDetails;
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: 350,
height: 350,
},
bottomModal: {
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,
color: '#81868e',
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,8 +1,9 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { ScrollView, View, StyleSheet } from 'react-native'; import { ScrollView, View, StyleSheet } from 'react-native';
import { BlueLoading, BlueSpacing20, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../BlueComponents'; import { BlueSpacing20, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle, BlueLoadingHook } from '../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { SegwitP2SHWallet, LegacyWallet, HDSegwitP2SHWallet, HDSegwitBech32Wallet } from '../class'; import { SegwitP2SHWallet, LegacyWallet, HDSegwitP2SHWallet, HDSegwitBech32Wallet } from '../class';
import { BlueCurrentTheme } from '../components/themes';
const bitcoin = require('bitcoinjs-lib'); const bitcoin = require('bitcoinjs-lib');
const BlueCrypto = require('react-native-blue-crypto'); const BlueCrypto = require('react-native-blue-crypto');
const encryption = require('../blue_modules/encryption'); const encryption = require('../blue_modules/encryption');
@ -11,6 +12,7 @@ const BlueElectrum = require('../blue_modules/BlueElectrum');
const styles = StyleSheet.create({ const styles = StyleSheet.create({
root: { root: {
flex: 1, flex: 1,
backgroundColor: BlueCurrentTheme.colors.background,
}, },
center: { center: {
alignItems: 'center', alignItems: 'center',
@ -18,11 +20,6 @@ const styles = StyleSheet.create({
}); });
export default class Selftest extends Component { export default class Selftest extends Component {
static navigationOptions = () => ({
...BlueNavigationStyle(),
title: 'Self test',
});
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -213,7 +210,7 @@ export default class Selftest extends Component {
render() { render() {
if (this.state.isLoading) { if (this.state.isLoading) {
return <BlueLoading />; return <BlueLoadingHook />;
} }
return ( return (
@ -261,3 +258,8 @@ Selftest.propTypes = {
goBack: PropTypes.func, goBack: PropTypes.func,
}), }),
}; };
Selftest.navigationOptions = () => ({
...BlueNavigationStyle(),
title: 'Self test',
});

View file

@ -12,7 +12,9 @@ import {
BlueFormLabel, BlueFormLabel,
BlueTextCentered, BlueTextCentered,
BlueBigCheckmark, BlueBigCheckmark,
BlueNavigationStyle,
} from '../../BlueComponents'; } from '../../BlueComponents';
import { BlueCurrentTheme } from '../../components/themes';
import BlueElectrum from '../../blue_modules/BlueElectrum'; import BlueElectrum from '../../blue_modules/BlueElectrum';
const bitcoin = require('bitcoinjs-lib'); const bitcoin = require('bitcoinjs-lib');
@ -23,7 +25,7 @@ const BROADCAST_RESULT = Object.freeze({
error: 'error', error: 'error',
}); });
export default function Broadcast() { const Broadcast = () => {
const [tx, setTx] = useState(''); const [tx, setTx] = useState('');
const [txHex, setTxHex] = useState(''); const [txHex, setTxHex] = useState('');
const [broadcastResult, setBroadcastResult] = useState(BROADCAST_RESULT.none); const [broadcastResult, setBroadcastResult] = useState(BROADCAST_RESULT.none);
@ -72,7 +74,7 @@ export default function Broadcast() {
/> />
<BlueSpacing10 /> <BlueSpacing10 />
<BlueButton title="BROADCAST" onPress={handleBroadcast} disabled={broadcastResult === BROADCAST_RESULT.pending} /> <BlueButton title="Send" onPress={handleBroadcast} disabled={broadcastResult === BROADCAST_RESULT.pending} />
</BlueCard> </BlueCard>
)} )}
{BROADCAST_RESULT.success === broadcastResult && <SuccessScreen tx={tx} />} {BROADCAST_RESULT.success === broadcastResult && <SuccessScreen tx={tx} />}
@ -80,7 +82,13 @@ export default function Broadcast() {
</KeyboardAvoidingView> </KeyboardAvoidingView>
</SafeBlueArea> </SafeBlueArea>
); );
} };
export default Broadcast;
Broadcast.navigationOptions = () => ({
...BlueNavigationStyle(),
title: 'Broadcast',
});
const styles = StyleSheet.create({ const styles = StyleSheet.create({
wrapper: { wrapper: {
@ -101,7 +109,7 @@ const styles = StyleSheet.create({
width: '100%', width: '100%',
}, },
link: { link: {
color: 'blue', color: BlueCurrentTheme.colors.foregroundColor,
}, },
mainCard: { mainCard: {
padding: 0, padding: 0,
@ -128,7 +136,7 @@ const styles = StyleSheet.create({
backgroundColor: '#d2f8d6', backgroundColor: '#d2f8d6',
borderRadius: 4, borderRadius: 4,
marginTop: 20, marginTop: 20,
color: '#37c0a1', color: BlueCurrentTheme.colors.foregroundColor,
fontWeight: '500', fontWeight: '500',
fontSize: 14, fontSize: 14,
paddingHorizontal: 16, paddingHorizontal: 16,

View file

@ -17,20 +17,15 @@ import {
SegwitP2SHWallet, SegwitP2SHWallet,
SegwitBech32Wallet, SegwitBech32Wallet,
} from '../../class'; } from '../../class';
import { BlueCurrentTheme } from '../../components/themes';
const loc = require('../../loc'); const loc = require('../../loc');
const EV = require('../../blue_modules/events'); const EV = require('../../blue_modules/events');
const currency = require('../../blue_modules/currency'); const currency = require('../../blue_modules/currency');
const BlueElectrum = require('../../blue_modules/BlueElectrum'); const BlueElectrum = require('../../blue_modules/BlueElectrum');
const Bignumber = require('bignumber.js'); const Bignumber = require('bignumber.js');
/** @type {AppStorage} */ /** @type {AppStorage} */
const BlueApp = require('../../BlueApp');
export default class Confirm extends Component { export default class Confirm extends Component {
static navigationOptions = () => ({
...BlueNavigationStyle(null, false),
title: loc.send.confirm.header,
});
constructor(props) { constructor(props) {
super(props); super(props);
@ -207,19 +202,19 @@ export default class Confirm extends Component {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
transactionDetailsTitle: { transactionDetailsTitle: {
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
fontWeight: '500', fontWeight: '500',
fontSize: 17, fontSize: 17,
marginBottom: 2, marginBottom: 2,
}, },
transactionDetailsSubtitle: { transactionDetailsSubtitle: {
color: '#9aa0aa', color: BlueCurrentTheme.colors.feeText,
fontWeight: '500', fontWeight: '500',
fontSize: 15, fontSize: 15,
marginBottom: 20, marginBottom: 20,
}, },
transactionAmountFiat: { transactionAmountFiat: {
color: '#9aa0aa', color: BlueCurrentTheme.colors.feeText,
fontWeight: '500', fontWeight: '500',
fontSize: 15, fontSize: 15,
marginVertical: 20, marginVertical: 20,
@ -230,12 +225,12 @@ const styles = StyleSheet.create({
justifyContent: 'center', justifyContent: 'center',
}, },
valueValue: { valueValue: {
color: '#0f5cc0', color: BlueCurrentTheme.colors.alternativeTextColor2,
fontSize: 36, fontSize: 36,
fontWeight: '600', fontWeight: '600',
}, },
valueUnit: { valueUnit: {
color: '#0f5cc0', color: BlueCurrentTheme.colors.alternativeTextColor2,
fontSize: 16, fontSize: 16,
marginHorizontal: 4, marginHorizontal: 4,
paddingBottom: 6, paddingBottom: 6,
@ -248,19 +243,18 @@ const styles = StyleSheet.create({
marginVertical: 8, marginVertical: 8,
}, },
separator: { separator: {
backgroundColor: BlueApp.settings.inputBorderColor,
height: 0.5, height: 0.5,
margin: 16, margin: 16,
}, },
root: { root: {
flex: 1, flex: 1,
paddingTop: 19, paddingTop: 19,
backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
rootWrap: { rootWrap: {
marginTop: 16, marginTop: 16,
alignItems: 'center', alignItems: 'center',
justifyContent: 'space-between', justifyContent: 'space-between',
backgroundColor: '#FFFFFF',
}, },
flat: { flat: {
maxHeight: '55%', maxHeight: '55%',
@ -270,7 +264,6 @@ const styles = StyleSheet.create({
justifyContent: 'center', justifyContent: 'center',
paddingTop: 16, paddingTop: 16,
paddingBottom: 16, paddingBottom: 16,
backgroundColor: '#FFFFFF',
}, },
cardText: { cardText: {
color: '#37c0a1', color: '#37c0a1',
@ -284,7 +277,7 @@ const styles = StyleSheet.create({
marginVertical: 24, marginVertical: 24,
}, },
txText: { txText: {
color: '#0c2550', color: BlueCurrentTheme.colors.buttonTextColor,
fontSize: 15, fontSize: 15,
fontWeight: '500', fontWeight: '500',
alignSelf: 'center', alignSelf: 'center',
@ -301,3 +294,8 @@ Confirm.propTypes = {
params: PropTypes.object, params: PropTypes.object,
}), }),
}; };
Confirm.navigationOptions = () => ({
...BlueNavigationStyle(null, false),
title: loc.send.confirm.header,
});

View file

@ -22,31 +22,11 @@ import { BitcoinUnit } from '../../models/bitcoinUnits';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import Share from 'react-native-share'; import Share from 'react-native-share';
import RNFS from 'react-native-fs'; import RNFS from 'react-native-fs';
/** @type {AppStorage} */ import { BlueCurrentTheme } from '../../components/themes';
const BlueApp = require('../../BlueApp');
const loc = require('../../loc'); const loc = require('../../loc');
const currency = require('../../blue_modules/currency'); const currency = require('../../blue_modules/currency');
export default class SendCreate extends Component { export default class SendCreate extends Component {
static navigationOptions = ({ navigation, route }) => {
let headerRight;
if (route.params.exportTXN) {
headerRight = () => (
<TouchableOpacity style={styles.export} onPress={route.params.exportTXN}>
<Icon size={22} name="share-alternative" type="entypo" color={BlueApp.settings.foregroundColor} />
</TouchableOpacity>
);
} else {
headerRight = null;
}
return {
...BlueNavigationStyle,
title: loc.send.create.details,
headerRight,
};
};
constructor(props) { constructor(props) {
super(props); super(props);
console.log('send/create constructor'); console.log('send/create constructor');
@ -183,13 +163,13 @@ export default class SendCreate extends Component {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
transactionDetailsTitle: { transactionDetailsTitle: {
color: '#0c2550', color: BlueCurrentTheme.colors.feeText,
fontWeight: '500', fontWeight: '500',
fontSize: 17, fontSize: 17,
marginBottom: 2, marginBottom: 2,
}, },
transactionDetailsSubtitle: { transactionDetailsSubtitle: {
color: '#9aa0aa', color: BlueCurrentTheme.colors.foregroundColor,
fontWeight: '500', fontWeight: '500',
fontSize: 15, fontSize: 15,
marginBottom: 20, marginBottom: 20,
@ -201,20 +181,21 @@ const styles = StyleSheet.create({
alignSelf: 'flex-end', alignSelf: 'flex-end',
}, },
separator: { separator: {
backgroundColor: BlueApp.settings.inputBorderColor, backgroundColor: BlueCurrentTheme.colors.inputBorderColor,
height: 0.5, height: 0.5,
marginVertical: 16, marginVertical: 16,
}, },
root: { root: {
flex: 1, flex: 1,
paddingTop: 19, paddingTop: 19,
backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
card: { card: {
alignItems: 'center', alignItems: 'center',
flex: 1, flex: 1,
}, },
cardText: { cardText: {
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
fontWeight: '500', fontWeight: '500',
}, },
cardTx: { cardTx: {
@ -251,3 +232,22 @@ SendCreate.propTypes = {
params: PropTypes.object, params: PropTypes.object,
}), }),
}; };
SendCreate.navigationOptions = ({ navigation, route }) => {
let headerRight;
if (route.params.exportTXN) {
headerRight = () => (
<TouchableOpacity style={styles.export} onPress={route.params.exportTXN}>
<Icon size={22} name="share-alternative" type="entypo" color={BlueCurrentTheme.colors.foregroundColor} />
</TouchableOpacity>
);
} else {
headerRight = null;
}
return {
...BlueNavigationStyle,
title: loc.send.create.details,
headerRight,
};
};

View file

@ -40,6 +40,7 @@ import { BitcoinTransaction } from '../../models/bitcoinTransactionInfo';
import DocumentPicker from 'react-native-document-picker'; import DocumentPicker from 'react-native-document-picker';
import RNFS from 'react-native-fs'; import RNFS from 'react-native-fs';
import DeeplinkSchemaMatch from '../../class/deeplink-schema-match'; import DeeplinkSchemaMatch from '../../class/deeplink-schema-match';
import { BlueCurrentTheme } from '../../components/themes';
const bitcoin = require('bitcoinjs-lib'); const bitcoin = require('bitcoinjs-lib');
const currency = require('../../blue_modules/currency'); const currency = require('../../blue_modules/currency');
const BigNumber = require('bignumber.js'); const BigNumber = require('bignumber.js');
@ -53,34 +54,36 @@ const styles = StyleSheet.create({
loading: { loading: {
flex: 1, flex: 1,
paddingTop: 20, paddingTop: 20,
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.background,
}, },
root: { root: {
flex: 1, flex: 1,
justifyContent: 'space-between', justifyContent: 'space-between',
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
scrollViewContent: { scrollViewContent: {
flexWrap: 'wrap', flexWrap: 'wrap',
flexDirection: 'row', flexDirection: 'row',
}, },
modalContent: { modalContent: {
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.modal,
padding: 22, padding: 22,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
borderTopLeftRadius: 16, borderTopLeftRadius: 16,
borderTopRightRadius: 16, borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)', borderTopColor: BlueCurrentTheme.colors.borderTopColor,
borderWidth: BlueCurrentTheme.colors.borderWidth,
minHeight: 200, minHeight: 200,
height: 200, height: 200,
}, },
advancedTransactionOptionsModalContent: { advancedTransactionOptionsModalContent: {
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.modal,
padding: 22, padding: 22,
borderTopLeftRadius: 16, borderTopLeftRadius: 16,
borderTopRightRadius: 16, borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)', borderTopColor: BlueCurrentTheme.colors.borderTopColor,
borderWidth: BlueCurrentTheme.colors.borderWidth,
minHeight: 130, minHeight: 130,
}, },
bottomModal: { bottomModal: {
@ -88,7 +91,7 @@ const styles = StyleSheet.create({
margin: 0, margin: 0,
}, },
feeSliderInput: { feeSliderInput: {
backgroundColor: '#d2f8d6', backgroundColor: BlueCurrentTheme.colors.feeLabel,
minWidth: 127, minWidth: 127,
height: 60, height: 60,
borderRadius: 8, borderRadius: 8,
@ -98,7 +101,7 @@ const styles = StyleSheet.create({
}, },
feeSliderText: { feeSliderText: {
fontWeight: '600', fontWeight: '600',
color: '#37c0a1', color: BlueCurrentTheme.colors.feeValue,
marginBottom: 0, marginBottom: 0,
marginRight: 4, marginRight: 4,
textAlign: 'right', textAlign: 'right',
@ -106,7 +109,7 @@ const styles = StyleSheet.create({
}, },
feeSliderUnit: { feeSliderUnit: {
fontWeight: '600', fontWeight: '600',
color: '#37c0a1', color: BlueCurrentTheme.colors.feeValue,
paddingRight: 4, paddingRight: 4,
textAlign: 'left', textAlign: 'left',
fontSize: 16, fontSize: 16,
@ -137,7 +140,6 @@ const styles = StyleSheet.create({
marginHorizontal: 56, marginHorizontal: 56,
marginVertical: 16, marginVertical: 16,
alignContent: 'center', alignContent: 'center',
backgroundColor: '#FFFFFF',
minHeight: 44, minHeight: 44,
}, },
select: { select: {
@ -159,21 +161,22 @@ const styles = StyleSheet.create({
marginVertical: 4, marginVertical: 4,
}, },
selectLabel: { selectLabel: {
color: '#0c2550', color: BlueCurrentTheme.colors.buttonTextColor,
fontSize: 14, fontSize: 14,
}, },
of: { of: {
alignSelf: 'flex-end', alignSelf: 'flex-end',
marginRight: 18, marginRight: 18,
marginVertical: 8, marginVertical: 8,
color: BlueCurrentTheme.colors.feeText,
}, },
memo: { memo: {
flexDirection: 'row', flexDirection: 'row',
borderColor: '#d2d2d2', borderColor: BlueCurrentTheme.colors.formBorder,
borderBottomColor: '#d2d2d2', borderBottomColor: BlueCurrentTheme.colors.formBorder,
borderWidth: 1, borderWidth: 1,
borderBottomWidth: 0.5, borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
minHeight: 44, minHeight: 44,
height: 44, height: 44,
marginHorizontal: 20, marginHorizontal: 20,
@ -194,11 +197,11 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
}, },
feeLabel: { feeLabel: {
color: '#81868e', color: BlueCurrentTheme.colors.feeText,
fontSize: 14, fontSize: 14,
}, },
feeRow: { feeRow: {
backgroundColor: '#d2f8d6', backgroundColor: BlueCurrentTheme.colors.feeLabel,
minWidth: 40, minWidth: 40,
height: 25, height: 25,
borderRadius: 4, borderRadius: 4,
@ -208,24 +211,19 @@ const styles = StyleSheet.create({
paddingHorizontal: 10, paddingHorizontal: 10,
}, },
feeValue: { feeValue: {
color: '#37c0a1', color: BlueCurrentTheme.colors.feeValue,
marginBottom: 0, marginBottom: 0,
marginRight: 4, marginRight: 4,
textAlign: 'right', textAlign: 'right',
}, },
feeUnit: { feeUnit: {
color: '#37c0a1', color: BlueCurrentTheme.colors.feeValue,
paddingRight: 4, paddingRight: 4,
textAlign: 'left', textAlign: 'left',
}, },
}); });
export default class SendDetails extends Component { export default class SendDetails extends Component {
static navigationOptions = ({ navigation, route }) => ({
...BlueCreateTxNavigationStyle(navigation, route.params.withAdvancedOptionsMenuButton, route.params.advancedOptionsMenuButtonAction),
title: loc.send.header,
});
state = { isLoading: true }; state = { isLoading: true };
constructor(props) { constructor(props) {
@ -1082,3 +1080,8 @@ SendDetails.propTypes = {
}), }),
}), }),
}; };
SendDetails.navigationOptions = ({ navigation, route }) => ({
...BlueCreateTxNavigationStyle(navigation, route.params.withAdvancedOptionsMenuButton, route.params.advancedOptionsMenuButtonAction),
title: loc.send.header,
});

View file

@ -17,6 +17,7 @@ import {
import Clipboard from '@react-native-community/clipboard'; import Clipboard from '@react-native-community/clipboard';
import { import {
BlueButton, BlueButton,
SecondButton,
BlueText, BlueText,
SafeBlueArea, SafeBlueArea,
BlueCard, BlueCard,
@ -34,6 +35,7 @@ import RNFS from 'react-native-fs';
import DocumentPicker from 'react-native-document-picker'; import DocumentPicker from 'react-native-document-picker';
import { decodeUR, extractSingleWorkload } from 'bc-ur/dist'; import { decodeUR, extractSingleWorkload } from 'bc-ur/dist';
import { Psbt } from 'bitcoinjs-lib'; import { Psbt } from 'bitcoinjs-lib';
import { BlueCurrentTheme } from '../../components/themes';
const loc = require('../../loc'); const loc = require('../../loc');
const EV = require('../../blue_modules/events'); const EV = require('../../blue_modules/events');
const BlueElectrum = require('../../blue_modules/BlueElectrum'); const BlueElectrum = require('../../blue_modules/BlueElectrum');
@ -45,6 +47,7 @@ const { height, width } = Dimensions.get('window');
const styles = StyleSheet.create({ const styles = StyleSheet.create({
root: { root: {
flex: 1, flex: 1,
backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
scrollViewContent: { scrollViewContent: {
flexGrow: 1, flexGrow: 1,
@ -86,15 +89,15 @@ const styles = StyleSheet.create({
flex: 1, flex: 1,
}, },
hexLabel: { hexLabel: {
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
fontWeight: '500', fontWeight: '500',
}, },
hexInput: { hexInput: {
borderColor: '#ebebeb', borderColor: BlueCurrentTheme.colors.formBorder,
backgroundColor: '#d2f8d6', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
borderRadius: 4, borderRadius: 4,
marginTop: 20, marginTop: 20,
color: '#37c0a1', color: BlueCurrentTheme.colors.foregroundColor,
fontWeight: '500', fontWeight: '500',
fontSize: 14, fontSize: 14,
paddingHorizontal: 16, paddingHorizontal: 16,
@ -105,7 +108,7 @@ const styles = StyleSheet.create({
marginVertical: 24, marginVertical: 24,
}, },
hexText: { hexText: {
color: '#9aa0aa', color: BlueCurrentTheme.colors.foregroundColor,
fontSize: 15, fontSize: 15,
fontWeight: '500', fontWeight: '500',
alignSelf: 'center', alignSelf: 'center',
@ -117,11 +120,6 @@ const styles = StyleSheet.create({
}); });
export default class PsbtWithHardwareWallet extends Component { export default class PsbtWithHardwareWallet extends Component {
static navigationOptions = () => ({
...BlueNavigationStyle(null, false),
title: loc.send.header,
});
cameraRef = null; cameraRef = null;
_onReadUniformResource = ur => { _onReadUniformResource = ur => {
@ -319,7 +317,7 @@ export default class PsbtWithHardwareWallet extends Component {
<Text style={styles.hexText}>Verify on coinb.in</Text> <Text style={styles.hexText}>Verify on coinb.in</Text>
</TouchableOpacity> </TouchableOpacity>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueButton onPress={this.broadcast} title={loc.send.confirm.sendNow} /> <SecondButton onPress={this.broadcast} title={loc.send.confirm.sendNow} />
</BlueCard> </BlueCard>
</View> </View>
); );
@ -394,36 +392,36 @@ export default class PsbtWithHardwareWallet extends Component {
<View style={styles.container}> <View style={styles.container}>
<BlueCard> <BlueCard>
<BlueText testID="TextHelperForPSBT"> <BlueText testID="TextHelperForPSBT">
This is partially signed bitcoin transaction (PSBT). Please finish signing it with your hardware wallet. This is a partially signed bitcoin transaction (PSBT). Please finish signing it with your hardware wallet.
</BlueText> </BlueText>
<BlueSpacing20 /> <BlueSpacing20 />
<DynamicQRCode value={this.state.psbt.toHex()} capacity={200} /> <DynamicQRCode value={this.state.psbt.toHex()} capacity={200} />
<BlueSpacing20 /> <BlueSpacing20 />
<BlueButton <SecondButton
icon={{ icon={{
name: 'qrcode', name: 'qrcode',
type: 'font-awesome', type: 'font-awesome',
color: BlueApp.settings.buttonTextColor, color: BlueCurrentTheme.colors.buttonTextColor,
}} }}
onPress={() => this.setState({ renderScanner: true, animatedQRCodeData: [] })} onPress={() => this.setState({ renderScanner: true, animatedQRCodeData: [] })}
title="Scan Signed Transaction" title="Scan Signed Transaction"
/> />
<BlueSpacing20 /> <BlueSpacing20 />
<BlueButton <SecondButton
icon={{ icon={{
name: 'file-import', name: 'file-import',
type: 'material-community', type: 'material-community',
color: BlueApp.settings.buttonTextColor, color: BlueCurrentTheme.colors.buttonTextColor,
}} }}
onPress={this.openSignedTransaction} onPress={this.openSignedTransaction}
title="Open Signed Transaction" title="Open Signed Transaction"
/> />
<BlueSpacing20 /> <BlueSpacing20 />
<BlueButton <SecondButton
icon={{ icon={{
name: 'share-alternative', name: 'share-alternative',
type: 'entypo', type: 'entypo',
color: BlueApp.settings.buttonTextColor, color: BlueCurrentTheme.colors.buttonTextColor,
}} }}
onPress={this.exportPSBT} onPress={this.exportPSBT}
title="Export to file" title="Export to file"
@ -453,3 +451,8 @@ PsbtWithHardwareWallet.propTypes = {
params: PropTypes.object, params: PropTypes.object,
}), }),
}; };
PsbtWithHardwareWallet.navigationOptions = () => ({
...BlueNavigationStyle(null, false),
title: loc.send.header,
});

View file

@ -6,12 +6,14 @@ import { Text } from 'react-native-elements';
import { BlueButton, SafeBlueArea, BlueCard } from '../../BlueComponents'; import { BlueButton, SafeBlueArea, BlueCard } from '../../BlueComponents';
import { BitcoinUnit } from '../../models/bitcoinUnits'; import { BitcoinUnit } from '../../models/bitcoinUnits';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { BlueCurrentTheme } from '../../components/themes';
const loc = require('../../loc'); const loc = require('../../loc');
const styles = StyleSheet.create({ const styles = StyleSheet.create({
root: { root: {
flex: 1, flex: 1,
paddingTop: 19, paddingTop: 19,
backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
amout: { amout: {
alignItems: 'center', alignItems: 'center',
@ -24,12 +26,12 @@ const styles = StyleSheet.create({
paddingBottom: 16, paddingBottom: 16,
}, },
amountValue: { amountValue: {
color: '#0f5cc0', color: BlueCurrentTheme.colors.alternativeTextColor2,
fontSize: 36, fontSize: 36,
fontWeight: '600', fontWeight: '600',
}, },
amountUnit: { amountUnit: {
color: '#0f5cc0', color: BlueCurrentTheme.colors.alternativeTextColor2,
fontSize: 16, fontSize: 16,
marginHorizontal: 4, marginHorizontal: 4,
paddingBottom: 6, paddingBottom: 6,
@ -61,11 +63,6 @@ const styles = StyleSheet.create({
}); });
export default class Success extends Component { export default class Success extends Component {
static navigationOptions = {
headerShown: false,
gesturesEnabled: false,
};
constructor(props) { constructor(props) {
super(props); super(props);
console.log('send/success constructor'); console.log('send/success constructor');
@ -103,7 +100,26 @@ export default class Success extends Component {
)} )}
</BlueCard> </BlueCard>
<View style={styles.ready}> <View style={styles.ready}>
<LottieView style={styles.lottie} source={require('../../img/bluenice.json')} autoPlay loop={false} /> <LottieView
style={styles.lottie}
source={require('../../img/bluenice.json')}
autoPlay
loop={false}
colorFilters={[
{
keypath: 'spark',
color: BlueCurrentTheme.colors.success,
},
{
keypath: 'circle',
color: BlueCurrentTheme.colors.success,
},
{
keypath: 'Oval',
color: BlueCurrentTheme.colors.successCheck,
},
]}
/>
</View> </View>
<BlueCard> <BlueCard>
<BlueButton <BlueButton
@ -134,3 +150,8 @@ Success.propTypes = {
params: PropTypes.object, params: PropTypes.object,
}), }),
}; };
Success.navigationOptions = {
headerShown: false,
gesturesEnabled: false,
};

View file

@ -1,9 +1,8 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ScrollView, Platform, TouchableWithoutFeedback, TouchableOpacity, StyleSheet } from 'react-native'; import { ScrollView, Platform, TouchableWithoutFeedback, TouchableOpacity, StyleSheet } from 'react-native';
import { BlueLoading, BlueText, BlueSpacing20, BlueListItem, SafeBlueArea, BlueNavigationStyle, BlueCard } from '../../BlueComponents'; import { BlueLoading, BlueTextHooks, BlueSpacing20, BlueListItemHooks, BlueNavigationStyle, BlueCard } from '../../BlueComponents';
import PropTypes from 'prop-types';
import { AppStorage } from '../../class'; import { AppStorage } from '../../class';
import { useNavigation } from '@react-navigation/native'; import { useNavigation, useTheme } from '@react-navigation/native';
import HandoffSettings from '../../class/handoff'; import HandoffSettings from '../../class/handoff';
const BlueApp: AppStorage = require('../../BlueApp'); const BlueApp: AppStorage = require('../../BlueApp');
const loc = require('../../loc'); const loc = require('../../loc');
@ -19,6 +18,7 @@ const GeneralSettings = () => {
const [isAdancedModeEnabled, setIsAdancedModeEnabled] = useState(false); const [isAdancedModeEnabled, setIsAdancedModeEnabled] = useState(false);
const [isHandoffUseEnabled, setIsHandoffUseEnabled] = useState(false); const [isHandoffUseEnabled, setIsHandoffUseEnabled] = useState(false);
const { navigate } = useNavigation(); const { navigate } = useNavigation();
const { colors } = useTheme();
const onAdvancedModeSwitch = async value => { const onAdvancedModeSwitch = async value => {
await BlueApp.setIsAdancedModeEnabled(value); await BlueApp.setIsAdancedModeEnabled(value);
setIsAdancedModeEnabled(value); setIsAdancedModeEnabled(value);
@ -37,46 +37,59 @@ const GeneralSettings = () => {
})(); })();
}); });
const stylesWithThemeHook = {
root: {
...styles.root,
backgroundColor: colors.background,
},
scroll: {
...styles.scroll,
backgroundColor: colors.background,
},
scrollBody: {
...styles.scrollBody,
backgroundColor: colors.background,
},
};
return isLoading ? ( return isLoading ? (
<BlueLoading /> <BlueLoading />
) : ( ) : (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}> <ScrollView style={stylesWithThemeHook.scroll}>
<ScrollView>
{BlueApp.getWallets().length > 1 && ( {BlueApp.getWallets().length > 1 && (
<> <>
<BlueListItem component={TouchableOpacity} onPress={() => navigate('DefaultView')} title="On Launch" chevron /> <BlueListItemHooks component={TouchableOpacity} onPress={() => navigate('DefaultView')} title="On Launch" chevron />
</> </>
)} )}
{Platform.OS === 'ios' ? ( {Platform.OS === 'ios' ? (
<> <>
<BlueListItem <BlueListItemHooks
hideChevron hideChevron
title="Continuity" title="Continuity"
Component={TouchableWithoutFeedback} Component={TouchableWithoutFeedback}
switch={{ onValueChange: onHandOffEnabledSwitch, value: isHandoffUseEnabled }} switch={{ onValueChange: onHandOffEnabledSwitch, value: isHandoffUseEnabled }}
/> />
<BlueCard> <BlueCard>
<BlueText> <BlueTextHooks>
When enabled, you will be able to view selected wallets, and transactions, using your other Apple iCloud connected devices. When enabled, you will be able to view selected wallets, and transactions, using your other Apple iCloud connected devices.
</BlueText> </BlueTextHooks>
</BlueCard> </BlueCard>
<BlueSpacing20 /> <BlueSpacing20 />
</> </>
) : null} ) : null}
<BlueListItem <BlueListItemHooks
Component={TouchableWithoutFeedback} Component={TouchableWithoutFeedback}
title={loc.settings.enable_advanced_mode} title={loc.settings.enable_advanced_mode}
switch={{ onValueChange: onAdvancedModeSwitch, value: isAdancedModeEnabled }} switch={{ onValueChange: onAdvancedModeSwitch, value: isAdancedModeEnabled }}
/> />
<BlueCard> <BlueCard>
<BlueText> <BlueTextHooks>
When enabled, you will see advanced options such as different wallet types, the ability to specify the LNDHub instance you wish When enabled, you will see advanced options such as different wallet types, the ability to specify the LNDHub instance you wish to
to connect to and custom entropy during wallet creation. connect to and custom entropy during wallet creation.
</BlueText> </BlueTextHooks>
</BlueCard> </BlueCard>
<BlueSpacing20 /> <BlueSpacing20 />
</ScrollView> </ScrollView>
</SafeBlueArea>
); );
}; };
@ -85,12 +98,4 @@ GeneralSettings.navigationOptions = () => ({
title: 'General', title: 'General',
}); });
GeneralSettings.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
popToTop: PropTypes.func,
goBack: PropTypes.func,
}),
};
export default GeneralSettings; export default GeneralSettings;

View file

@ -1,42 +1,48 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ScrollView, TouchableOpacity, StyleSheet } from 'react-native'; import { ScrollView, StyleSheet } from 'react-native';
import { BlueNavigationStyle, BlueLoading, SafeBlueArea, BlueListItem } from '../../BlueComponents'; import { SafeBlueArea, BlueListItemHooks, BlueNavigationStyle, BlueLoadingHook } from '../../BlueComponents';
import { useNavigation } from '@react-navigation/native'; import { useNavigation, useTheme } from '@react-navigation/native';
const loc = require('../../loc'); const loc = require('../../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
},
});
const NetworkSettings = () => { const NetworkSettings = () => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const { navigate } = useNavigation(); const { navigate } = useNavigation();
const { colors } = useTheme();
const styles = StyleSheet.create({
root: {
flex: 1,
backgroundColor: colors.background,
},
});
useEffect(() => { useEffect(() => {
setIsLoading(false); setIsLoading(false);
}, []); }, []);
const navigateToElectrumSettings = () => {
navigate('ElectrumSettings');
};
const navigateToLightningSettings = () => {
navigate('LightningSettings');
};
const navigateToBroadcast = () => {
navigate('Broadcast');
};
return isLoading ? ( return isLoading ? (
<BlueLoading /> <BlueLoadingHook />
) : ( ) : (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView> <ScrollView>
<BlueListItem title="Electrum server" component={TouchableOpacity} onPress={() => navigate('ElectrumSettings')} chevron /> <BlueListItemHooks title="Electrum server" onPress={navigateToElectrumSettings} chevron />
<BlueListItem <BlueListItemHooks title={loc.settings.lightning_settings} onPress={navigateToLightningSettings} chevron />
title={loc.settings.lightning_settings} <BlueListItemHooks title="Broadcast transaction" onPress={navigateToBroadcast} chevron />
component={TouchableOpacity}
onPress={() => navigate('LightningSettings')}
chevron
/>
<BlueListItem title="Broadcast transaction" component={TouchableOpacity} onPress={() => navigate('Broadcast')} chevron />
</ScrollView> </ScrollView>
</SafeBlueArea> </SafeBlueArea>
); );
}; };
NetworkSettings.navigationOptions = { NetworkSettings.navigationOptions = () => ({
...BlueNavigationStyle(), ...BlueNavigationStyle(),
title: 'Network', title: 'Network',
}; });
export default NetworkSettings; export default NetworkSettings;

View file

@ -1,15 +1,15 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ScrollView, Linking, Dimensions, Image, View, Text, StyleSheet } from 'react-native'; import { ScrollView, Linking, Dimensions, Image, View, Text, StyleSheet } from 'react-native';
import { useNavigation } from '@react-navigation/native'; import { useNavigation, useTheme } from '@react-navigation/native';
import { import {
BlueTextCentered, BlueTextCentered,
BlueLoading,
BlueSpacing20, BlueSpacing20,
BlueButton, BlueButton,
SafeBlueArea, SafeBlueArea,
BlueCard, BlueCard,
BlueListItemHooks,
BlueNavigationStyle, BlueNavigationStyle,
BlueListItem, BlueLoadingHook,
} from '../../BlueComponents'; } from '../../BlueComponents';
import { getApplicationName, getVersion, getBundleId, getBuildNumber } from 'react-native-device-info'; import { getApplicationName, getVersion, getBundleId, getBuildNumber } from 'react-native-device-info';
import Rate, { AndroidMarket } from 'react-native-rate'; import Rate, { AndroidMarket } from 'react-native-rate';
@ -17,6 +17,10 @@ import Rate, { AndroidMarket } from 'react-native-rate';
const { width, height } = Dimensions.get('window'); const { width, height } = Dimensions.get('window');
const loc = require('../../loc/'); const loc = require('../../loc/');
const About = () => {
const [isLoading, setIsLoading] = useState(true);
const { navigate } = useNavigation();
const { colors } = useTheme();
const styles = StyleSheet.create({ const styles = StyleSheet.create({
root: { root: {
flex: 1, flex: 1,
@ -41,23 +45,19 @@ const styles = StyleSheet.create({
textBackup: { textBackup: {
maxWidth: 260, maxWidth: 260,
marginBottom: 40, marginBottom: 40,
color: '#0C2550', color: colors.foregroundColor,
fontSize: 15, fontSize: 15,
textAlign: 'center', textAlign: 'center',
fontWeight: '500', fontWeight: '500',
}, },
buildWith: { buildWith: {
backgroundColor: '#f9f9f9', backgroundColor: colors.inputBackgroundColor,
padding: 16, padding: 16,
paddingTop: 0, paddingTop: 0,
borderRadius: 8, borderRadius: 8,
}, },
}); });
const About = () => {
const [isLoading, setIsLoading] = useState(true);
const { navigate } = useNavigation();
useEffect(() => { useEffect(() => {
setIsLoading(false); setIsLoading(false);
}, []); }, []);
@ -103,7 +103,7 @@ const About = () => {
}; };
return isLoading ? ( return isLoading ? (
<BlueLoading /> <BlueLoadingHook />
) : ( ) : (
<SafeBlueArea style={styles.root}> <SafeBlueArea style={styles.root}>
<ScrollView testID="AboutScrollView"> <ScrollView testID="AboutScrollView">
@ -115,7 +115,7 @@ const About = () => {
<BlueButton onPress={handleOnRatePress} title="Leave us a review ⭐🙏" /> <BlueButton onPress={handleOnRatePress} title="Leave us a review ⭐🙏" />
</View> </View>
</BlueCard> </BlueCard>
<BlueListItem <BlueListItemHooks
leftIcon={{ leftIcon={{
name: 'twitter', name: 'twitter',
type: 'font-awesome', type: 'font-awesome',
@ -124,7 +124,7 @@ const About = () => {
onPress={handleOnTwitterPress} onPress={handleOnTwitterPress}
title="Follow us on Twitter" title="Follow us on Twitter"
/> />
<BlueListItem <BlueListItemHooks
leftIcon={{ leftIcon={{
name: 'telegram', name: 'telegram',
type: 'font-awesome', type: 'font-awesome',
@ -133,11 +133,11 @@ const About = () => {
onPress={handleOnTelegramPress} onPress={handleOnTelegramPress}
title="Telegram chat" title="Telegram chat"
/> />
<BlueListItem <BlueListItemHooks
leftIcon={{ leftIcon={{
name: 'github', name: 'github',
type: 'font-awesome', type: 'font-awesome',
color: 'black', color: colors.foregroundColor,
}} }}
onPress={handleOnGithubPress} onPress={handleOnGithubPress}
title="GitHub" title="GitHub"
@ -154,7 +154,7 @@ const About = () => {
<BlueTextCentered>Electrum server</BlueTextCentered> <BlueTextCentered>Electrum server</BlueTextCentered>
</View> </View>
</BlueCard> </BlueCard>
<BlueListItem <BlueListItemHooks
leftIcon={{ leftIcon={{
name: 'book', name: 'book',
type: 'font-awesome', type: 'font-awesome',
@ -164,17 +164,17 @@ const About = () => {
onPress={handleOnReleaseNotesPress} onPress={handleOnReleaseNotesPress}
title="Release notes" title="Release notes"
/> />
<BlueListItem <BlueListItemHooks
leftIcon={{ leftIcon={{
name: 'law', name: 'law',
type: 'octicon', type: 'octicon',
color: 'black', color: colors.foregroundColor,
}} }}
chevron chevron
onPress={handleOnLicensingPress} onPress={handleOnLicensingPress}
title="MIT License" title="MIT License"
/> />
<BlueListItem <BlueListItemHooks
leftIcon={{ leftIcon={{
name: 'flask', name: 'flask',
type: 'font-awesome', type: 'font-awesome',
@ -204,6 +204,6 @@ const About = () => {
About.navigationOptions = () => ({ About.navigationOptions = () => ({
...BlueNavigationStyle(), ...BlueNavigationStyle(),
title: loc.settings.about, headerTitle: loc.settings.about,
}); });
export default About; export default About;

View file

@ -1,29 +1,32 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { FlatList, TouchableOpacity, ActivityIndicator, View, StyleSheet } from 'react-native'; import { FlatList, TouchableOpacity, ActivityIndicator, View, StyleSheet } from 'react-native';
import { SafeBlueArea, BlueNavigationStyle, BlueListItem, BlueText, BlueCard } from '../../BlueComponents'; import { SafeBlueArea, BlueListItemHooks, BlueTextHooks, BlueCard, BlueNavigationStyle } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import { FiatUnit } from '../../models/fiatUnit'; import { FiatUnit } from '../../models/fiatUnit';
import { useTheme } from '@react-navigation/native';
const loc = require('../../loc'); const loc = require('../../loc');
const currency = require('../../blue_modules/currency'); const currency = require('../../blue_modules/currency');
const data = Object.values(FiatUnit); const data = Object.values(FiatUnit);
const Currency = () => {
const [isSavingNewPreferredCurrency, setIsSavingNewPreferredCurrency] = useState(false);
const [selectedCurrency, setSelectedCurrency] = useState(null);
const { colors } = useTheme();
const styles = StyleSheet.create({ const styles = StyleSheet.create({
flex: { flex: {
flex: 1, flex: 1,
backgroundColor: colors.background,
}, },
activity: { activity: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
backgroundColor: colors.background,
}, },
}); });
const Currency = () => {
const [isSavingNewPreferredCurrency, setIsSavingNewPreferredCurrency] = useState(false);
const [selectedCurrency, setSelectedCurrency] = useState(null);
useEffect(() => { useEffect(() => {
const fetchCurrency = async () => { const fetchCurrency = async () => {
try { try {
@ -49,7 +52,7 @@ const Currency = () => {
extraData={data} extraData={data}
renderItem={({ item }) => { renderItem={({ item }) => {
return ( return (
<BlueListItem <BlueListItemHooks
disabled={isSavingNewPreferredCurrency} disabled={isSavingNewPreferredCurrency}
title={`${item.endPointKey} (${item.symbol})`} title={`${item.endPointKey} (${item.symbol})`}
{...(selectedCurrency.endPointKey === item.endPointKey {...(selectedCurrency.endPointKey === item.endPointKey
@ -68,7 +71,7 @@ const Currency = () => {
}} }}
/> />
<BlueCard> <BlueCard>
<BlueText>Prices are obtained from CoinDesk</BlueText> <BlueTextHooks>Prices are obtained from CoinDesk</BlueTextHooks>
</BlueCard> </BlueCard>
</SafeBlueArea> </SafeBlueArea>
); );

View file

@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { TouchableOpacity, View, TouchableWithoutFeedback, StyleSheet } from 'react-native'; import { View, TouchableWithoutFeedback, StyleSheet } from 'react-native';
import { SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle, BlueListItem } from '../../BlueComponents'; import { SafeBlueArea, BlueCard, BlueNavigationStyle, BlueListItemHooks, BlueTextHooks } from '../../BlueComponents';
import OnAppLaunch from '../../class/on-app-launch'; import OnAppLaunch from '../../class/on-app-launch';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
@ -56,7 +56,7 @@ const DefaultView = () => {
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.flex}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.flex}>
<View> <View>
<BlueListItem <BlueListItemHooks
title="View All Wallets" title="View All Wallets"
Component={TouchableWithoutFeedback} Component={TouchableWithoutFeedback}
switch={{ switch={{
@ -66,10 +66,10 @@ const DefaultView = () => {
}} }}
/> />
<BlueCard> <BlueCard>
<BlueText>When disabled, BlueWallet will immediately open the selected wallet at launch.</BlueText> <BlueTextHooks>When disabled, BlueWallet will immediately open the selected wallet at launch.</BlueTextHooks>
</BlueCard> </BlueCard>
{!viewAllWalletsEnabled && ( {!viewAllWalletsEnabled && (
<BlueListItem title="Default into" component={TouchableOpacity} onPress={selectWallet} rightTitle={defaultWalletLabel} chevron /> <BlueListItemHooks title="Default into" onPress={selectWallet} rightTitle={defaultWalletLabel} chevron />
)} )}
</View> </View>
</SafeBlueArea> </SafeBlueArea>

View file

@ -4,8 +4,9 @@ import { View, TextInput, StyleSheet } from 'react-native';
import { AppStorage } from '../../class'; import { AppStorage } from '../../class';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import { ScrollView } from 'react-native-gesture-handler'; import { ScrollView } from 'react-native-gesture-handler';
import { BlueLoading, BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueNavigationStyle, BlueText } from '../../BlueComponents'; import { BlueLoading, BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../../BlueComponents';
import PropTypes from 'prop-types'; import { BlueCurrentTheme } from '../../components/themes';
const loc = require('../../loc'); const loc = require('../../loc');
const BlueElectrum = require('../../blue_modules/BlueElectrum'); const BlueElectrum = require('../../blue_modules/BlueElectrum');
@ -15,7 +16,7 @@ const styles = StyleSheet.create({
}, },
status: { status: {
textAlign: 'center', textAlign: 'center',
color: '#9AA0AA', color: BlueCurrentTheme.colors.feeText,
marginBottom: 4, marginBottom: 4,
}, },
connectWrap: { connectWrap: {
@ -33,13 +34,13 @@ const styles = StyleSheet.create({
borderRadius: 20, borderRadius: 20,
}, },
containerConnected: { containerConnected: {
backgroundColor: '#D2F8D6', backgroundColor: BlueCurrentTheme.colors.feeLabel,
}, },
containerDisconnected: { containerDisconnected: {
backgroundColor: '#F8D2D2', backgroundColor: '#F8D2D2',
}, },
textConnected: { textConnected: {
color: '#37C0A1', color: BlueCurrentTheme.colors.feeValue,
fontWeight: 'bold', fontWeight: 'bold',
}, },
textDisconnected: { textDisconnected: {
@ -48,19 +49,19 @@ const styles = StyleSheet.create({
}, },
hostname: { hostname: {
textAlign: 'center', textAlign: 'center',
color: '#0C2550', color: BlueCurrentTheme.colors.foregroundColor,
}, },
explain: { explain: {
color: '#9AA0AA', color: BlueCurrentTheme.colors.feeText,
marginBottom: -24, marginBottom: -24,
}, },
inputWrap: { inputWrap: {
flexDirection: 'row', flexDirection: 'row',
borderColor: '#d2d2d2', borderColor: BlueCurrentTheme.colors.formBorder,
borderBottomColor: '#d2d2d2', borderBottomColor: BlueCurrentTheme.colors.formBorder,
borderWidth: 1, borderWidth: 1,
borderBottomWidth: 0.5, borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
minHeight: 44, minHeight: 44,
height: 44, height: 44,
alignItems: 'center', alignItems: 'center',
@ -76,11 +77,6 @@ const styles = StyleSheet.create({
}); });
export default class ElectrumSettings extends Component { export default class ElectrumSettings extends Component {
static navigationOptions = () => ({
...BlueNavigationStyle(),
title: loc.settings.electrum_settings,
});
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -223,9 +219,7 @@ export default class ElectrumSettings extends Component {
} }
} }
ElectrumSettings.propTypes = { ElectrumSettings.navigationOptions = () => ({
navigation: PropTypes.shape({ ...BlueNavigationStyle(),
navigate: PropTypes.func, title: loc.settings.electrum_settings,
goBack: PropTypes.func, });
}),
};

View file

@ -1,106 +1,100 @@
/* global alert */ /* global alert */
import React, { Component } from 'react'; import React, { useEffect, useState, useCallback } from 'react';
import { ScrollView, Alert, Platform, TouchableOpacity, TouchableWithoutFeedback, StyleSheet } from 'react-native'; import { ScrollView, Alert, Platform, TouchableOpacity, TouchableWithoutFeedback, StyleSheet } from 'react-native';
import { import {
BlueLoading, BlueLoadingHook,
BlueHeaderDefaultSub,
BlueListItem,
SafeBlueArea, SafeBlueArea,
BlueNavigationStyle,
BlueSpacing20, BlueSpacing20,
BlueCard, BlueCard,
BlueText, BlueListItemHooks,
BlueHeaderDefaultSubHooks,
BlueTextHooks,
BlueNavigationStyle,
} from '../../BlueComponents'; } from '../../BlueComponents';
import PropTypes from 'prop-types';
import { AppStorage } from '../../class'; import { AppStorage } from '../../class';
import { useNavigation, StackActions } from '@react-navigation/native';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import Biometric from '../../class/biometrics'; import Biometric from '../../class/biometrics';
import { colors } from 'react-native-elements';
const BlueApp: AppStorage = require('../../BlueApp'); const BlueApp: AppStorage = require('../../BlueApp');
const prompt = require('../../blue_modules/prompt'); const prompt = require('../../blue_modules/prompt');
const loc = require('../../loc'); const loc = require('../../loc');
const EncryptStorage = () => {
const [isLoading, setIsLoading] = useState(true);
const [deleteWalletsAfterUninstall, setDeleteWalletsAfterUninstall] = useState(false);
const [biometrics, setBiometrics] = useState({ isDeviceBiometricCapable: false, isBiometricsEnabled: false, biometricsType: '' });
const [storageIsEncrypted, setStorageIsEncrypted] = useState(false);
const { navigate, dispatch } = useNavigation();
const styles = StyleSheet.create({ const styles = StyleSheet.create({
root: { root: {
flex: 1, flex: 1,
backgroundColor: colors.background,
}, },
}); });
export default class EncryptStorage extends Component { const initialState = useCallback(async () => {
static navigationOptions = () => ({
...BlueNavigationStyle(),
title: 'Security',
});
constructor(props) {
super(props);
this.state = {
isLoading: true,
language: loc.getLanguage(),
deleteWalletsAfterUninstall: false,
biometrics: { isDeviceBiometricCapable: false, isBiometricsEnabled: false, biometricsType: '' },
};
}
async componentDidMount() {
const isBiometricsEnabled = await Biometric.isBiometricUseEnabled(); const isBiometricsEnabled = await Biometric.isBiometricUseEnabled();
const isDeviceBiometricCapable = await Biometric.isDeviceBiometricCapable(); const isDeviceBiometricCapable = await Biometric.isDeviceBiometricCapable();
const biometricsType = (await Biometric.biometricType()) || 'biometrics'; const biometricsType = (await Biometric.biometricType()) || 'biometrics';
this.setState({ const deleteWalletsAfterUninstall = await BlueApp.isDeleteWalletAfterUninstallEnabled();
isLoading: false, const isStorageEncrypted = await BlueApp.storageIsEncrypted();
advancedModeEnabled: await BlueApp.isAdancedModeEnabled(), setBiometrics(biometrics);
storageIsEncrypted: await BlueApp.storageIsEncrypted(), setStorageIsEncrypted(isStorageEncrypted);
deleteWalletsAfterUninstall: await BlueApp.isDeleteWalletAfterUninstallEnabled(), setDeleteWalletsAfterUninstall(deleteWalletsAfterUninstall);
biometrics: { isBiometricsEnabled, isDeviceBiometricCapable, biometricsType }, setBiometrics({ isBiometricsEnabled, isDeviceBiometricCapable, biometricsType });
}); setIsLoading(false);
} // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
initialState();
}, [initialState]);
decryptStorage = async () => { const decryptStorage = useCallback(async () => {
const password = await prompt(loc.settings.password, loc._.storage_is_encrypted).catch(() => { const password = await prompt(loc.settings.password, loc._.storage_is_encrypted).catch(() => {
this.setState({ isLoading: false }); setIsLoading(false);
}); });
try { try {
await BlueApp.decryptStorage(password); await BlueApp.decryptStorage(password);
this.props.navigation.popToTop(); dispatch(StackActions.popToTop());
} catch (e) { } catch (e) {
if (password) { if (password) {
alert(loc._.bad_password); alert(loc._.bad_password);
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
} }
this.setState({
isLoading: false, setIsLoading(false);
storageIsEncrypted: await BlueApp.storageIsEncrypted(), setStorageIsEncrypted(await BlueApp.storageIsEncrypted());
deleteWalletAfterUninstall: await BlueApp.isDeleteWalletAfterUninstallEnabled(), setDeleteWalletsAfterUninstall(await BlueApp.isDeleteWalletAfterUninstallEnabled());
});
} }
}; }, [dispatch]);
onDeleteWalletsAfterUninstallSwitch = async value => { const onDeleteWalletsAfterUninstallSwitch = useCallback(async value => {
await BlueApp.setResetOnAppUninstallTo(value); await BlueApp.setResetOnAppUninstallTo(value);
this.setState({ deleteWalletsAfterUninstall: value }); setDeleteWalletsAfterUninstall(value);
}; }, []);
onEncryptStorageSwitch = value => { const onEncryptStorageSwitch = useCallback(
this.setState({ isLoading: true }, async () => { async value => {
setIsLoading(true);
if (value === true) { if (value === true) {
let p1 = await prompt(loc.settings.password, loc.settings.password_explain).catch(() => { let p1 = await prompt(loc.settings.password, loc.settings.password_explain).catch(() => {
this.setState({ isLoading: false }); setIsLoading(false);
p1 = undefined; p1 = undefined;
}); });
if (!p1) { if (!p1) {
this.setState({ isLoading: false }); setIsLoading(false);
return; return;
} }
const p2 = await prompt(loc.settings.password, loc.settings.retype_password).catch(() => { const p2 = await prompt(loc.settings.password, loc.settings.retype_password).catch(() => {
this.setState({ isLoading: false }); setIsLoading(false);
}); });
if (p1 === p2) { if (p1 === p2) {
await BlueApp.encryptStorage(p1); await BlueApp.encryptStorage(p1);
this.setState({ setIsLoading(false);
isLoading: false, setStorageIsEncrypted(await BlueApp.storageIsEncrypted());
storageIsEncrypted: await BlueApp.storageIsEncrypted(),
});
} else { } else {
this.setState({ isLoading: false }); setIsLoading(false);
alert(loc.settings.passwords_do_not_match); alert(loc.settings.passwords_do_not_match);
} }
} else { } else {
@ -111,77 +105,87 @@ export default class EncryptStorage extends Component {
{ {
text: loc.send.details.cancel, text: loc.send.details.cancel,
style: 'cancel', style: 'cancel',
onPress: () => this.setState({ isLoading: false }), onPress: () => setIsLoading(false),
}, },
{ {
text: loc._.ok, text: loc._.ok,
style: 'destructive', style: 'destructive',
onPress: this.decryptStorage, onPress: decryptStorage,
}, },
], ],
{ cancelable: false }, { cancelable: false },
); );
} }
}); },
}; [decryptStorage],
);
onUseBiometricSwitch = async value => { const onUseBiometricSwitch = useCallback(
const isBiometricsEnabled = this.state.biometrics; async value => {
const isBiometricsEnabled = {
isDeviceBiometricCapable: biometrics.isDeviceBiometricCapable,
isBiometricsEnabled: biometrics.isBiometricsEnabled,
biometricsType: biometrics.biometricsType,
};
if (await Biometric.unlockWithBiometrics()) { if (await Biometric.unlockWithBiometrics()) {
isBiometricsEnabled.isBiometricsEnabled = value; isBiometricsEnabled.isBiometricsEnabled = value;
await Biometric.setBiometricUseEnabled(value); await Biometric.setBiometricUseEnabled(value);
this.setState({ biometrics: isBiometricsEnabled }); setBiometrics(isBiometricsEnabled);
} }
},
[biometrics],
);
const navigateToPlausibleDeniability = () => {
navigate('PlausibleDeniability');
}; };
render() { return isLoading ? (
if (this.state.isLoading) {
return <BlueLoading />;
}
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView> <BlueLoadingHook />
{this.state.biometrics.isDeviceBiometricCapable && ( </SafeBlueArea>
) : (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView contentContainerStyle={styles.root}>
{biometrics.isDeviceBiometricCapable && (
<> <>
<BlueHeaderDefaultSub leftText="biometrics" rightComponent={null} /> <BlueHeaderDefaultSubHooks leftText="biometrics" rightComponent={null} />
<BlueListItem <BlueListItemHooks
title={`Use ${this.state.biometrics.biometricsType}`} title={`Use ${biometrics.biometricsType}`}
Component={TouchableWithoutFeedback} Component={TouchableWithoutFeedback}
switch={{ value: this.state.biometrics.isBiometricsEnabled, onValueChange: this.onUseBiometricSwitch }} switch={{ value: biometrics.isBiometricsEnabled, onValueChange: onUseBiometricSwitch }}
/> />
<BlueCard> <BlueCard>
<BlueText> <BlueTextHooks>
{this.state.biometrics.biometricsType} will be used to confirm your identity prior to making a transaction, unlocking, {biometrics.biometricsType} will be used to confirm your identity prior to making a transaction, unlocking, exporting or
exporting or deleting a wallet. {this.state.biometrics.biometricsType} will not be used to unlock an encrypted storage. deleting a wallet. {biometrics.biometricsType} will not be used to unlock an encrypted storage.
</BlueText> </BlueTextHooks>
</BlueCard> </BlueCard>
<BlueSpacing20 /> <BlueSpacing20 />
</> </>
)} )}
<BlueHeaderDefaultSub leftText="storage" rightComponent={null} /> <BlueHeaderDefaultSubHooks leftText="storage" rightComponent={null} />
<BlueListItem <BlueListItemHooks
testID="EncyptedAndPasswordProtected" testID="EncyptedAndPasswordProtected"
hideChevron hideChevron
title="Encrypted and Password protected" title="Encrypted and Password protected"
Component={TouchableWithoutFeedback} Component={TouchableWithoutFeedback}
switch={{ onValueChange: this.onEncryptStorageSwitch, value: this.state.storageIsEncrypted }} switch={{ onValueChange: onEncryptStorageSwitch, value: storageIsEncrypted }}
/> />
{Platform.OS === 'ios' && ( {Platform.OS === 'ios' && (
<BlueListItem <BlueListItemHooks
hideChevron hideChevron
title="Delete if BlueWallet is uninstalled" title="Delete if BlueWallet is uninstalled"
Component={TouchableWithoutFeedback} Component={TouchableWithoutFeedback}
switch={{ switch={{
onValueChange: this.onDeleteWalletsAfterUninstallSwitch, onValueChange: onDeleteWalletsAfterUninstallSwitch,
value: this.state.deleteWalletsAfterUninstall, value: deleteWalletsAfterUninstall,
}} }}
/> />
)} )}
{this.state.storageIsEncrypted && ( {storageIsEncrypted && (
<BlueListItem <BlueListItemHooks
onPress={() => this.props.navigation.navigate('PlausibleDeniability')} onPress={navigateToPlausibleDeniability}
disabled={!this.state.storageIsEncrypted}
title={loc.settings.plausible_deniability} title={loc.settings.plausible_deniability}
chevron chevron
testID="PlausibleDeniabilityButton" testID="PlausibleDeniabilityButton"
@ -191,13 +195,10 @@ export default class EncryptStorage extends Component {
</ScrollView> </ScrollView>
</SafeBlueArea> </SafeBlueArea>
); );
}
}
EncryptStorage.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
popToTop: PropTypes.func,
goBack: PropTypes.func,
}),
}; };
export default EncryptStorage;
EncryptStorage.navigationOptions = () => ({
...BlueNavigationStyle(),
headerTitle: 'Security',
});

View file

@ -1,81 +1,59 @@
import React, { Component } from 'react'; import React, { useState, useEffect, useCallback } from 'react';
import { FlatList, StyleSheet } from 'react-native'; import { FlatList, StyleSheet } from 'react-native';
import { BlueLoading, BlueText, SafeBlueArea, BlueListItem, BlueCard, BlueNavigationStyle } from '../../BlueComponents'; import { SafeBlueArea, BlueListItemHooks, BlueCard, BlueLoadingHook, BlueNavigationStyle, BlueTextHooks } from '../../BlueComponents';
import PropTypes from 'prop-types';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import { AvailableLanguages } from '../../loc/languages'; import { AvailableLanguages } from '../../loc/languages';
const loc = require('../../loc'); const loc = require('../../loc');
const Language = () => {
const [isLoading, setIsLoading] = useState(true);
const [language, setLanguage] = useState(loc.getLanguage());
const styles = StyleSheet.create({ const styles = StyleSheet.create({
flex: { flex: {
flex: 1, flex: 1,
}, },
}); });
export default class Language extends Component { useEffect(() => {
static navigationOptions = () => ({ setIsLoading(false);
...BlueNavigationStyle(), }, []);
title: loc.settings.language,
});
constructor(props) { const renderItem = useCallback(
super(props); ({ item }) => {
this.state = {
isLoading: true,
language: loc.getLanguage(),
availableLanguages: AvailableLanguages,
};
}
async componentDidMount() {
this.setState({
isLoading: false,
});
}
renderItem = ({ item }) => {
return ( return (
<BlueListItem <BlueListItemHooks
onPress={() => { onPress={() => {
console.log('setLanguage', item.value); console.log('setLanguage', item.value);
loc.saveLanguage(item.value); loc.saveLanguage(item.value);
return this.setState({ language: item.value }); setLanguage(item.value);
}} }}
title={item.label} title={item.label}
{...(this.state.language === item.value {...(language === item.value
? { ? {
rightIcon: <Icon name="check" type="octaicon" color="#0070FF" />, rightIcon: <Icon name="check" type="octaicon" color="#0070FF" />,
} }
: { hideChevron: true })} : { hideChevron: true })}
/> />
); );
}; },
[language],
);
render() { return isLoading ? (
if (this.state.isLoading) { <BlueLoadingHook />
return <BlueLoading />; ) : (
}
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.flex}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.flex}>
<FlatList <FlatList style={styles.flex} keyExtractor={(_item, index) => `${index}`} data={AvailableLanguages} renderItem={renderItem} />
style={styles.flex}
keyExtractor={(_item, index) => `${index}`}
data={this.state.availableLanguages}
extraData={this.state.availableLanguages}
renderItem={this.renderItem}
/>
<BlueCard> <BlueCard>
<BlueText>When selecting a new language, restarting BlueWallet may be required for the change to take effect.</BlueText> <BlueTextHooks>When selecting a new language, restarting BlueWallet may be required for the change to take effect.</BlueTextHooks>
</BlueCard> </BlueCard>
</SafeBlueArea> </SafeBlueArea>
); );
}
}
Language.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
goBack: PropTypes.func,
}),
}; };
Language.navigationOptions = () => ({
...BlueNavigationStyle(),
headerTitle: loc.settings.language,
});
export default Language;

View file

@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { ScrollView, StyleSheet } from 'react-native'; import { ScrollView, StyleSheet } from 'react-native';
import { BlueLoading, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle, BlueSpacing20 } from '../../BlueComponents'; import { SafeBlueArea, BlueCard, BlueTextHooks, BlueNavigationStyle, BlueSpacing20, BlueLoadingHook } from '../../BlueComponents';
/** @type {AppStorage} */ /** @type {AppStorage} */
const styles = StyleSheet.create({ const styles = StyleSheet.create({
@ -17,34 +17,34 @@ const Licensing = () => {
}, []); }, []);
return isLoading ? ( return isLoading ? (
<BlueLoading /> <BlueLoadingHook />
) : ( ) : (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView> <ScrollView>
<BlueCard> <BlueCard>
<BlueText>MIT License</BlueText> <BlueTextHooks>MIT License</BlueTextHooks>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueText>Copyright (c) 2018-2020 BlueWallet Services</BlueText> <BlueTextHooks>Copyright (c) 2018-2020 BlueWallet Services</BlueTextHooks>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueText> <BlueTextHooks>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
</BlueText> </BlueTextHooks>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueText> <BlueTextHooks>
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
</BlueText> </BlueTextHooks>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueText> <BlueTextHooks>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</BlueText> </BlueTextHooks>
</BlueCard> </BlueCard>
</ScrollView> </ScrollView>
</SafeBlueArea> </SafeBlueArea>

View file

@ -1,14 +1,22 @@
/* global alert */ /* global alert */
import React, { Component } from 'react'; import React, { useState, useEffect, useCallback } from 'react';
import { View, TextInput, Linking, StyleSheet } from 'react-native'; import { View, TextInput, Linking, StyleSheet } from 'react-native';
import { AppStorage } from '../../class'; import { AppStorage } from '../../class';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import { BlueLoading, BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueNavigationStyle, BlueText } from '../../BlueComponents'; import {
import PropTypes from 'prop-types'; BlueSpacing20,
BlueButton,
SafeBlueArea,
BlueCard,
BlueNavigationStyle,
BlueLoadingHook,
BlueTextHooks,
} from '../../BlueComponents';
import { Button } from 'react-native-elements'; import { Button } from 'react-native-elements';
import { LightningCustodianWallet } from '../../class/wallets/lightning-custodian-wallet'; import { LightningCustodianWallet } from '../../class/wallets/lightning-custodian-wallet';
/** @type {AppStorage} */ import { useTheme } from '@react-navigation/native';
const BlueApp = require('../../BlueApp'); import { BlueCurrentTheme } from '../../components/themes';
const loc = require('../../loc'); const loc = require('../../loc');
const styles = StyleSheet.create({ const styles = StyleSheet.create({
@ -17,11 +25,11 @@ const styles = StyleSheet.create({
}, },
uri: { uri: {
flexDirection: 'row', flexDirection: 'row',
borderColor: '#d2d2d2', borderColor: BlueCurrentTheme.colors.formBorder,
borderBottomColor: '#d2d2d2', borderBottomColor: BlueCurrentTheme.colors.formBorder,
borderWidth: 1, borderWidth: 1,
borderBottomWidth: 0.5, borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
minHeight: 44, minHeight: 44,
height: 44, height: 44,
alignItems: 'center', alignItems: 'center',
@ -39,66 +47,52 @@ const styles = StyleSheet.create({
}, },
}); });
export default class LightningSettings extends Component { const LightningSettings = () => {
static navigationOptions = () => ({ const [isLoading, setIsLoading] = useState(true);
...BlueNavigationStyle(), const [URI, setURI] = useState();
title: loc.settings.lightning_settings, const { colors } = useTheme();
});
constructor(props) { useEffect(() => {
super(props); AsyncStorage.getItem(AppStorage.LNDHUB)
this.state = { .then(setURI)
isLoading: true, .then(() => setIsLoading(false))
}; .catch(() => setIsLoading(false));
} }, []);
async componentDidMount() { const save = useCallback(async () => {
const URI = await AsyncStorage.getItem(AppStorage.LNDHUB); setIsLoading(true);
this.setState({
isLoading: false,
URI,
});
}
save = () => {
this.setState({ isLoading: true }, async () => {
this.state.URI = this.state.URI ? this.state.URI : '';
try { try {
if (this.state.URI) { if (URI) {
await LightningCustodianWallet.isValidNodeAddress(this.state.URI); await LightningCustodianWallet.isValidNodeAddress(URI);
// validating only if its not empty. empty means use default // validating only if its not empty. empty means use default
} }
await AsyncStorage.setItem(AppStorage.LNDHUB, this.state.URI); await AsyncStorage.setItem(AppStorage.LNDHUB, URI);
alert('Your changes have been saved successfully'); alert('Your changes have been saved successfully');
} catch (error) { } catch (error) {
alert('Not a valid LndHub URI'); alert('Not a valid LndHub URI');
console.log(error); console.log(error);
} }
this.setState({ isLoading: false }); setIsLoading(false);
}); }, [URI]);
};
render() {
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<BlueCard> <BlueCard>
<BlueText>{loc.settings.lightning_settings_explain}</BlueText> <BlueTextHooks>{loc.settings.lightning_settings_explain}</BlueTextHooks>
</BlueCard> </BlueCard>
<Button <Button
icon={{ icon={{
name: 'github', name: 'github',
type: 'font-awesome', type: 'font-awesome',
color: BlueApp.settings.buttonTextColor, color: colors.foregroundColor,
backgroundColor: '#FFFFFF',
}} }}
onPress={() => { onPress={() => {
Linking.openURL('https://github.com/BlueWallet/LndHub'); Linking.openURL('https://github.com/BlueWallet/LndHub');
}} }}
titleStyle={{ color: BlueApp.settings.buttonAlternativeTextColor }} titleStyle={{ color: colors.buttonAlternativeTextColor }}
title="github.com/BlueWallet/LndHub" title="github.com/BlueWallet/LndHub"
color={BlueApp.settings.buttonTextColor} color={colors.buttonTextColor}
buttonStyle={styles.buttonStyle} buttonStyle={styles.buttonStyle}
/> />
@ -106,27 +100,27 @@ export default class LightningSettings extends Component {
<View style={styles.uri}> <View style={styles.uri}>
<TextInput <TextInput
placeholder={LightningCustodianWallet.defaultBaseUri} placeholder={LightningCustodianWallet.defaultBaseUri}
value={this.state.URI} value={URI}
onChangeText={text => this.setState({ URI: text })} onChangeText={setURI}
numberOfLines={1} numberOfLines={1}
style={styles.uriText} style={styles.uriText}
placeholderTextColor="#81868e" placeholderTextColor="#81868e"
editable={!this.state.isLoading} editable={!isLoading}
textContentType="URL"
autoCapitalize="none"
underlineColorAndroid="transparent" underlineColorAndroid="transparent"
/> />
</View> </View>
<BlueSpacing20 /> <BlueSpacing20 />
{this.state.isLoading ? <BlueLoading /> : <BlueButton onPress={this.save} title={loc.settings.save} />} {isLoading ? <BlueLoadingHook /> : <BlueButton onPress={save} title={loc.settings.save} />}
</BlueCard> </BlueCard>
</SafeBlueArea> </SafeBlueArea>
); );
}
}
LightningSettings.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
goBack: PropTypes.func,
}),
}; };
LightningSettings.navigationOptions = () => ({
...BlueNavigationStyle(),
title: loc.settings.lightning_settings,
});
export default LightningSettings;

View file

@ -1,29 +1,31 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { ScrollView, StyleSheet } from 'react-native'; import { ScrollView, StyleSheet } from 'react-native';
import { BlueLoading, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../../BlueComponents'; import { SafeBlueArea, BlueCard, BlueNavigationStyle, BlueLoadingHook, BlueTextHooks } from '../../BlueComponents';
import { useTheme } from '@react-navigation/native';
/** @type {AppStorage} */ /** @type {AppStorage} */
const styles = StyleSheet.create({
root: {
flex: 1,
},
});
const ReleaseNotes = () => { const ReleaseNotes = () => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const notes = require('../../release-notes'); const notes = require('../../release-notes');
const { colors } = useTheme();
const styles = StyleSheet.create({
root: {
flex: 1,
backgroundColor: colors.background,
},
});
useEffect(() => { useEffect(() => {
setIsLoading(false); setIsLoading(false);
}, []); }, []);
return isLoading ? ( return isLoading ? (
<BlueLoading /> <BlueLoadingHook />
) : ( ) : (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<ScrollView> <ScrollView>
<BlueCard> <BlueCard>
<BlueText>{notes}</BlueText> <BlueTextHooks>{notes}</BlueTextHooks>
</BlueCard> </BlueCard>
</ScrollView> </ScrollView>
</SafeBlueArea> </SafeBlueArea>

View file

@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ScrollView, TouchableOpacity, StyleSheet } from 'react-native'; import { ScrollView, TouchableOpacity, StyleSheet, StatusBar } from 'react-native';
import { BlueNavigationStyle, BlueLoading, SafeBlueArea, BlueHeaderDefaultSub, BlueListItem } from '../../BlueComponents'; import { BlueLoading, BlueListItemHooks, BlueHeaderDefaultSubHooks } from '../../BlueComponents';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
const loc = require('../../loc'); const loc = require('../../loc');
@ -21,21 +21,21 @@ const Settings = () => {
return isLoading ? ( return isLoading ? (
<BlueLoading /> <BlueLoading />
) : ( ) : (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}> <ScrollView style={styles.root}>
<ScrollView> <StatusBar barStyle="default" />
<BlueHeaderDefaultSub leftText={loc.settings.header} rightComponent={null} /> <BlueHeaderDefaultSubHooks leftText={loc.settings.header} rightComponent={null} />
<BlueListItem title="General" component={TouchableOpacity} onPress={() => navigate('GeneralSettings')} chevron /> <BlueListItemHooks title="General" component={TouchableOpacity} onPress={() => navigate('GeneralSettings')} chevron />
<BlueListItem title={loc.settings.currency} component={TouchableOpacity} onPress={() => navigate('Currency')} chevron /> <BlueListItemHooks title={loc.settings.currency} component={TouchableOpacity} onPress={() => navigate('Currency')} chevron />
<BlueListItem title={loc.settings.language} component={TouchableOpacity} onPress={() => navigate('Language')} chevron /> <BlueListItemHooks title={loc.settings.language} component={TouchableOpacity} onPress={() => navigate('Language')} chevron />
<BlueListItem <BlueListItemHooks
title="Security" title="Security"
onPress={() => navigate('EncryptStorage')} onPress={() => navigate('EncryptStorage')}
component={TouchableOpacity} component={TouchableOpacity}
testID="SecurityButton" testID="SecurityButton"
chevron chevron
/> />
<BlueListItem title="Network" component={TouchableOpacity} onPress={() => navigate('NetworkSettings')} chevron /> <BlueListItemHooks title="Network" component={TouchableOpacity} onPress={() => navigate('NetworkSettings')} chevron />
<BlueListItem <BlueListItemHooks
title={loc.settings.about} title={loc.settings.about}
component={TouchableOpacity} component={TouchableOpacity}
onPress={() => navigate('About')} onPress={() => navigate('About')}
@ -43,10 +43,7 @@ const Settings = () => {
chevron chevron
/> />
</ScrollView> </ScrollView>
</SafeBlueArea>
); );
}; };
Settings.navigationOptions = {
...BlueNavigationStyle,
};
export default Settings; export default Settings;

View file

@ -79,11 +79,6 @@ const styles = StyleSheet.create({
}); });
export default class CPFP extends Component { export default class CPFP extends Component {
static navigationOptions = () => ({
...BlueNavigationStyle(null, false),
title: 'Bump fee (CPFP)',
});
constructor(props) { constructor(props) {
super(props); super(props);
let txid; let txid;
@ -276,3 +271,7 @@ CPFP.propTypes = {
}), }),
}), }),
}; };
CPFP.navigationOptions = () => ({
...BlueNavigationStyle(null, false),
title: 'Bump fee (CPFP)',
});

View file

@ -16,11 +16,6 @@ const styles = StyleSheet.create({
}); });
export default class RBFBumpFee extends CPFP { export default class RBFBumpFee extends CPFP {
static navigationOptions = () => ({
...BlueNavigationStyle(null, false),
title: 'Bump fee (RBF)',
});
async componentDidMount() { async componentDidMount() {
console.log('transactions/RBFBumpFee - componentDidMount'); console.log('transactions/RBFBumpFee - componentDidMount');
this.setState({ this.setState({
@ -125,3 +120,8 @@ RBFBumpFee.propTypes = {
}), }),
}), }),
}; };
RBFBumpFee.navigationOptions = () => ({
...BlueNavigationStyle(null, false),
title: 'Bump fee (RBF)',
});

View file

@ -16,11 +16,6 @@ const styles = StyleSheet.create({
}); });
export default class RBFCancel extends CPFP { export default class RBFCancel extends CPFP {
static navigationOptions = () => ({
...BlueNavigationStyle(null, false),
title: 'Cancel this transaction (RBF)',
});
async componentDidMount() { async componentDidMount() {
console.log('transactions/RBFCancel - componentDidMount'); console.log('transactions/RBFCancel - componentDidMount');
this.setState({ this.setState({
@ -130,3 +125,8 @@ RBFCancel.propTypes = {
}), }),
}), }),
}; };
RBFCancel.navigationOptions = () => ({
...BlueNavigationStyle(null, false),
title: 'Cancel this transaction (RBF)',
});

View file

@ -5,7 +5,6 @@ import {
SafeBlueArea, SafeBlueArea,
BlueCard, BlueCard,
BlueText, BlueText,
BlueHeaderDefaultSub,
BlueLoading, BlueLoading,
BlueSpacing20, BlueSpacing20,
BlueCopyToClipboardButton, BlueCopyToClipboardButton,
@ -14,6 +13,7 @@ import {
import HandoffSettings from '../../class/handoff'; import HandoffSettings from '../../class/handoff';
import Handoff from 'react-native-handoff'; import Handoff from 'react-native-handoff';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { BlueCurrentTheme } from '../../components/themes';
/** @type {AppStorage} */ /** @type {AppStorage} */
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
const loc = require('../../loc'); const loc = require('../../loc');
@ -36,6 +36,7 @@ const styles = StyleSheet.create({
fontSize: 16, fontSize: 16,
fontWeight: '500', fontWeight: '500',
marginBottom: 4, marginBottom: 4,
color: BlueCurrentTheme.colors.foregroundColor,
}, },
rowValue: { rowValue: {
marginBottom: 26, marginBottom: 26,
@ -44,6 +45,7 @@ const styles = StyleSheet.create({
txId: { txId: {
fontSize: 16, fontSize: 16,
fontWeight: '500', fontWeight: '500',
color: BlueCurrentTheme.colors.foregroundColor,
}, },
txHash: { txHash: {
marginBottom: 8, marginBottom: 8,
@ -51,16 +53,29 @@ const styles = StyleSheet.create({
}, },
txLink: { txLink: {
marginBottom: 26, marginBottom: 26,
color: '#2f5fb3', color: BlueCurrentTheme.colors.alternativeTextColor2,
}, },
save: { save: {
marginHorizontal: 16, marginHorizontal: 16,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
}, },
saveText: {
color: BlueCurrentTheme.colors.alternativeTextColor2,
},
memoTextInput: { memoTextInput: {
fontSize: 24, flexDirection: 'row',
color: '#2f5fb3', borderColor: BlueCurrentTheme.colors.formBorder,
borderBottomColor: BlueCurrentTheme.colors.formBorder,
borderWidth: 1,
borderBottomWidth: 0.5,
backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
minHeight: 44,
height: 44,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
paddingHorizontal: 8,
}, },
}); });
@ -79,16 +94,6 @@ function arrDiff(a1, a2) {
} }
export default class TransactionsDetails extends Component { export default class TransactionsDetails extends Component {
static navigationOptions = ({ navigation, route }) => ({
...BlueNavigationStyle(),
title: '',
headerRight: () => (
<TouchableOpacity disabled={route.params.isLoading === true} style={styles.save} onPress={route.params.handleOnSaveButtonTapped}>
<Text style={styles.saveText}>{loc.wallets.details.save}</Text>
</TouchableOpacity>
),
});
constructor(props) { constructor(props) {
super(props); super(props);
const hash = props.route.params.hash; const hash = props.route.params.hash;
@ -160,7 +165,6 @@ export default class TransactionsDetails extends Component {
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<StatusBar barStyle="dark-content" />
{this.state.isHandOffUseEnabled && ( {this.state.isHandOffUseEnabled && (
<Handoff <Handoff
title={`Bitcoin Transaction ${this.state.tx.hash}`} title={`Bitcoin Transaction ${this.state.tx.hash}`}
@ -168,7 +172,7 @@ export default class TransactionsDetails extends Component {
url={`https://blockstream.info/tx/${this.state.tx.hash}`} url={`https://blockstream.info/tx/${this.state.tx.hash}`}
/> />
)} )}
<BlueHeaderDefaultSub leftText={loc.transactions.details.title} rightComponent={null} /> <StatusBar barStyle="default" />
<ScrollView style={styles.scroll}> <ScrollView style={styles.scroll}>
<BlueCard> <BlueCard>
<View> <View>
@ -276,3 +280,17 @@ TransactionsDetails.propTypes = {
setParams: PropTypes.func, setParams: PropTypes.func,
}), }),
}; };
TransactionsDetails.navigationOptions = ({ navigation, route }) => ({
...BlueNavigationStyle(),
title: loc.transactions.details.title,
headerStyle: {
...BlueNavigationStyle().headerStyle,
backgroundColor: BlueCurrentTheme.colors.customHeader,
},
headerRight: () => (
<TouchableOpacity disabled={route.params.isLoading === true} style={styles.save} onPress={route.params.handleOnSaveButtonTapped}>
<Text style={styles.saveText}>{loc.wallets.details.save}</Text>
</TouchableOpacity>
),
});

View file

@ -18,6 +18,7 @@ import { BitcoinUnit } from '../../models/bitcoinUnits';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import Handoff from 'react-native-handoff'; import Handoff from 'react-native-handoff';
import HandoffSettings from '../../class/handoff'; import HandoffSettings from '../../class/handoff';
import { BlueCurrentTheme } from '../../components/themes';
/** @type {AppStorage} */ /** @type {AppStorage} */
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
const loc = require('../../loc'); const loc = require('../../loc');
@ -40,12 +41,12 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
}, },
value: { value: {
color: '#2f5fb3', color: BlueCurrentTheme.colors.alternativeTextColor2,
fontSize: 36, fontSize: 36,
fontWeight: '600', fontWeight: '600',
}, },
valueUnit: { valueUnit: {
color: '#2f5fb3', color: BlueCurrentTheme.colors.alternativeTextColor2,
fontSize: 16, fontSize: 16,
fontWeight: '600', fontWeight: '600',
}, },
@ -58,7 +59,7 @@ const styles = StyleSheet.create({
fontSize: 14, fontSize: 14,
}, },
iconRoot: { iconRoot: {
backgroundColor: '#ccddf9', backgroundColor: BlueCurrentTheme.colors.success,
width: 120, width: 120,
height: 120, height: 120,
borderRadius: 60, borderRadius: 60,
@ -94,7 +95,7 @@ const styles = StyleSheet.create({
}, },
confirmations: { confirmations: {
borderRadius: 11, borderRadius: 11,
backgroundColor: '#eef0f4', backgroundColor: BlueCurrentTheme.colors.lightButton,
width: 109, width: 109,
height: 21, height: 21,
alignSelf: 'center', alignSelf: 'center',
@ -132,11 +133,6 @@ const styles = StyleSheet.create({
}); });
export default class TransactionsStatus extends Component { export default class TransactionsStatus extends Component {
static navigationOptions = () => ({
...BlueNavigationStyle(),
title: '',
});
constructor(props) { constructor(props) {
super(props); super(props);
const hash = props.route.params.hash; const hash = props.route.params.hash;
@ -251,7 +247,6 @@ export default class TransactionsStatus extends Component {
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<StatusBar barStyle="dark-content" />
{this.state.isHandOffUseEnabled && ( {this.state.isHandOffUseEnabled && (
<Handoff <Handoff
title={`Bitcoin Transaction ${this.state.tx.hash}`} title={`Bitcoin Transaction ${this.state.tx.hash}`}
@ -259,6 +254,7 @@ export default class TransactionsStatus extends Component {
url={`https://blockstream.info/tx/${this.state.tx.hash}`} url={`https://blockstream.info/tx/${this.state.tx.hash}`}
/> />
)} )}
<StatusBar barStyle="default" />
<View style={styles.container}> <View style={styles.container}>
<BlueCard> <BlueCard>
<View style={styles.center}> <View style={styles.center}>
@ -285,7 +281,7 @@ export default class TransactionsStatus extends Component {
<View style={styles.iconRoot}> <View style={styles.iconRoot}>
<View> <View>
<Icon name="check" size={50} type="font-awesome" color="#0f5cc0" /> <Icon name="check" size={50} type="font-awesome" color={BlueCurrentTheme.colors.successCheck} />
</View> </View>
<View style={[styles.iconWrap, styles.margin]}> <View style={[styles.iconWrap, styles.margin]}>
{(() => { {(() => {
@ -436,3 +432,12 @@ TransactionsStatus.propTypes = {
params: PropTypes.object, params: PropTypes.object,
}), }),
}; };
TransactionsStatus.navigationOptions = () => ({
...BlueNavigationStyle(),
title: '',
headerStyle: {
...BlueNavigationStyle().headerStyle,
backgroundColor: BlueCurrentTheme.colors.customHeader,
},
});

View file

@ -22,14 +22,13 @@ import {
BitcoinButton, BitcoinButton,
BlueFormLabel, BlueFormLabel,
BlueButton, BlueButton,
SafeBlueArea,
BlueNavigationStyle, BlueNavigationStyle,
BlueButtonLink, BlueButtonLink,
BlueSpacing20, BlueSpacing20,
} from '../../BlueComponents'; } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { HDSegwitBech32Wallet, SegwitP2SHWallet, HDSegwitP2SHWallet, LightningCustodianWallet, AppStorage } from '../../class'; import { HDSegwitBech32Wallet, SegwitP2SHWallet, HDSegwitP2SHWallet, LightningCustodianWallet, AppStorage } from '../../class';
import { BlueCurrentTheme } from '../../components/themes';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
const EV = require('../../blue_modules/events'); const EV = require('../../blue_modules/events');
@ -41,14 +40,15 @@ const styles = StyleSheet.create({
loading: { loading: {
flex: 1, flex: 1,
paddingTop: 20, paddingTop: 20,
backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
label: { label: {
flexDirection: 'row', flexDirection: 'row',
borderColor: '#d2d2d2', borderColor: BlueCurrentTheme.colors.formBorder,
borderBottomColor: '#d2d2d2', borderBottomColor: BlueCurrentTheme.colors.formBorder,
borderWidth: 1, borderWidth: 1,
borderBottomWidth: 0.5, borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
minHeight: 44, minHeight: 44,
height: 44, height: 44,
marginHorizontal: 20, marginHorizontal: 20,
@ -86,16 +86,16 @@ const styles = StyleSheet.create({
marginHorizontal: 20, marginHorizontal: 20,
}, },
advancedText: { advancedText: {
color: '#0c2550', color: BlueCurrentTheme.colors.feeText,
fontWeight: '500', fontWeight: '500',
}, },
lndUri: { lndUri: {
flexDirection: 'row', flexDirection: 'row',
borderColor: '#d2d2d2', borderColor: BlueCurrentTheme.colors.formBorder,
borderBottomColor: '#d2d2d2', borderBottomColor: BlueCurrentTheme.colors.formBorder,
borderWidth: 1, borderWidth: 1,
borderBottomWidth: 0.5, borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
minHeight: 44, minHeight: 44,
height: 44, height: 44,
alignItems: 'center', alignItems: 'center',
@ -113,6 +113,10 @@ const styles = StyleSheet.create({
}, },
noPadding: { noPadding: {
paddingHorizontal: 0, paddingHorizontal: 0,
backgroundColor: BlueCurrentTheme.colors.elevated,
},
root: {
backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
}); });
@ -181,9 +185,9 @@ export default class WalletsAdd extends Component {
} }
return ( return (
<SafeBlueArea> <ScrollView style={styles.root}>
<StatusBar barStyle="light-content" /> <StatusBar barStyle="default" />
<ScrollView> <BlueSpacing20 />
<KeyboardAvoidingView enabled behavior={Platform.OS === 'ios' ? 'padding' : null} keyboardVerticalOffset={62}> <KeyboardAvoidingView enabled behavior={Platform.OS === 'ios' ? 'padding' : null} keyboardVerticalOffset={62}>
<BlueFormLabel>{loc.wallets.add.wallet_name}</BlueFormLabel> <BlueFormLabel>{loc.wallets.add.wallet_name}</BlueFormLabel>
<View style={styles.label}> <View style={styles.label}>
@ -425,7 +429,6 @@ export default class WalletsAdd extends Component {
</View> </View>
</KeyboardAvoidingView> </KeyboardAvoidingView>
</ScrollView> </ScrollView>
</SafeBlueArea>
); );
} }
} }

View file

@ -14,12 +14,6 @@ const styles = StyleSheet.create({
}); });
export default class BuyBitcoin extends Component { export default class BuyBitcoin extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: '',
headerLeft: null,
});
constructor(props) { constructor(props) {
super(props); super(props);
const wallet = props.route.params.wallet; const wallet = props.route.params.wallet;
@ -97,7 +91,7 @@ export default class BuyBitcoin extends Component {
return ( return (
<SafeBlueArea style={styles.root}> <SafeBlueArea style={styles.root}>
<StatusBar barStyle="light-content" /> <StatusBar barStyle="default" />
<WebView <WebView
source={{ source={{
uri, uri,
@ -117,3 +111,9 @@ BuyBitcoin.propTypes = {
}), }),
}), }),
}; };
BuyBitcoin.navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: '',
headerLeft: null,
});

View file

@ -16,7 +16,7 @@ import {
StyleSheet, StyleSheet,
StatusBar, StatusBar,
} from 'react-native'; } from 'react-native';
import { BlueButton, SafeBlueArea, BlueCard, BlueSpacing20, BlueNavigationStyle, BlueText } from '../../BlueComponents'; import { SecondButton, SafeBlueArea, BlueCard, BlueSpacing20, BlueNavigationStyle, BlueText } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { LightningCustodianWallet } from '../../class/wallets/lightning-custodian-wallet'; import { LightningCustodianWallet } from '../../class/wallets/lightning-custodian-wallet';
import { HDLegacyBreadwalletWallet } from '../../class/wallets/hd-legacy-breadwallet-wallet'; import { HDLegacyBreadwalletWallet } from '../../class/wallets/hd-legacy-breadwallet-wallet';
@ -26,6 +26,7 @@ import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import Biometric from '../../class/biometrics'; import Biometric from '../../class/biometrics';
import { HDSegwitBech32Wallet, SegwitP2SHWallet, LegacyWallet, SegwitBech32Wallet, WatchOnlyWallet } from '../../class'; import { HDSegwitBech32Wallet, SegwitP2SHWallet, LegacyWallet, SegwitBech32Wallet, WatchOnlyWallet } from '../../class';
import { ScrollView } from 'react-native-gesture-handler'; import { ScrollView } from 'react-native-gesture-handler';
import { BlueCurrentTheme } from '../../components/themes';
const EV = require('../../blue_modules/events'); const EV = require('../../blue_modules/events');
const prompt = require('../../blue_modules/prompt'); const prompt = require('../../blue_modules/prompt');
/** @type {AppStorage} */ /** @type {AppStorage} */
@ -45,36 +46,36 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
}, },
saveText: { saveText: {
color: '#0c2550', color: BlueCurrentTheme.colors.outputValue,
}, },
address: { address: {
alignItems: 'center', alignItems: 'center',
flex: 1, flex: 1,
}, },
textLabel1: { textLabel1: {
color: '#0c2550', color: BlueCurrentTheme.colors.feeText,
fontWeight: '500', fontWeight: '500',
fontSize: 14, fontSize: 14,
marginVertical: 12, marginVertical: 12,
}, },
textLabel2: { textLabel2: {
color: '#0c2550', color: BlueCurrentTheme.colors.feeText,
fontWeight: '500', fontWeight: '500',
fontSize: 14, fontSize: 14,
marginVertical: 16, marginVertical: 16,
}, },
textValue: { textValue: {
color: '#81868e', color: BlueCurrentTheme.colors.outputValue,
fontWeight: '500', fontWeight: '500',
fontSize: 14, fontSize: 14,
}, },
input: { input: {
flexDirection: 'row', flexDirection: 'row',
borderColor: '#d2d2d2', borderColor: BlueCurrentTheme.colors.formBorder,
borderBottomColor: '#d2d2d2', borderBottomColor: BlueCurrentTheme.colors.formBorder,
borderWidth: 1, borderWidth: 1,
borderBottomWidth: 0.5, borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
minHeight: 44, minHeight: 44,
height: 44, height: 44,
alignItems: 'center', alignItems: 'center',
@ -102,24 +103,6 @@ const styles = StyleSheet.create({
}); });
export default class WalletDetails extends Component { export default class WalletDetails extends Component {
static navigationOptions = ({ navigation, route }) => ({
...BlueNavigationStyle(),
title: loc.wallets.details.title,
headerRight: () => (
<TouchableOpacity
disabled={route.params.isLoading === true}
style={styles.save}
onPress={() => {
if (route.params.saveAction) {
route.params.saveAction();
}
}}
>
<Text style={styles.saveText}>{loc.wallets.details.save}</Text>
</TouchableOpacity>
),
});
constructor(props) { constructor(props) {
super(props); super(props);
@ -200,7 +183,7 @@ export default class WalletDetails extends Component {
renderMarketplaceButton = () => { renderMarketplaceButton = () => {
return Platform.select({ return Platform.select({
android: ( android: (
<BlueButton <SecondButton
onPress={() => onPress={() =>
this.props.navigation.navigate('Marketplace', { this.props.navigation.navigate('Marketplace', {
fromWallet: this.state.wallet, fromWallet: this.state.wallet,
@ -210,7 +193,7 @@ export default class WalletDetails extends Component {
/> />
), ),
ios: ( ios: (
<BlueButton <SecondButton
onPress={async () => { onPress={async () => {
Linking.openURL('https://bluewallet.io/marketplace-btc/'); Linking.openURL('https://bluewallet.io/marketplace-btc/');
}} }}
@ -230,7 +213,7 @@ export default class WalletDetails extends Component {
} }
return ( return (
<SafeBlueArea style={styles.root}> <SafeBlueArea style={styles.root}>
<StatusBar barStyle="dark-content" /> <StatusBar barStyle="default" />
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}> <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<KeyboardAvoidingView behavior="position"> <KeyboardAvoidingView behavior="position">
<ScrollView contentContainerStyle={styles.scrollViewContent}> <ScrollView contentContainerStyle={styles.scrollViewContent}>
@ -309,7 +292,7 @@ export default class WalletDetails extends Component {
</> </>
)} )}
<BlueButton <SecondButton
onPress={() => onPress={() =>
this.props.navigation.navigate('WalletExport', { this.props.navigation.navigate('WalletExport', {
wallet: this.state.wallet, wallet: this.state.wallet,
@ -325,7 +308,7 @@ export default class WalletDetails extends Component {
this.state.wallet.type === HDSegwitBech32Wallet.type || this.state.wallet.type === HDSegwitBech32Wallet.type ||
this.state.wallet.type === HDSegwitP2SHWallet.type) && ( this.state.wallet.type === HDSegwitP2SHWallet.type) && (
<> <>
<BlueButton <SecondButton
onPress={() => onPress={() =>
this.props.navigation.navigate('WalletXpub', { this.props.navigation.navigate('WalletXpub', {
secret: this.state.wallet.getSecret(), secret: this.state.wallet.getSecret(),
@ -341,7 +324,7 @@ export default class WalletDetails extends Component {
{this.state.wallet.type !== LightningCustodianWallet.type && ( {this.state.wallet.type !== LightningCustodianWallet.type && (
<> <>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueButton onPress={() => this.props.navigation.navigate('Broadcast')} title="Broadcast transaction" /> <SecondButton onPress={() => this.props.navigation.navigate('Broadcast')} title="Broadcast transaction" />
</> </>
)} )}
<BlueSpacing20 /> <BlueSpacing20 />
@ -397,6 +380,24 @@ export default class WalletDetails extends Component {
} }
} }
WalletDetails.navigationOptions = ({ navigation, route }) => ({
...BlueNavigationStyle(),
title: loc.wallets.details.title,
headerRight: () => (
<TouchableOpacity
disabled={route.params.isLoading === true}
style={styles.save}
onPress={() => {
if (route.params.saveAction) {
route.params.saveAction();
}
}}
>
<Text style={styles.saveText}>{loc.wallets.details.save}</Text>
</TouchableOpacity>
),
});
WalletDetails.propTypes = { WalletDetails.propTypes = {
navigation: PropTypes.shape({ navigation: PropTypes.shape({
state: PropTypes.shape({ state: PropTypes.shape({

View file

@ -6,6 +6,7 @@ import PropTypes from 'prop-types';
import Privacy from '../../Privacy'; import Privacy from '../../Privacy';
import Biometric from '../../class/biometrics'; import Biometric from '../../class/biometrics';
import { LegacyWallet, LightningCustodianWallet, SegwitBech32Wallet, SegwitP2SHWallet, WatchOnlyWallet } from '../../class'; import { LegacyWallet, LightningCustodianWallet, SegwitBech32Wallet, SegwitP2SHWallet, WatchOnlyWallet } from '../../class';
import { BlueCurrentTheme } from '../../components/themes';
/** @type {AppStorage} */ /** @type {AppStorage} */
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
const loc = require('../../loc'); const loc = require('../../loc');
@ -18,6 +19,7 @@ const styles = StyleSheet.create({
}, },
root: { root: {
flex: 1, flex: 1,
backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
scrollViewContent: { scrollViewContent: {
alignItems: 'center', alignItems: 'center',
@ -27,24 +29,18 @@ const styles = StyleSheet.create({
type: { type: {
fontSize: 17, fontSize: 17,
fontWeight: '700', fontWeight: '700',
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
}, },
secret: { secret: {
alignItems: 'center', alignItems: 'center',
paddingHorizontal: 16, paddingHorizontal: 16,
fontSize: 16, fontSize: 16,
color: '#0C2550', color: BlueCurrentTheme.colors.foregroundColor,
lineHeight: 24, lineHeight: 24,
}, },
}); });
export default class WalletExport extends Component { export default class WalletExport extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: loc.wallets.export.title,
headerLeft: null,
});
constructor(props) { constructor(props) {
super(props); super(props);
const wallet = props.route.params.wallet; const wallet = props.route.params.wallet;
@ -118,8 +114,9 @@ export default class WalletExport extends Component {
logo={require('../../img/qr-code.png')} logo={require('../../img/qr-code.png')}
size={this.state.qrCodeHeight} size={this.state.qrCodeHeight}
logoSize={70} logoSize={70}
color={BlueApp.settings.foregroundColor} color={BlueCurrentTheme.colors.foregroundColor}
logoBackgroundColor={BlueApp.settings.brandingColor} logoBackgroundColor={BlueCurrentTheme.colors.brandingColor}
backgroundColor={BlueCurrentTheme.colors.background}
ecl="H" ecl="H"
/> />
@ -147,3 +144,8 @@ WalletExport.propTypes = {
}), }),
}), }),
}; };
WalletExport.navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: loc.wallets.export.title,
headerLeft: null,
});

View file

@ -25,6 +25,7 @@ import Modal from 'react-native-modal';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import { AppStorage } from '../../class'; import { AppStorage } from '../../class';
import * as NavigationService from '../../NavigationService'; import * as NavigationService from '../../NavigationService';
import { BlueCurrentTheme } from '../../components/themes';
const BlueApp: AppStorage = require('../../BlueApp'); const BlueApp: AppStorage = require('../../BlueApp');
const A = require('../../blue_modules/analytics'); const A = require('../../blue_modules/analytics');
@ -38,11 +39,6 @@ export default class HodlHodl extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
props.navigation.setParams({
handleLoginPress: this.handleLoginPress,
displayLoginButton: true,
handleMyContractsPress: this.handleMyContractsPress,
});
this.state = { this.state = {
HodlApi: false, HodlApi: false,
isLoading: true, isLoading: true,
@ -72,7 +68,7 @@ export default class HodlHodl extends Component {
this.setState({ HodlApi, hodlApiKey }); this.setState({ HodlApi, hodlApiKey });
this.props.navigation.setParams({ displayLoginButton }); this.props.navigation.setParams({ displayLoginButton });
}; };
NavigationService.navigate('HodlHodlRoot', { params: { cb: handleLoginCallback }, screen: 'HodlHodlLogin' }); NavigationService.navigate('HodlHodlLoginRoot', { params: { cb: handleLoginCallback }, screen: 'HodlHodlLogin' });
}; };
handleMyContractsPress = () => { handleMyContractsPress = () => {
@ -185,7 +181,11 @@ export default class HodlHodl extends Component {
const HodlApi = new HodlHodlApi(hodlApiKey); const HodlApi = new HodlHodlApi(hodlApiKey);
this.setState({ HodlApi, hodlApiKey }); this.setState({ HodlApi, hodlApiKey });
this.props.navigation.setParams({ displayLoginButton }); this.props.navigation.setParams({
handleLoginPress: this.handleLoginPress,
displayLoginButton: displayLoginButton,
handleMyContractsPress: this.handleMyContractsPress,
});
try { try {
await this.fetchMyCountry(); await this.fetchMyCountry();
@ -204,16 +204,14 @@ export default class HodlHodl extends Component {
this.fetchListOfMethods(); this.fetchListOfMethods();
} }
_onPress(item) { _onPress = item => {
const offers = this.state.offers.filter(value => value.id === item.id); const offers = this.state.offers.filter(value => value.id === item.id);
if (offers && offers[0]) { if (offers && offers[0]) {
NavigationService.navigate('HodlHodlViewOffer', { this.props.navigation.navigate('HodlHodlViewOffer', { offerToDisplay: offers[0] });
offerToDisplay: offers[0],
});
} else { } else {
Linking.openURL('https://hodlhodl.com/offers/' + item.id); Linking.openURL('https://hodlhodl.com/offers/' + item.id);
} }
} };
_onCountryPress(item) { _onCountryPress(item) {
this.setState( this.setState(
@ -716,7 +714,13 @@ export default class HodlHodl extends Component {
<View style={styles.grayTextContainerContainer}> <View style={styles.grayTextContainerContainer}>
<View style={styles.grayTextContainer}> <View style={styles.grayTextContainer}>
<Icon name="place" type="material" size={20} color="#0c2550" containerStyle={styles.paddingLeft10} /> <Icon
name="place"
type="material"
size={20}
color={BlueCurrentTheme.colors.foregroundColor}
containerStyle={styles.paddingLeft10}
/>
{this.state.isLoading ? ( {this.state.isLoading ? (
<ActivityIndicator /> <ActivityIndicator />
) : ( ) : (
@ -732,7 +736,13 @@ export default class HodlHodl extends Component {
> >
<Text style={styles.blueText}>Filters</Text> <Text style={styles.blueText}>Filters</Text>
<Icon name="filter-list" type="material" size={24} color="#2f5fb3" containerStyle={styles.paddingLeft10} /> <Icon
name="filter-list"
type="material"
size={24}
color={BlueCurrentTheme.colors.foregroundColor}
containerStyle={styles.paddingLeft10}
/>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</View> </View>
@ -815,7 +825,7 @@ export default class HodlHodl extends Component {
render() { render() {
return ( return (
<SafeBlueArea> <SafeBlueArea>
<StatusBar barStyle="light-content" /> <StatusBar barStyle="default" />
<SectionList <SectionList
refreshControl={<RefreshControl onRefresh={this._onRefreshOffers} refreshing={this.state.showShowFlatListRefreshControl} />} refreshControl={<RefreshControl onRefresh={this._onRefreshOffers} refreshing={this.state.showShowFlatListRefreshControl} />}
renderItem={this.renderItem} renderItem={this.renderItem}
@ -848,7 +858,11 @@ HodlHodl.propTypes = {
HodlHodl.navigationOptions = ({ navigation, route }) => ({ HodlHodl.navigationOptions = ({ navigation, route }) => ({
...BlueNavigationStyle(navigation, true), ...BlueNavigationStyle(navigation, true),
title: '', title: '',
headerLeft: () => { headerStyle: {
...BlueNavigationStyle(navigation, true).headerStyle,
backgroundColor: BlueCurrentTheme.colors.customHeader,
},
headerRight: () => {
return route.params.displayLoginButton ? ( return route.params.displayLoginButton ? (
<BlueButtonLink title="Login" onPress={route.params.handleLoginPress} style={styles.marginHorizontal20} /> <BlueButtonLink title="Login" onPress={route.params.handleLoginPress} style={styles.marginHorizontal20} />
) : ( ) : (
@ -864,7 +878,7 @@ const styles = StyleSheet.create({
color: '#9AA0AA', color: '#9AA0AA',
}, },
modalContent: { modalContent: {
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.elevated,
padding: 22, padding: 22,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
@ -875,7 +889,7 @@ const styles = StyleSheet.create({
height: 400, height: 400,
}, },
modalContentShort: { modalContentShort: {
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.elevated,
padding: 22, padding: 22,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
@ -892,14 +906,14 @@ const styles = StyleSheet.create({
Title: { Title: {
fontWeight: 'bold', fontWeight: 'bold',
fontSize: 30, fontSize: 30,
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
}, },
BottomLine: { BottomLine: {
fontSize: 10, fontSize: 10,
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
}, },
grayDropdownTextContainer: { grayDropdownTextContainer: {
backgroundColor: '#EEF0F4', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
borderRadius: 20, borderRadius: 20,
height: 35, height: 35,
top: 3, top: 3,
@ -911,7 +925,7 @@ const styles = StyleSheet.create({
flexDirection: 'row', flexDirection: 'row',
}, },
grayTextContainerContainer: { grayTextContainerContainer: {
backgroundColor: '#EEF0F4', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
borderRadius: 20, borderRadius: 20,
height: 44, height: 44,
justifyContent: 'center', justifyContent: 'center',
@ -925,7 +939,7 @@ const styles = StyleSheet.create({
flexDirection: 'row', flexDirection: 'row',
}, },
blueText: { blueText: {
color: '#2f5fb3', color: BlueCurrentTheme.colors.foregroundColor,
fontSize: 15, fontSize: 15,
fontWeight: '600', fontWeight: '600',
}, },
@ -939,17 +953,17 @@ const styles = StyleSheet.create({
locationText: { locationText: {
top: 0, top: 0,
left: 5, left: 5,
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
fontSize: 20, fontSize: 20,
fontWeight: '500', fontWeight: '500',
}, },
nicknameText: { nicknameText: {
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
fontSize: 18, fontSize: 18,
fontWeight: '600', fontWeight: '600',
}, },
blueTextContainer: { blueTextContainer: {
backgroundColor: '#CCDDF9', backgroundColor: BlueCurrentTheme.colors.mainColor,
borderRadius: 20, borderRadius: 20,
width: 110, width: 110,
flex: 1, flex: 1,
@ -963,11 +977,11 @@ const styles = StyleSheet.create({
}, },
searchInputContainer: { searchInputContainer: {
flexDirection: 'row', flexDirection: 'row',
borderColor: '#EEF0F4', borderColor: BlueCurrentTheme.colors.inputBackgroundColor,
borderBottomColor: '#EEF0F4', borderBottomColor: BlueCurrentTheme.colors.inputBackgroundColor,
borderWidth: 1.0, borderWidth: 1.0,
borderBottomWidth: 0.5, borderBottomWidth: 0.5,
backgroundColor: '#EEF0F4', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
minHeight: 48, minHeight: 48,
height: 48, height: 48,
marginHorizontal: 20, marginHorizontal: 20,
@ -997,40 +1011,44 @@ const styles = StyleSheet.create({
itemPrice: { fontWeight: '600', fontSize: 14, color: '#9AA0AA' }, itemPrice: { fontWeight: '600', fontSize: 14, color: '#9AA0AA' },
minmax: { color: '#9AA0AA', fontSize: 12, paddingLeft: 10 }, minmax: { color: '#9AA0AA', fontSize: 12, paddingLeft: 10 },
noOffersWrapper: { height: '100%', justifyContent: 'center' }, noOffersWrapper: { height: '100%', justifyContent: 'center' },
noOffersText: { textAlign: 'center', color: '#9AA0AA', paddingHorizontal: 16 }, noOffersText: { textAlign: 'center', color: BlueCurrentTheme.colors.feeText, paddingHorizontal: 16 },
modalFlatList: { width: '100%' }, modalFlatList: { width: '100%' },
itemSeparator: { height: 0.5, width: '100%', backgroundColor: '#C8C8C8' }, itemSeparator: { height: 0.5, width: '100%', backgroundColor: BlueCurrentTheme.colors.lightBorder },
itemNameWrapper: { backgroundColor: 'white', flex: 1, flexDirection: 'row', paddingTop: 20, paddingBottom: 20 }, itemNameWrapper: { backgroundColor: BlueCurrentTheme.colors.elevated, flex: 1, flexDirection: 'row', paddingTop: 20, paddingBottom: 20 },
itemNameBold: { fontSize: 20, color: '#0c2550', fontWeight: 'bold' }, itemNameBold: { fontSize: 20, color: BlueCurrentTheme.colors.foregroundColor, fontWeight: 'bold' },
itemNameNormal: { fontSize: 20, color: '#0c2550', fontWeight: 'normal' }, itemNameNormal: { fontSize: 20, color: BlueCurrentTheme.colors.foregroundColor, fontWeight: 'normal' },
whiteBackground: { backgroundColor: 'white' }, whiteBackground: { backgroundColor: BlueCurrentTheme.colors.background },
filterCurrencyText: { fontSize: 16, color: '#9AA0AA' }, filterCurrencyText: { fontSize: 16, color: BlueCurrentTheme.colors.foregroundColor },
filteCurrencyTextWrapper: { color: '#9AA0AA', right: 0, position: 'absolute' }, filteCurrencyTextWrapper: { color: BlueCurrentTheme.colors.foregroundColor, right: 0, position: 'absolute' },
currencyNativeName: { fontSize: 20, color: '#0c2550' }, currencyNativeName: { fontSize: 20, color: BlueCurrentTheme.colors.foregroundColor },
currencyWrapper: { paddingLeft: 10, flex: 1, flexDirection: 'row' }, currencyWrapper: { paddingLeft: 10, flex: 1, flexDirection: 'row' },
methodNameText: { fontSize: 16, color: '#9AA0AA' }, methodNameText: { fontSize: 16, color: BlueCurrentTheme.colors.foregroundColor },
searchTextInput: { fontSize: 17, flex: 1, marginHorizontal: 8, minHeight: 33, paddingLeft: 6, paddingRight: 6, color: '#81868e' }, searchTextInput: { fontSize: 17, flex: 1, marginHorizontal: 8, minHeight: 33, paddingLeft: 6, paddingRight: 6, color: '#81868e' },
iconWithOffset: { left: -10 }, iconWithOffset: { left: -10 },
paddingLeft10: { paddingLeft: 10 }, paddingLeft10: { paddingLeft: 10 },
countryNativeNameBold: { fontSize: 20, color: '#0c2550', fontWeight: 'bold' }, countryNativeNameBold: { fontSize: 20, color: BlueCurrentTheme.colors.foregroundColor, fontWeight: 'bold' },
countryNativeNameNormal: { fontSize: 20, color: '#0c2550', fontWeight: 'normal' }, countryNativeNameNormal: { fontSize: 20, color: BlueCurrentTheme.colors.foregroundColor, fontWeight: 'normal' },
curSearchInput: { flex: 1, marginHorizontal: 8, minHeight: 33, paddingLeft: 6, paddingRight: 6, color: '#81868e' }, curSearchInput: { flex: 1, marginHorizontal: 8, minHeight: 33, paddingLeft: 6, paddingRight: 6, color: '#81868e' },
mthdSearchInput: { flex: 1, marginHorizontal: 8, minHeight: 33, paddingLeft: 6, paddingRight: 6, color: '#81868e' }, mthdSearchInput: { flex: 1, marginHorizontal: 8, minHeight: 33, paddingLeft: 6, paddingRight: 6, color: '#81868e' },
currencyTextBold: { currencyTextBold: {
fontSize: 20, fontSize: 20,
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
fontWeight: 'bold', fontWeight: 'bold',
}, },
currencyTextNormal: { currencyTextNormal: {
fontSize: 20, fontSize: 20,
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
fontWeight: 'normal', fontWeight: 'normal',
}, },
currencyText: {
fontSize: 20,
color: BlueCurrentTheme.colors.foregroundColor,
},
noPaddingLeftOrRight: { paddingLeft: 0, paddingRight: 0 }, noPaddingLeftOrRight: { paddingLeft: 0, paddingRight: 0 },
flexRow: { flexDirection: 'row' }, flexRow: { flexDirection: 'row' },
traderRatingText2: { color: '#9AA0AA' }, traderRatingText2: { color: '#9AA0AA' },
itemPriceWrapper: { itemPriceWrapper: {
backgroundColor: '#EEF0F4', backgroundColor: BlueCurrentTheme.colors.lightButton,
borderRadius: 20, borderRadius: 20,
paddingLeft: 8, paddingLeft: 8,
paddingRight: 8, paddingRight: 8,
@ -1043,8 +1061,8 @@ const styles = StyleSheet.create({
offersSectionList: { marginTop: 24, flex: 1 }, offersSectionList: { marginTop: 24, flex: 1 },
marginHorizontal20: { marginHorizontal: 20 }, marginHorizontal20: { marginHorizontal: 20 },
avatarImage: { width: 40, height: 40, borderRadius: 40 }, avatarImage: { width: 40, height: 40, borderRadius: 40 },
avatarWrapper: { backgroundColor: 'white', flex: 1, flexDirection: 'row' }, avatarWrapper: { backgroundColor: BlueCurrentTheme.colors.background, flex: 1, flexDirection: 'row' },
avatarWrapperWrapper: { backgroundColor: 'white', paddingTop: 16, paddingBottom: 16 }, avatarWrapperWrapper: { backgroundColor: BlueCurrentTheme.colors.background, paddingTop: 16, paddingBottom: 16 },
headerWrapper: { marginHorizontal: 20, marginBottom: 8 }, headerWrapper: { backgroundColor: BlueCurrentTheme.colors.background, marginHorizontal: 20, marginBottom: 8 },
verifiedIcon: { marginTop: 5, marginRight: 5 }, verifiedIcon: { marginTop: 5, marginRight: 5 },
}); });

View file

@ -1,7 +1,7 @@
import React, { Component } from 'react'; import React, { useRef } from 'react';
import { WebView } from 'react-native-webview'; import { WebView } from 'react-native-webview';
import { BlueNavigationStyle, SafeBlueArea } from '../../BlueComponents'; import { BlueNavigationStyle, SafeBlueArea } from '../../BlueComponents';
import PropTypes from 'prop-types'; import { useRoute, useNavigation } from '@react-navigation/native';
const url = 'https://accounts.hodlhodl.com/accounts/request_access?attributes=api_key,api_signature_key'; const url = 'https://accounts.hodlhodl.com/accounts/request_access?attributes=api_key,api_signature_key';
@ -15,28 +15,17 @@ const INJECTED_JAVASCRIPT = `(function() {
})();`; })();`;
export default class HodlHodlLogin extends Component { const HodlHodlLogin = () => {
static navigationOptions = ({ navigation }) => ({ const webView = useRef();
...BlueNavigationStyle(navigation, true), const { cb } = useRoute().params;
title: 'Login', const navigation = useNavigation();
headerLeft: null,
});
constructor(props) {
super(props);
this.state = {
url: url,
};
}
render() {
return ( return (
<SafeBlueArea> <SafeBlueArea>
<WebView <WebView
injectedJavaScript={INJECTED_JAVASCRIPT} injectedJavaScript={INJECTED_JAVASCRIPT}
ref={ref => (this.webview = ref)} ref={webView}
source={{ uri: this.state.url }} source={{ uri: url }}
onMessage={e => { onMessage={e => {
// this is a handler which receives messages sent from within the browser // this is a handler which receives messages sent from within the browser
@ -51,25 +40,19 @@ export default class HodlHodlLogin extends Component {
} catch (_) {} } catch (_) {}
if (json && json.allowed && json.data && json.data.api_key) { if (json && json.allowed && json.data && json.data.api_key) {
this.props.route.params.cb(json.data.api_key, json.data.api_signature_key); cb(json.data.api_key, json.data.api_signature_key);
this.props.navigation.pop(); navigation.dangerouslyGetParent().pop();
} }
}} }}
/> />
</SafeBlueArea> </SafeBlueArea>
); );
}
}
HodlHodlLogin.propTypes = {
route: PropTypes.shape({
params: PropTypes.shape({
cb: PropTypes.func.isRequired,
}),
}),
navigation: PropTypes.shape({
getParam: PropTypes.func,
navigate: PropTypes.func,
pop: PropTypes.func,
}),
}; };
HodlHodlLogin.navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: 'Login',
headerLeft: null,
});
export default HodlHodlLogin;

View file

@ -19,22 +19,16 @@ import {
BlueNavigationStyle, BlueNavigationStyle,
BlueSpacing10, BlueSpacing10,
BlueSpacing20, BlueSpacing20,
SafeBlueArea,
} from '../../BlueComponents'; } from '../../BlueComponents';
import { AppStorage } from '../../class'; import { AppStorage } from '../../class';
import { HodlHodlApi } from '../../class/hodl-hodl-api'; import { HodlHodlApi } from '../../class/hodl-hodl-api';
import Modal from 'react-native-modal'; import Modal from 'react-native-modal';
import * as NavigationService from '../../NavigationService'; import * as NavigationService from '../../NavigationService';
import { BlueCurrentTheme } from '../../components/themes';
const BlueApp: AppStorage = require('../../BlueApp'); const BlueApp: AppStorage = require('../../BlueApp');
export default class HodlHodlMyContracts extends Component { export default class HodlHodlMyContracts extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: 'My contracts',
headerLeft: null,
});
constructor(props) { constructor(props) {
super(props); super(props);
@ -64,13 +58,13 @@ export default class HodlHodlMyContracts extends Component {
render() { render() {
if (this.state.isLoading) return <BlueLoading />; if (this.state.isLoading) return <BlueLoading />;
return ( return (
<SafeBlueArea> <View style={styles.root}>
<FlatList <FlatList
scrollEnabled={false} scrollEnabled={false}
keyExtractor={(item, index) => { keyExtractor={(item, index) => {
return item.id; return item.id;
}} }}
ListEmptyComponent={() => <Text style={styles.emptyComponentText}>You dont have any contracts in progress</Text>} ListEmptyComponent={() => <Text style={styles.emptyComponentText}>You don't have any contracts in progress</Text>}
style={styles.flatList} style={styles.flatList}
ItemSeparatorComponent={() => <View style={styles.itemSeparatorComponent} />} ItemSeparatorComponent={() => <View style={styles.itemSeparatorComponent} />}
data={this.state.contracts} data={this.state.contracts}
@ -104,7 +98,7 @@ export default class HodlHodlMyContracts extends Component {
)} )}
/> />
{this.renderContract()} {this.renderContract()}
</SafeBlueArea> </View>
); );
} }
@ -346,12 +340,16 @@ export default class HodlHodlMyContracts extends Component {
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
root: {
flex: 1,
backgroundColor: BlueCurrentTheme.colors.elevated,
},
bottomModal: { bottomModal: {
justifyContent: 'flex-end', justifyContent: 'flex-end',
margin: 0, margin: 0,
}, },
modalContent: { modalContent: {
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.modal,
padding: 22, padding: 22,
borderTopLeftRadius: 16, borderTopLeftRadius: 16,
borderTopRightRadius: 16, borderTopRightRadius: 16,
@ -363,7 +361,7 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
}, },
statusGreenWrapper: { statusGreenWrapper: {
backgroundColor: '#d2f8d5', backgroundColor: BlueCurrentTheme.colors.feeLabel,
borderRadius: 20, borderRadius: 20,
height: 28, height: 28,
justifyContent: 'center', justifyContent: 'center',
@ -374,10 +372,10 @@ const styles = StyleSheet.create({
}, },
statusGreenText: { statusGreenText: {
fontSize: 12, fontSize: 12,
color: '#37bfa0', color: BlueCurrentTheme.colors.feeValue,
}, },
statusGrayWrapper: { statusGrayWrapper: {
backgroundColor: '#ebebeb', backgroundColor: BlueCurrentTheme.colors.lightBorder,
borderRadius: 20, borderRadius: 20,
height: 28, height: 28,
justifyContent: 'center', justifyContent: 'center',
@ -388,10 +386,10 @@ const styles = StyleSheet.create({
}, },
statusGrayText: { statusGrayText: {
fontSize: 12, fontSize: 12,
color: 'gray', color: '#9AA0AA',
}, },
statusGrayWrapper2: { statusGrayWrapper2: {
backgroundColor: '#f8f8f8', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
borderRadius: 5, borderRadius: 5,
minHeight: 28, minHeight: 28,
maxHeight: 56, maxHeight: 56,
@ -402,26 +400,36 @@ const styles = StyleSheet.create({
}, },
statusGrayText2: { statusGrayText2: {
fontSize: 12, fontSize: 12,
color: 'gray', color: '#9AA0AA',
}, },
btcText: { btcText: {
fontWeight: 'bold', fontWeight: 'bold',
fontSize: 18, fontSize: 18,
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
}, },
subheaderText: { subheaderText: {
fontSize: 12, fontSize: 12,
fontWeight: 'bold', fontWeight: 'bold',
color: '#0c2550', color: BlueCurrentTheme.colors.feeText,
}, },
emptyComponentText: { textAlign: 'center', color: '#9AA0AA', paddingHorizontal: 16 }, loading: { backgroundColor: BlueCurrentTheme.colors.elevated },
emptyComponentText: { textAlign: 'center', color: '#9AA0AA', paddingHorizontal: 16, backgroundColor: BlueCurrentTheme.colors.elevated },
itemSeparatorComponent: { height: 0.5, width: '100%', backgroundColor: '#C8C8C8' }, itemSeparatorComponent: { height: 0.5, width: '100%', backgroundColor: '#C8C8C8' },
flexDirectionRow: { flexDirection: 'row' }, flexDirectionRow: { flexDirection: 'row' },
flexDirectionColumn: { flexDirection: 'column' }, flexDirectionColumn: { flexDirection: 'column' },
volumeBreakdownText: { fontSize: 18, color: '#0c2550' }, volumeBreakdownText: { fontSize: 18, color: BlueCurrentTheme.colors.foregroundColor },
contractStatusText: { fontSize: 14, color: 'gray', fontWeight: 'normal' }, contractStatusText: { fontSize: 13, color: 'gray', fontWeight: 'normal' },
cancelContractText: { color: '#d0021b', fontSize: 15, paddingTop: 20, fontWeight: '500', textAlign: 'center' }, cancelContractText: { color: '#d0021b', fontSize: 15, paddingTop: 20, fontWeight: '500', textAlign: 'center' },
openChatText: { color: '#1b02d0', fontSize: 15, paddingTop: 20, fontWeight: '500', textAlign: 'center' }, openChatText: { color: BlueCurrentTheme.colors.foregroundColor, fontSize: 15, paddingTop: 20, fontWeight: '500', textAlign: 'center' },
flatList: { paddingTop: 30 }, flatList: { paddingTop: 30, backgroundColor: BlueCurrentTheme.colors.elevated },
roleText: { fontSize: 14, color: 'gray', padding: 5 }, roleText: { fontSize: 14, color: 'gray', padding: 5 },
}); });
HodlHodlMyContracts.navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: 'My contracts',
headerStyle: {
backgroundColor: BlueCurrentTheme.colors.elevated,
},
headerRight: null,
});

View file

@ -7,16 +7,12 @@ import { HodlHodlApi } from '../../class/hodl-hodl-api';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import { AppStorage } from '../../class'; import { AppStorage } from '../../class';
import * as NavigationService from '../../NavigationService'; import * as NavigationService from '../../NavigationService';
import { BlueCurrentTheme } from '../../components/themes';
const BlueApp: AppStorage = require('../../BlueApp'); const BlueApp: AppStorage = require('../../BlueApp');
const prompt = require('../../blue_modules/prompt'); const prompt = require('../../blue_modules/prompt');
export default class HodlHodlViewOffer extends Component { export default class HodlHodlViewOffer extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(),
title: '',
});
constructor(props) { constructor(props) {
super(props); super(props);
@ -75,7 +71,7 @@ export default class HodlHodlViewOffer extends Component {
const HodlApi = new HodlHodlApi(hodlApiKey); const HodlApi = new HodlHodlApi(hodlApiKey);
this.setState({ HodlApi, hodlApiKey }); this.setState({ HodlApi, hodlApiKey });
}; };
NavigationService.navigate('HodlHodlRoot', { params: { cb: handleLoginCallback }, screen: 'HodlHodlLogin' }); NavigationService.navigate('HodlHodl', { params: { cb: handleLoginCallback }, screen: 'HodlHodlLogin' });
}; };
async _onAcceptOfferPress(offer) { async _onAcceptOfferPress(offer) {
@ -269,19 +265,19 @@ HodlHodlViewOffer.propTypes = {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
modalContent: { modalContent: {
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.background,
padding: 22, padding: 22,
}, },
Title: { Title: {
fontWeight: '600', fontWeight: '600',
fontSize: 24, fontSize: 24,
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
}, },
circleWhite: { circleWhite: {
position: 'absolute', position: 'absolute',
bottom: 0, bottom: 0,
right: 3, right: 3,
backgroundColor: 'white', backgroundColor: BlueCurrentTheme.colors.background,
width: 13, width: 13,
height: 13, height: 13,
borderRadius: 6, borderRadius: 6,
@ -296,7 +292,7 @@ const styles = StyleSheet.create({
borderRadius: 5, borderRadius: 5,
}, },
grayTextContainerContainer: { grayTextContainerContainer: {
backgroundColor: '#EEF0F4', backgroundColor: BlueCurrentTheme.colors.lightButton,
borderRadius: 20, borderRadius: 20,
height: 30, height: 30,
justifyContent: 'center', justifyContent: 'center',
@ -306,7 +302,7 @@ const styles = StyleSheet.create({
paddingRight: 20, paddingRight: 20,
}, },
greenTextContainerContainer: { greenTextContainerContainer: {
backgroundColor: '#d2f8d5', backgroundColor: BlueCurrentTheme.colors.feeLabel,
borderRadius: 20, borderRadius: 20,
height: 30, height: 30,
justifyContent: 'center', justifyContent: 'center',
@ -323,7 +319,7 @@ const styles = StyleSheet.create({
}, },
priceText: { priceText: {
top: 0, top: 0,
color: '#37bfa0', color: BlueCurrentTheme.colors.feeValue,
fontSize: 14, fontSize: 14,
fontWeight: '500', fontWeight: '500',
}, },
@ -338,7 +334,7 @@ const styles = StyleSheet.create({
lineHeight: 23, lineHeight: 23,
}, },
nicknameText: { nicknameText: {
color: '#0c2550', color: BlueCurrentTheme.colors.foregroundColor,
fontSize: 16, fontSize: 16,
fontWeight: 'bold', fontWeight: 'bold',
}, },
@ -349,20 +345,35 @@ const styles = StyleSheet.create({
locationText: { locationText: {
color: '#9BA0A9', color: '#9BA0A9',
}, },
horizontalScrollIemHeader: { fontSize: 12, color: '#9AA0AA' }, horizontalScrollIemHeader: { color: BlueCurrentTheme.colors.feeText },
horizontalScrollItemBody: { fontSize: 14, fontWeight: 'bold', color: '#0c2550' }, horizontalScrollItemBody: { fontSize: 14, fontWeight: 'bold', color: BlueCurrentTheme.colors.foregroundColor },
horizontalScrollWrapper: { flexDirection: 'column', paddingTop: 20, paddingBottom: 20, paddingRight: 40 }, horizontalScrollWrapper: { flexDirection: 'column', paddingTop: 20, paddingBottom: 20, paddingRight: 40 },
flexDirRow: { flexDirection: 'row' }, flexDirRow: { flexDirection: 'row' },
iconWithPadding: { paddingLeft: 16 }, iconWithPadding: { paddingLeft: 16 },
_hr: { _hr: {
borderWidth: 0, borderWidth: 0,
borderBottomWidth: 1, borderBottomWidth: 1,
borderColor: '#ebebeb', borderColor: BlueCurrentTheme.colors.lightBorder,
}, },
avatarImg: { width: 60, height: 60, borderRadius: 60 }, avatarImg: { width: 60, height: 60, borderRadius: 60 },
avatarWrapper: { backgroundColor: 'white', flex: 1, flexDirection: 'column', alignItems: 'center', marginTop: 32 }, avatarWrapper: {
backgroundColor: BlueCurrentTheme.colors.background,
flex: 1,
flexDirection: 'column',
alignItems: 'center',
marginTop: 32,
},
verifiedIcon: { marginTop: 3, marginRight: 5 }, verifiedIcon: { marginTop: 3, marginRight: 5 },
traderWrapper: { alignItems: 'center', marginTop: 8 }, traderWrapper: { alignItems: 'center', marginTop: 8 },
acceptOfferButtonWrapper: { width: '70%', alignItems: 'center' }, acceptOfferButtonWrapper: { width: '70%', alignItems: 'center' },
acceptOfferButtonWrapperWrapper: { marginTop: 24, alignItems: 'center' }, acceptOfferButtonWrapperWrapper: { marginTop: 24, alignItems: 'center' },
}); });
HodlHodlViewOffer.navigationOptions = () => ({
...BlueNavigationStyle(),
title: '',
headerStyle: {
...BlueNavigationStyle().headerStyle,
backgroundColor: BlueCurrentTheme.colors.customHeader,
},
});

View file

@ -4,12 +4,6 @@ import { BlueNavigationStyle, SafeBlueArea } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
export default class HodlHodlWebview extends Component { export default class HodlHodlWebview extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: '',
headerLeft: null,
});
constructor(props) { constructor(props) {
super(props); super(props);
@ -36,3 +30,9 @@ HodlHodlWebview.propTypes = {
}), }),
}), }),
}; };
HodlHodlWebview.navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: '',
headerLeft: null,
});

View file

@ -13,28 +13,30 @@ import {
} from '../../BlueComponents'; } from '../../BlueComponents';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import Privacy from '../../Privacy'; import Privacy from '../../Privacy';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
import WalletImport from '../../class/wallet-import'; import WalletImport from '../../class/wallet-import';
const loc = require('../../loc'); const loc = require('../../loc');
const { width } = Dimensions.get('window'); const { width } = Dimensions.get('window');
const styles = StyleSheet.create({
root: {
flex: 1,
paddingTop: 40,
},
center: {
flex: 1,
alignItems: 'center',
},
});
const WalletsImport = () => { const WalletsImport = () => {
const [isToolbarVisibleForAndroid, setIsToolbarVisibleForAndroid] = useState(false); const [isToolbarVisibleForAndroid, setIsToolbarVisibleForAndroid] = useState(false);
const route = useRoute(); const route = useRoute();
const label = (route.params && route.params.label) || ''; const label = (route.params && route.params.label) || '';
const [importText, setImportText] = useState(label); const [importText, setImportText] = useState(label);
const navigation = useNavigation(); const navigation = useNavigation();
const { colors } = useTheme();
const styles = StyleSheet.create({
root: {
flex: 1,
paddingTop: 40,
backgroundColor: colors.elevated,
},
center: {
flex: 1,
alignItems: 'center',
backgroundColor: colors.elevated,
},
});
useEffect(() => { useEffect(() => {
Privacy.enableBlur(); Privacy.enableBlur();
@ -92,8 +94,8 @@ const WalletsImport = () => {
return ( return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}> <SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
<StatusBar barStyle="light-content" /> <StatusBar barStyle="default" />
<BlueSpacing20 />
<BlueFormLabel>{loc.wallets.import.explanation}</BlueFormLabel> <BlueFormLabel>{loc.wallets.import.explanation}</BlueFormLabel>
<BlueSpacing20 /> <BlueSpacing20 />
<BlueFormMultiInput <BlueFormMultiInput
@ -148,8 +150,8 @@ const WalletsImport = () => {
); );
}; };
WalletsImport.navigationOptions = { WalletsImport.navigationOptions = ({ navigation, route }) => ({
...BlueNavigationStyle(), ...BlueNavigationStyle(),
title: loc.wallets.import.title, title: loc.wallets.import.title,
}; });
export default WalletsImport; export default WalletsImport;

View file

@ -23,6 +23,7 @@ import WalletImport from '../../class/wallet-import';
import ActionSheet from '../ActionSheet'; import ActionSheet from '../ActionSheet';
import ImagePicker from 'react-native-image-picker'; import ImagePicker from 'react-native-image-picker';
import * as NavigationService from '../../NavigationService'; import * as NavigationService from '../../NavigationService';
import { BlueCurrentTheme } from '../../components/themes';
const EV = require('../../blue_modules/events'); const EV = require('../../blue_modules/events');
const A = require('../../blue_modules/analytics'); const A = require('../../blue_modules/analytics');
const BlueApp: AppStorage = require('../../BlueApp'); const BlueApp: AppStorage = require('../../BlueApp');
@ -33,18 +34,6 @@ const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
const WalletsListSections = { CAROUSEL: 'CAROUSEL', LOCALTRADER: 'LOCALTRADER', TRANSACTIONS: 'TRANSACTIONS' }; const WalletsListSections = { CAROUSEL: 'CAROUSEL', LOCALTRADER: 'LOCALTRADER', TRANSACTIONS: 'TRANSACTIONS' };
export default class WalletsList extends Component { export default class WalletsList extends Component {
static navigationOptions = ({ navigation, route }) => {
return {
...BlueNavigationStyle(navigation, true),
title: '',
headerRight: () => (
<TouchableOpacity testID="SettingsButton" style={styles.headerTouch} onPress={() => NavigationService.navigate('Settings')}>
<Icon size={22} name="kebab-horizontal" type="octicon" color={BlueApp.settings.foregroundColor} />
</TouchableOpacity>
),
};
};
walletsCarousel = React.createRef(); walletsCarousel = React.createRef();
constructor(props) { constructor(props) {
@ -289,7 +278,7 @@ export default class WalletsList extends Component {
renderListHeaderComponent = () => { renderListHeaderComponent = () => {
return ( return (
<View style={styles.listHeader}> <View style={styles.listHeaderBack}>
<Text style={styles.listHeaderText}>{loc.transactions.list.title}</Text> <Text style={styles.listHeaderText}>{loc.transactions.list.title}</Text>
</View> </View>
); );
@ -316,7 +305,7 @@ export default class WalletsList extends Component {
return ( return (
<TouchableOpacity <TouchableOpacity
onPress={() => { onPress={() => {
this.props.navigation.navigate('HodlHodlRoot', { params: { wallet: this.state.wallet }, screen: 'HodlHodl' }); this.props.navigation.navigate('HodlHodl', { params: { wallet: this.state.wallet }, screen: 'HodlHodl' });
}} }}
style={styles.ltRoot} style={styles.ltRoot}
> >
@ -527,7 +516,7 @@ export default class WalletsList extends Component {
render() { render() {
return ( return (
<View style={styles.root}> <View style={styles.root}>
<StatusBar barStyle="dark-content" /> <StatusBar barStyle="default" />
<View style={styles.walletsListWrapper}> <View style={styles.walletsListWrapper}>
<SectionList <SectionList
refreshControl={<RefreshControl onRefresh={this.refreshTransactions} refreshing={!this.state.isFlatListRefreshControlHidden} />} refreshControl={<RefreshControl onRefresh={this.refreshTransactions} refreshing={!this.state.isFlatListRefreshControlHidden} />}
@ -561,12 +550,12 @@ const styles = StyleSheet.create({
right: 0, right: 0,
}, },
wrapper: { wrapper: {
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.brandingColor,
flex: 1, flex: 1,
}, },
walletsListWrapper: { walletsListWrapper: {
flex: 1, flex: 1,
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.brandingColor,
}, },
headerStyle: { headerStyle: {
...Platform.select({ ...Platform.select({
@ -595,7 +584,7 @@ const styles = StyleSheet.create({
fontWeight: 'bold', fontWeight: 'bold',
fontSize: 24, fontSize: 24,
marginVertical: 8, marginVertical: 8,
color: BlueApp.settings.foregroundColor, color: BlueCurrentTheme.colors.foregroundColor,
}, },
ltRoot: { ltRoot: {
flexDirection: 'row', flexDirection: 'row',
@ -603,7 +592,7 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
marginHorizontal: 16, marginHorizontal: 16,
marginVertical: 16, marginVertical: 16,
backgroundColor: '#eef0f4', backgroundColor: BlueCurrentTheme.colors.ballOutgoingExpired,
padding: 16, padding: 16,
borderRadius: 6, borderRadius: 6,
}, },
@ -613,12 +602,12 @@ const styles = StyleSheet.create({
ltTextBig: { ltTextBig: {
fontSize: 16, fontSize: 16,
fontWeight: '600', fontWeight: '600',
color: '#0C2550', color: BlueCurrentTheme.colors.foregroundColor,
}, },
ltTextSmall: { ltTextSmall: {
fontSize: 13, fontSize: 13,
fontWeight: '500', fontWeight: '500',
color: '#9AA0AA', color: BlueCurrentTheme.colors.alternativeTextColor,
}, },
ltButtonWrap: { ltButtonWrap: {
flexDirection: 'column', flexDirection: 'column',
@ -676,3 +665,22 @@ WalletsList.propTypes = {
params: PropTypes.object, params: PropTypes.object,
}), }),
}; };
WalletsList.navigationOptions = ({ navigation, route }) => {
return {
...BlueNavigationStyle(navigation, true),
title: '',
headerStyle: {
backgroundColor: BlueCurrentTheme.colors.customHeader,
borderBottomWidth: 0,
elevation: 0,
shadowOpacity: 0,
shadowOffset: { height: 0, width: 0 },
},
headerRight: () => (
<TouchableOpacity testID="SettingsButton" style={styles.headerTouch} onPress={() => NavigationService.navigate('Settings')}>
<Icon size={22} name="kebab-horizontal" type="octicon" color={BlueCurrentTheme.colors.foregroundColor} />
</TouchableOpacity>
),
};
};

View file

@ -5,12 +5,6 @@ import { BlueLoading, BlueNavigationStyle } from '../../BlueComponents';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
export default class Marketplace extends Component { export default class Marketplace extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: 'Marketplace',
headerLeft: null,
});
webview = React.createRef(); webview = React.createRef();
constructor(props) { constructor(props) {
@ -80,3 +74,9 @@ Marketplace.propTypes = {
params: PropTypes.object, params: PropTypes.object,
}), }),
}; };
Marketplace.navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: 'Marketplace',
headerLeft: null,
});

View file

@ -1,13 +1,21 @@
import React, { useEffect, useState, useCallback } from 'react'; import React, { useEffect, useState, useCallback } from 'react';
import { ActivityIndicator, View, BackHandler, Text, ScrollView, StyleSheet, StatusBar } from 'react-native'; import { ActivityIndicator, View, BackHandler, Text, ScrollView, StyleSheet, StatusBar } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
import { BlueSpacing20, SafeBlueArea, BlueNavigationStyle, BlueText, BlueButton } from '../../BlueComponents'; import { BlueSpacing20, SafeBlueArea, BlueNavigationStyle, BlueText, BlueButton } from '../../BlueComponents';
import Privacy from '../../Privacy'; import Privacy from '../../Privacy';
const loc = require('../../loc'); const loc = require('../../loc');
const PleaseBackup = () => {
const [isLoading, setIsLoading] = useState(true);
const route = useRoute();
const words = route.params.secret.split(' ');
const navigation = useNavigation();
const { colors } = useTheme();
const styles = StyleSheet.create({ const styles = StyleSheet.create({
flex: { flex: {
flex: 1, flex: 1,
backgroundColor: colors.elevated,
}, },
loading: { loading: {
flex: 1, flex: 1,
@ -17,7 +25,7 @@ const styles = StyleSheet.create({
width: 'auto', width: 'auto',
marginRight: 8, marginRight: 8,
marginBottom: 8, marginBottom: 8,
backgroundColor: '#f5f5f5', backgroundColor: colors.inputBackgroundColor,
paddingTop: 6, paddingTop: 6,
paddingBottom: 6, paddingBottom: 6,
paddingLeft: 8, paddingLeft: 8,
@ -25,7 +33,7 @@ const styles = StyleSheet.create({
borderRadius: 4, borderRadius: 4,
}, },
wortText: { wortText: {
color: '#81868E', color: colors.labelText,
fontWeight: 'bold', fontWeight: 'bold',
}, },
scrollViewContent: { scrollViewContent: {
@ -38,13 +46,13 @@ const styles = StyleSheet.create({
successText: { successText: {
textAlign: 'center', textAlign: 'center',
fontWeight: 'bold', fontWeight: 'bold',
color: '#0C2550', color: colors.foregroundColor,
}, },
pleaseText: { pleaseText: {
paddingBottom: 10, paddingBottom: 10,
paddingRight: 0, paddingRight: 0,
paddingLeft: 0, paddingLeft: 0,
color: '#0C2550', color: colors.foregroundColor,
}, },
secret: { secret: {
flex: 1, flex: 1,
@ -61,12 +69,6 @@ const styles = StyleSheet.create({
}, },
}); });
const PleaseBackup = () => {
const [isLoading, setIsLoading] = useState(true);
const route = useRoute();
const words = route.params.secret.split(' ');
const navigation = useNavigation();
const handleBackButton = useCallback(() => { const handleBackButton = useCallback(() => {
navigation.dangerouslyGetParent().pop(); navigation.dangerouslyGetParent().pop();
return true; return true;
@ -102,7 +104,7 @@ const PleaseBackup = () => {
</View> </View>
) : ( ) : (
<SafeBlueArea style={styles.flex}> <SafeBlueArea style={styles.flex}>
<StatusBar barStyle="light-content" /> <StatusBar barStyle="default" />
<ScrollView contentContainerStyle={styles.scrollViewContent} testID="PleaseBackupScrollView"> <ScrollView contentContainerStyle={styles.scrollViewContent} testID="PleaseBackupScrollView">
<View style={styles.please}> <View style={styles.please}>
<BlueText style={styles.successText}>{loc.pleasebackup.success}</BlueText> <BlueText style={styles.successText}>{loc.pleasebackup.success}</BlueText>

View file

@ -1,5 +1,5 @@
import React, { useState, useCallback, useEffect } from 'react'; import React, { useState, useCallback, useEffect } from 'react';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
import { View, Dimensions, StyleSheet, BackHandler, StatusBar } from 'react-native'; import { View, Dimensions, StyleSheet, BackHandler, StatusBar } from 'react-native';
import { import {
SafeBlueArea, SafeBlueArea,
@ -14,27 +14,27 @@ import QRCode from 'react-native-qrcode-svg';
import Privacy from '../../Privacy'; import Privacy from '../../Privacy';
import { ScrollView } from 'react-native-gesture-handler'; import { ScrollView } from 'react-native-gesture-handler';
const { height, width } = Dimensions.get('window'); const { height, width } = Dimensions.get('window');
const BlueApp = require('../../BlueApp');
const loc = require('../../loc'); const loc = require('../../loc');
const styles = StyleSheet.create({
root: {
flex: 1,
},
scrollViewContent: {
flexGrow: 1,
},
});
const PleaseBackupLNDHub = () => { const PleaseBackupLNDHub = () => {
const { wallet } = useRoute().params; const { wallet } = useRoute().params;
const navigation = useNavigation(); const navigation = useNavigation();
const { colors } = useTheme();
const [qrCodeHeight, setQrCodeHeight] = useState(height > width ? width - 40 : width / 2); const [qrCodeHeight, setQrCodeHeight] = useState(height > width ? width - 40 : width / 2);
const handleBackButton = useCallback(() => { const handleBackButton = useCallback(() => {
navigation.dangerouslyGetParent().pop(); navigation.dangerouslyGetParent().pop();
return true; return true;
}, [navigation]); }, [navigation]);
const styles = StyleSheet.create({
root: {
flex: 1,
backgroundColor: colors.elevated,
},
scrollViewContent: {
flexGrow: 1,
backgroundColor: colors.elevated,
},
});
useEffect(() => { useEffect(() => {
Privacy.enableBlur(); Privacy.enableBlur();
@ -52,7 +52,7 @@ const PleaseBackupLNDHub = () => {
return ( return (
<SafeBlueArea style={styles.root}> <SafeBlueArea style={styles.root}>
<StatusBar barStyle="light-content" /> <StatusBar barStyle="default" />
<ScrollView centerContent contentContainerStyle={styles.scrollViewContent} onLayout={onLayout}> <ScrollView centerContent contentContainerStyle={styles.scrollViewContent} onLayout={onLayout}>
<BlueCard> <BlueCard>
<View> <View>
@ -67,8 +67,9 @@ const PleaseBackupLNDHub = () => {
logo={require('../../img/qr-code.png')} logo={require('../../img/qr-code.png')}
logoSize={90} logoSize={90}
size={qrCodeHeight} size={qrCodeHeight}
color={BlueApp.settings.foregroundColor} color={colors.foregroundColor}
logoBackgroundColor={BlueApp.settings.brandingColor} logoBackgroundColor={colors.brandingColor}
backgroundColor={colors.background}
ecl="H" ecl="H"
/> />

View file

@ -3,11 +3,10 @@ import PropTypes from 'prop-types';
import BN from 'bignumber.js'; import BN from 'bignumber.js';
import { Dimensions, View, ScrollView, Text, Image, TouchableOpacity, StyleSheet } from 'react-native'; import { Dimensions, View, ScrollView, Text, Image, TouchableOpacity, StyleSheet } from 'react-native';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
import { BlueCurrentTheme } from '../../components/themes';
import { SafeBlueArea, BlueNavigationStyle, BlueTabs } from '../../BlueComponents'; import { BlueSpacing20, SafeBlueArea, BlueNavigationStyle, BlueTabs } from '../../BlueComponents';
const loc = require('../../loc'); const loc = require('../../loc');
const BlueApp = require('../../BlueApp');
const ENTROPY_LIMIT = 256; const ENTROPY_LIMIT = 256;
@ -133,7 +132,7 @@ const Dice = ({ push, sides }) => {
}; };
return ( return (
<ScrollView style={styles.diceScroll} contentContainerStyle={styles.diceContainer}> <ScrollView contentContainerStyle={styles.diceContainer}>
{[...Array(sides)].map((_, i) => ( {[...Array(sides)].map((_, i) => (
<TouchableOpacity key={i} onPress={() => push(getEntropy(i, sides))}> <TouchableOpacity key={i} onPress={() => push(getEntropy(i, sides))}>
<View style={styles.diceRoot}> <View style={styles.diceRoot}>
@ -141,7 +140,7 @@ const Dice = ({ push, sides }) => {
<Icon style={styles.diceIcon} name={diceIcon(i + 1)} size={70} color="grey" type="font-awesome-5" /> <Icon style={styles.diceIcon} name={diceIcon(i + 1)} size={70} color="grey" type="font-awesome-5" />
) : ( ) : (
<View style={styles.dice}> <View style={styles.dice}>
<Text>{i + 1}</Text> <Text style={styles.diceText}>{i + 1}</Text>
</View> </View>
)} )}
</View> </View>
@ -162,7 +161,7 @@ const Buttons = ({ pop, save }) => (
<View style={styles.buttonsBody}> <View style={styles.buttonsBody}>
<View style={styles.buttonsRow}> <View style={styles.buttonsRow}>
<View style={styles.buttonsIcon}> <View style={styles.buttonsIcon}>
<Icon name="undo" size={16} type="font-awesome" color={BlueApp.settings.buttonAlternativeTextColor} /> <Icon name="undo" size={16} type="font-awesome" color={BlueCurrentTheme.colors.buttonAlternativeTextColor} />
</View> </View>
<Text style={styles.buttonsLabel}>{loc.entropy.undo}</Text> <Text style={styles.buttonsLabel}>{loc.entropy.undo}</Text>
</View> </View>
@ -172,7 +171,7 @@ const Buttons = ({ pop, save }) => (
<View style={styles.buttonsBody}> <View style={styles.buttonsBody}>
<View style={styles.buttonsRow}> <View style={styles.buttonsRow}>
<View style={styles.buttonsIcon}> <View style={styles.buttonsIcon}>
<Icon name="arrow-down" size={16} type="font-awesome" color={BlueApp.settings.buttonAlternativeTextColor} /> <Icon name="arrow-down" size={16} type="font-awesome" color={BlueCurrentTheme.colors.buttonAlternativeTextColor} />
</View> </View>
<Text style={[styles.buttonsLabel, styles.buttonsLabelRight]}>{loc.entropy.save}</Text> <Text style={[styles.buttonsLabel, styles.buttonsLabelRight]}>{loc.entropy.save}</Text>
</View> </View>
@ -192,6 +191,7 @@ const Entropy = () => {
const navigation = useNavigation(); const navigation = useNavigation();
const [tab, setTab] = useState(1); const [tab, setTab] = useState(1);
const [show, setShow] = useState(false); const [show, setShow] = useState(false);
const { colors } = useTheme();
const push = v => v && dispatch({ type: 'push', value: v.value, bits: v.bits }); const push = v => v && dispatch({ type: 'push', value: v.value, bits: v.bits });
const pop = () => dispatch({ type: 'pop' }); const pop = () => dispatch({ type: 'pop' });
@ -207,6 +207,7 @@ const Entropy = () => {
return ( return (
<SafeBlueArea> <SafeBlueArea>
<BlueSpacing20 />
<TouchableOpacity onPress={() => setShow(!show)}> <TouchableOpacity onPress={() => setShow(!show)}>
<View style={styles.entropy}> <View style={styles.entropy}>
<Text style={styles.entropyText}>{show ? hex : `${bits} of 256 bits`}</Text> <Text style={styles.entropyText}>{show ? hex : `${bits} of 256 bits`}</Text>
@ -218,25 +219,13 @@ const Entropy = () => {
onSwitch={setTab} onSwitch={setTab}
tabs={[ tabs={[
({ active }) => ( ({ active }) => (
<Icon <Icon name="toll" type="material" color={active ? colors.buttonAlternativeTextColor : colors.buttonBackgroundColor} />
name="toll"
type="material"
color={active ? BlueApp.settings.buttonAlternativeTextColor : BlueApp.settings.buttonBackgroundColor}
/>
), ),
({ active }) => ( ({ active }) => (
<Icon <Icon name="dice" type="font-awesome-5" color={active ? colors.buttonAlternativeTextColor : colors.buttonBackgroundColor} />
name="dice"
type="font-awesome-5"
color={active ? BlueApp.settings.buttonAlternativeTextColor : BlueApp.settings.buttonBackgroundColor}
/>
), ),
({ active }) => ( ({ active }) => (
<Icon <Icon name="dice-d20" type="font-awesome-5" color={active ? colors.buttonAlternativeTextColor : colors.buttonBackgroundColor} />
name="dice-d20"
type="font-awesome-5"
color={active ? BlueApp.settings.buttonAlternativeTextColor : BlueApp.settings.buttonBackgroundColor}
/>
), ),
]} ]}
/> />
@ -267,7 +256,7 @@ const styles = StyleSheet.create({
padding: 5, padding: 5,
marginLeft: 10, marginLeft: 10,
marginRight: 10, marginRight: 10,
backgroundColor: '#f2f2f2', backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
borderRadius: 9, borderRadius: 9,
minHeight: 49, minHeight: 49,
paddingHorizontal: 8, paddingHorizontal: 8,
@ -278,13 +267,13 @@ const styles = StyleSheet.create({
entropyText: { entropyText: {
fontSize: 15, fontSize: 15,
fontFamily: 'Courier', fontFamily: 'Courier',
color: BlueCurrentTheme.colors.foregroundColor,
}, },
coinRoot: { coinRoot: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',
flexDirection: 'row', flexDirection: 'row',
flexWrap: 'wrap', flexWrap: 'wrap',
backgroundColor: 'white',
}, },
coinBody: { coinBody: {
flex: 0.33, flex: 0.33,
@ -293,7 +282,7 @@ const styles = StyleSheet.create({
aspectRatio: 1, aspectRatio: 1,
borderWidth: 1, borderWidth: 1,
borderRadius: 5, borderRadius: 5,
borderColor: 'grey', borderColor: BlueCurrentTheme.colors.lightButton,
margin: 10, margin: 10,
padding: 10, padding: 10,
}, },
@ -303,9 +292,6 @@ const styles = StyleSheet.create({
height: '100%', height: '100%',
borderRadius: 75, borderRadius: 75,
}, },
diceScroll: {
backgroundColor: 'white',
},
diceContainer: { diceContainer: {
alignItems: 'flex-start', alignItems: 'flex-start',
flexDirection: 'row', flexDirection: 'row',
@ -321,10 +307,13 @@ const styles = StyleSheet.create({
margin: 3, margin: 3,
borderWidth: 1, borderWidth: 1,
borderRadius: 5, borderRadius: 5,
borderColor: 'grey',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
aspectRatio: 1, aspectRatio: 1,
borderColor: BlueCurrentTheme.colors.buttonBackgroundColor,
},
diceText: {
color: BlueCurrentTheme.colors.foregroundColor,
}, },
diceIcon: { diceIcon: {
margin: 3, margin: 3,
@ -346,7 +335,7 @@ const styles = StyleSheet.create({
buttonsBody: { buttonsBody: {
flex: 1, flex: 1,
minWidth: 130, minWidth: 130,
backgroundColor: BlueApp.settings.buttonBackgroundColor, backgroundColor: BlueCurrentTheme.colors.buttonBackgroundColor,
}, },
buttonsRow: { buttonsRow: {
flex: 1, flex: 1,
@ -364,7 +353,7 @@ const styles = StyleSheet.create({
marginBottom: -11, marginBottom: -11,
}, },
buttonsLabel: { buttonsLabel: {
color: BlueApp.settings.buttonAlternativeTextColor, color: BlueCurrentTheme.colors.buttonAlternativeTextColor,
fontWeight: '500', fontWeight: '500',
left: 5, left: 5,
backgroundColor: 'transparent', backgroundColor: 'transparent',

View file

@ -7,6 +7,7 @@ import PropTypes from 'prop-types';
import { PlaceholderWallet, LightningCustodianWallet } from '../../class'; import { PlaceholderWallet, LightningCustodianWallet } from '../../class';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import WalletGradient from '../../class/wallet-gradient'; import WalletGradient from '../../class/wallet-gradient';
import { BlueCurrentTheme } from '../../components/themes';
const EV = require('../../blue_modules/events'); const EV = require('../../blue_modules/events');
/** @type {AppStorage} */ /** @type {AppStorage} */
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
@ -19,6 +20,7 @@ const styles = StyleSheet.create({
}, },
root: { root: {
flex: 1, flex: 1,
backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
itemRoot: { itemRoot: {
backgroundColor: 'transparent', backgroundColor: 'transparent',
@ -66,17 +68,6 @@ const styles = StyleSheet.create({
}); });
export default class ReorderWallets extends Component { export default class ReorderWallets extends Component {
static navigationOptions = ({ navigation, route }) => ({
...BlueNavigationStyle(
navigation,
true,
route.params && route.params.customCloseButtonFunction ? route.params.customCloseButtonFunction : undefined,
),
headerTitle: loc.wallets.reorder.title,
headerLeft: null,
gestureEnabled: false,
});
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -196,3 +187,14 @@ ReorderWallets.propTypes = {
goBack: PropTypes.func, goBack: PropTypes.func,
}), }),
}; };
ReorderWallets.navigationOptions = ({ navigation, route }) => ({
...BlueNavigationStyle(
navigation,
true,
route.params && route.params.customCloseButtonFunction ? route.params.customCloseButtonFunction : undefined,
),
headerTitle: loc.wallets.reorder.title,
headerLeft: null,
gestureEnabled: false,
});

View file

@ -1,19 +1,32 @@
/* eslint-disable react/prop-types */ /* eslint-disable react/prop-types */
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { View, ActivityIndicator, Image, Text, TouchableOpacity, FlatList, StyleSheet, StatusBar } from 'react-native'; import { View, ActivityIndicator, Image, Text, TouchableOpacity, FlatList, StyleSheet, StatusBar } from 'react-native';
import { SafeBlueArea, BlueNavigationStyle, BlueText, BlueSpacing20, BluePrivateBalance } from '../../BlueComponents'; import { SafeBlueArea, BlueText, BlueSpacing20, BluePrivateBalance, BlueNavigationStyle } from '../../BlueComponents';
import LinearGradient from 'react-native-linear-gradient'; import LinearGradient from 'react-native-linear-gradient';
import { LightningCustodianWallet } from '../../class/wallets/lightning-custodian-wallet'; import { LightningCustodianWallet } from '../../class/wallets/lightning-custodian-wallet';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import WalletGradient from '../../class/wallet-gradient'; import WalletGradient from '../../class/wallet-gradient';
import { useRoute } from '@react-navigation/native'; import { useRoute, useTheme } from '@react-navigation/native';
/** @type {AppStorage} */ /** @type {AppStorage} */
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
const loc = require('../../loc'); const loc = require('../../loc');
const SelectWallet = ({ navigation }) => {
const { chainType, onWalletSelect, availableWallets } = useRoute().params;
const [isLoading, setIsLoading] = useState(true);
const { colors } = useTheme();
let data = chainType
? BlueApp.getWallets().filter(item => item.chain === chainType && item.allowSend())
: BlueApp.getWallets().filter(item => item.allowSend()) || [];
if (availableWallets && availableWallets.length > 0) {
// availableWallets if provided, overrides chainType argument and `allowSend()` check
data = availableWallets;
}
const styles = StyleSheet.create({ const styles = StyleSheet.create({
root: { root: {
flex: 1, flex: 1,
backgroundColor: colors.background,
}, },
loading: { loading: {
flex: 1, flex: 1,
@ -75,18 +88,6 @@ const styles = StyleSheet.create({
}, },
}); });
const SelectWallet = ({ navigation }) => {
const { chainType, onWalletSelect, availableWallets } = useRoute().params;
const [isLoading, setIsLoading] = useState(true);
let data = chainType
? BlueApp.getWallets().filter(item => item.chain === chainType && item.allowSend())
: BlueApp.getWallets().filter(item => item.allowSend()) || [];
if (availableWallets && availableWallets.length > 0) {
// availableWallets if provided, overrides chainType argument and `allowSend()` check
data = availableWallets;
}
useEffect(() => { useEffect(() => {
setIsLoading(false); setIsLoading(false);
}, []); }, []);
@ -135,13 +136,14 @@ const SelectWallet = ({ navigation }) => {
if (isLoading) { if (isLoading) {
return ( return (
<View style={styles.loading}> <View style={styles.loading}>
<StatusBar barStyle="light-content" />
<ActivityIndicator /> <ActivityIndicator />
</View> </View>
); );
} else if (data.length <= 0) { } else if (data.length <= 0) {
return ( return (
<SafeBlueArea style={styles.root}> <SafeBlueArea style={styles.root}>
<StatusBar barStyle="dark-content" /> <StatusBar barStyle="light-content" />
<View style={styles.noWallets}> <View style={styles.noWallets}>
<BlueText style={styles.center}>There are currently no Bitcoin wallets available.</BlueText> <BlueText style={styles.center}>There are currently no Bitcoin wallets available.</BlueText>
<BlueSpacing20 /> <BlueSpacing20 />
@ -152,7 +154,7 @@ const SelectWallet = ({ navigation }) => {
} else { } else {
return ( return (
<SafeBlueArea style={styles.root}> <SafeBlueArea style={styles.root}>
<StatusBar barStyle="dark-content" /> <StatusBar barStyle="default" />
<FlatList extraData={data} data={data} renderItem={renderItem} keyExtractor={(_item, index) => `${index}`} /> <FlatList extraData={data} data={data} renderItem={renderItem} keyExtractor={(_item, index) => `${index}`} />
</SafeBlueArea> </SafeBlueArea>
); );
@ -160,9 +162,10 @@ const SelectWallet = ({ navigation }) => {
}; };
SelectWallet.navigationOptions = ({ navigation }) => ({ SelectWallet.navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true, () => navigation.goBack(null)), ...BlueNavigationStyle(navigation, true),
title: loc.wallets.select_wallet,
headerRight: null, headerRight: null,
headerTitle: loc.wallets.select_wallet,
headerBackTitleVisible: false,
}); });
export default SelectWallet; export default SelectWallet;

View file

@ -36,6 +36,7 @@ import Modal from 'react-native-modal';
import * as NavigationService from '../../NavigationService'; import * as NavigationService from '../../NavigationService';
import HandoffSettings from '../../class/handoff'; import HandoffSettings from '../../class/handoff';
import Handoff from 'react-native-handoff'; import Handoff from 'react-native-handoff';
import { BlueCurrentTheme } from '../../components/themes';
import ActionSheet from '../ActionSheet'; import ActionSheet from '../ActionSheet';
/** @type {AppStorage} */ /** @type {AppStorage} */
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
@ -66,7 +67,7 @@ const styles = StyleSheet.create({
height: 200, height: 200,
}, },
advancedTransactionOptionsModalContent: { advancedTransactionOptionsModalContent: {
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.elevated,
padding: 22, padding: 22,
borderTopLeftRadius: 16, borderTopLeftRadius: 16,
borderTopRightRadius: 16, borderTopRightRadius: 16,
@ -98,10 +99,10 @@ const styles = StyleSheet.create({
marginBottom: 8, marginBottom: 8,
fontWeight: 'bold', fontWeight: 'bold',
fontSize: 24, fontSize: 24,
color: BlueApp.settings.foregroundColor, color: BlueCurrentTheme.colors.foregroundColor,
}, },
marketplaceButton1: { marketplaceButton1: {
backgroundColor: '#f2f2f2', backgroundColor: BlueCurrentTheme.colors.lightButton,
borderRadius: 9, borderRadius: 9,
minHeight: 49, minHeight: 49,
flex: 1, flex: 1,
@ -112,7 +113,7 @@ const styles = StyleSheet.create({
}, },
marketplaceButton2: { marketplaceButton2: {
marginLeft: 5, marginLeft: 5,
backgroundColor: '#f2f2f2', backgroundColor: BlueCurrentTheme.colors.lightButton,
borderRadius: 9, borderRadius: 9,
minHeight: 49, minHeight: 49,
flex: 1, flex: 1,
@ -122,16 +123,16 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
}, },
marketpalceText1: { marketpalceText1: {
color: '#062453', color: BlueCurrentTheme.colors.cta2,
fontSize: 18, fontSize: 18,
}, },
marketpalceText2: { marketpalceText2: {
color: '#062453', color: BlueCurrentTheme.colors.cta2,
fontSize: 18, fontSize: 18,
marginHorizontal: 8, marginHorizontal: 8,
}, },
list: { list: {
backgroundColor: '#FFFFFF', backgroundColor: BlueCurrentTheme.colors.background,
flex: 1, flex: 1,
}, },
emptyTxs: { emptyTxs: {
@ -173,34 +174,6 @@ const styles = StyleSheet.create({
}); });
export default class WalletTransactions extends Component { export default class WalletTransactions extends Component {
static navigationOptions = ({ navigation, route }) => {
return {
headerRight: () => (
<TouchableOpacity
disabled={route.params.isLoading === true}
style={styles.walletDetails}
onPress={() =>
navigation.navigate('WalletDetails', {
wallet: route.params.wallet,
})
}
>
<Icon name="kebab-horizontal" type="octicon" size={22} color="#FFFFFF" />
</TouchableOpacity>
),
headerTitle: () => null,
headerStyle: {
backgroundColor: WalletGradient.headerColorFor(route.params.wallet.type),
borderBottomWidth: 0,
elevation: 0,
// shadowRadius: 0,
shadowOffset: { height: 0, width: 0 },
},
headerTintColor: '#FFFFFF',
headerBackTitleVisible: false,
};
};
walletBalanceText = null; walletBalanceText = null;
constructor(props) { constructor(props) {
@ -833,3 +806,31 @@ WalletTransactions.propTypes = {
params: PropTypes.object, params: PropTypes.object,
}), }),
}; };
WalletTransactions.navigationOptions = ({ navigation, route }) => {
return {
headerRight: () => (
<TouchableOpacity
disabled={route.params.isLoading === true}
style={styles.walletDetails}
onPress={() =>
navigation.navigate('WalletDetails', {
wallet: route.params.wallet,
})
}
>
<Icon name="kebab-horizontal" type="octicon" size={22} color="#FFFFFF" />
</TouchableOpacity>
),
headerTitle: () => null,
headerStyle: {
backgroundColor: WalletGradient.headerColorFor(route.params.wallet.type),
borderBottomWidth: 0,
elevation: 0,
// shadowRadius: 0,
shadowOffset: { height: 0, width: 0 },
},
headerTintColor: '#FFFFFF',
headerBackTitleVisible: false,
};
};

View file

@ -5,6 +5,7 @@ import { BlueSpacing20, SafeBlueArea, BlueText, BlueNavigationStyle, BlueCopyTex
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Privacy from '../../Privacy'; import Privacy from '../../Privacy';
import Biometric from '../../class/biometrics'; import Biometric from '../../class/biometrics';
import { BlueCurrentTheme } from '../../components/themes';
/** @type {AppStorage} */ /** @type {AppStorage} */
const BlueApp = require('../../BlueApp'); const BlueApp = require('../../BlueApp');
const loc = require('../../loc'); const loc = require('../../loc');
@ -14,6 +15,7 @@ const styles = StyleSheet.create({
root: { root: {
flex: 1, flex: 1,
paddingTop: 20, paddingTop: 20,
backgroundColor: BlueCurrentTheme.colors.elevated,
}, },
container: { container: {
alignItems: 'center', alignItems: 'center',
@ -23,12 +25,6 @@ const styles = StyleSheet.create({
}); });
export default class WalletXpub extends Component { export default class WalletXpub extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: loc.wallets.xpub.title,
headerLeft: null,
});
constructor(props) { constructor(props) {
super(props); super(props);
@ -98,8 +94,9 @@ export default class WalletXpub extends Component {
logo={require('../../img/qr-code.png')} logo={require('../../img/qr-code.png')}
size={this.state.qrCodeHeight} size={this.state.qrCodeHeight}
logoSize={90} logoSize={90}
color={BlueApp.settings.foregroundColor} color={BlueCurrentTheme.colors.foregroundColor}
logoBackgroundColor={BlueApp.settings.brandingColor} logoBackgroundColor={BlueCurrentTheme.colors.brandingColor}
backgroundColor={BlueCurrentTheme.colors.background}
ecl="H" ecl="H"
/> />
@ -123,3 +120,9 @@ WalletXpub.propTypes = {
}), }),
}), }),
}; };
WalletXpub.navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: loc.wallets.xpub.title,
headerLeft: null,
});