diff --git a/App.js b/App.js index f96672986..74e1bf46c 100644 --- a/App.js +++ b/App.js @@ -3,18 +3,20 @@ import React from 'react'; import { Linking, Appearance, DeviceEventEmitter, AppState, StyleSheet, KeyboardAvoidingView, Platform, View } from 'react-native'; import Clipboard from '@react-native-community/clipboard'; 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 Navigation from './Navigation'; import { navigationRef } 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 { Chain } from './models/bitcoinUnits'; import QuickActions from 'react-native-quick-actions'; import * as Sentry from '@sentry/react-native'; import OnAppLaunch from './class/on-app-launch'; import DeeplinkSchemaMatch from './class/deeplink-schema-match'; +import { BlueDefaultTheme, BlueDarkTheme, BlueCurrentTheme } from './components/themes'; + const A = require('./blue_modules/analytics'); if (process.env.NODE_ENV !== 'development') { @@ -35,12 +37,21 @@ export default class App extends React.Component { isClipboardContentModalVisible: false, clipboardContentModalAddressType: bitcoinModalString, clipboardContent: '', + theme: Appearance.getColorScheme(), }; componentDidMount() { EV(EV.enum.WALLETS_INITIALIZED, this.addListeners); + Appearance.addChangeListener(this.appearanceChanged); } + appearanceChanged = () => { + const appearance = Appearance.getColorScheme(); + if (appearance) { + this.setState({ theme: appearance }); + } + }; + addListeners = () => { Linking.addEventListener('url', this.handleOpenURL); AppState.addEventListener('change', this._handleAppStateChange); @@ -104,6 +115,7 @@ export default class App extends React.Component { componentWillUnmount() { Linking.removeEventListener('url', this.handleOpenURL); AppState.removeEventListener('change', this._handleAppStateChange); + Appearance.removeChangeListener(this.appearanceChanged); } _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? - this.setState({ isClipboardContentModalVisible: false })} @@ -219,7 +231,7 @@ export default class App extends React.Component { return ( - + {this.renderClipboardContentModal()} @@ -237,7 +249,7 @@ const styles = StyleSheet.create({ marginHorizontal: 8, }, modalContent: { - backgroundColor: '#FFFFFF', + backgroundColor: BlueCurrentTheme.colors.elevated, padding: 22, justifyContent: 'center', alignItems: 'center', diff --git a/BlueComponents.js b/BlueComponents.js index 2ac0d037a..8ba9d71f2 100644 --- a/BlueComponents.js +++ b/BlueComponents.js @@ -36,6 +36,8 @@ import NetworkTransactionFees, { NetworkTransactionFeeType } from './models/netw import Biometric from './class/biometrics'; import { encodeUR } from 'bc-ur/dist'; import QRCode from 'react-native-qrcode-svg'; +import { useTheme } from '@react-navigation/native'; +import { BlueCurrentTheme } from './components/themes'; const loc = require('./loc/'); /** @type {AppStorage} */ const BlueApp = require('./BlueApp'); @@ -52,11 +54,49 @@ if (aspectRatio > 1.6) { export class BlueButton extends Component { render() { - let backgroundColor = this.props.backgroundColor ? this.props.backgroundColor : BlueApp.settings.buttonBackgroundColor; - let fontColor = BlueApp.settings.buttonTextColor; + let backgroundColor = this.props.backgroundColor ? this.props.backgroundColor : BlueCurrentTheme.colors.mainColor; + let fontColor = BlueCurrentTheme.colors.buttonTextColor; if (this.props.disabled === true) { - backgroundColor = BlueApp.settings.buttonDisabledBackgroundColor; - fontColor = BlueApp.settings.buttonDisabledTextColor; + backgroundColor = BlueCurrentTheme.colors.buttonDisabledBackgroundColor; + fontColor = BlueCurrentTheme.colors.buttonDisabledTextColor; + } + let buttonWidth = this.props.width ? this.props.width : width / 1.5; + if ('noMinWidth' in this.props) { + buttonWidth = 0; + } + return ( + + + {this.props.icon && } + {this.props.title && {this.props.title}} + + + ); + } +} + +export class SecondButton extends Component { + render() { + let backgroundColor = this.props.backgroundColor ? this.props.backgroundColor : BlueCurrentTheme.colors.buttonBlueBackgroundColor; + let fontColor = BlueCurrentTheme.colors.buttonTextColor; + if (this.props.disabled === true) { + backgroundColor = BlueCurrentTheme.colors.buttonDisabledBackgroundColor; + fontColor = BlueCurrentTheme.colors.buttonDisabledTextColor; } let buttonWidth = this.props.width ? this.props.width : width / 1.5; if ('noMinWidth' in this.props) { @@ -99,10 +139,10 @@ export class BitcoinButton extends Component { > - {loc.wallets.add.bitcoin} + {loc.wallets.add.bitcoin} - {loc.wallets.add.lightning} + {loc.wallets.add.lightning} { + const { colors } = useTheme(); + return ( + + {title} + + ); +}; + export class BlueButtonLink extends Component { render() { return ( @@ -368,7 +425,7 @@ export class BlueButtonLink extends Component { }} {...this.props} > - {this.props.title} + {this.props.title} ); } @@ -391,6 +448,7 @@ export const BlueAlertWalletExportReminder = ({ onSuccess = () => {}, onFailure export const BlueNavigationStyle = (navigation, withNavigationCloseButton = false, customCloseButtonFunction = undefined) => { let headerRight; + const { colors, closeImage } = useTheme(); if (withNavigationCloseButton) { headerRight = () => ( - + ); } else { @@ -413,7 +471,6 @@ export const BlueNavigationStyle = (navigation, withNavigationCloseButton = fals return { headerStyle: { - backgroundColor: BlueApp.settings.brandingColor, borderBottomWidth: 0, elevation: 0, shadowOpacity: 0, @@ -421,12 +478,11 @@ export const BlueNavigationStyle = (navigation, withNavigationCloseButton = fals }, headerTitleStyle: { fontWeight: '600', - color: BlueApp.settings.foregroundColor, + color: colors.foregroundColor, }, headerRight, - headerTintColor: BlueApp.settings.foregroundColor, - // headerBackTitle: null, headerBackTitleVisible: false, + headerTintColor: colors.foregroundColor, }; }; @@ -434,8 +490,8 @@ export const BlueCreateTxNavigationStyle = (navigation, withAdvancedOptionsMenuB let headerRight; if (withAdvancedOptionsMenuButton) { headerRight = () => ( - - + + ); } else { @@ -443,25 +499,24 @@ export const BlueCreateTxNavigationStyle = (navigation, withAdvancedOptionsMenuB } return { headerStyle: { - backgroundColor: BlueApp.settings.brandingColor, borderBottomWidth: 0, elevation: 0, shadowOffset: { height: 0, width: 0 }, }, headerTitleStyle: { fontWeight: '600', - color: BlueApp.settings.foregroundColor, + color: BlueCurrentTheme.colors.foregroundColor, }, - headerTintColor: BlueApp.settings.foregroundColor, + headerTintColor: BlueCurrentTheme.colors.foregroundColor, headerLeft: () => ( { Keyboard.dismiss(); navigation.goBack(null); }} > - + ), headerRight, @@ -556,9 +611,9 @@ export class SafeBlueArea extends Component { render() { return ( ); } @@ -575,7 +630,7 @@ export class BlueText extends Component { return ( { + const { colors } = useTheme(); + return ( + + ); +}; export class BlueTextCentered extends Component { render() { - return ; + return ; } } @@ -595,16 +663,16 @@ export const BlueListItem = React.memo(props => ( bottomDivider containerStyle={{ backgroundColor: 'transparent', - borderBottomColor: '#ededed', + borderBottomColor: BlueCurrentTheme.colors.lightBorder, paddingTop: 16, paddingBottom: 16, }} titleStyle={{ - color: props.disabled ? BlueApp.settings.buttonDisabledTextColor : BlueApp.settings.foregroundColor, + color: props.disabled ? BlueCurrentTheme.colors.buttonDisabledTextColor : BlueCurrentTheme.colors.foregroundColor, fontSize: 16, fontWeight: '500', }} - subtitleStyle={{ flexWrap: 'wrap', color: BlueApp.settings.alternativeTextColor, fontWeight: '400', fontSize: 14 }} + subtitleStyle={{ flexWrap: 'wrap', color: BlueCurrentTheme.colors.alternativeTextColor, fontWeight: '400', fontSize: 14 }} subtitleNumberOfLines={1} titleNumberOfLines={0} Component={TouchableOpacity} @@ -612,9 +680,36 @@ export const BlueListItem = React.memo(props => ( /> )); +export const BlueListItemHooks = props => { + const { colors } = useTheme(); + return ( + + ); +}; + export class BlueFormLabel extends Component { render() { - return ; + return ; } } @@ -623,14 +718,14 @@ export class BlueFormInput extends Component { return ( ); @@ -652,15 +747,18 @@ export class BlueFormMultiInput extends Component { underlineColorAndroid="transparent" numberOfLines={4} style={{ + paddingHorizontal: 8, + paddingVertical: 16, flex: 1, marginTop: 5, marginHorizontal: 20, - borderColor: BlueApp.settings.inputBorderColor, - borderBottomColor: BlueApp.settings.inputBorderColor, - borderWidth: 0.5, + borderColor: BlueCurrentTheme.colors.formBorder, + borderBottomColor: BlueCurrentTheme.colors.formBorder, + borderWidth: 1, borderBottomWidth: 0.5, - backgroundColor: BlueApp.settings.inputBackgroundColor, - color: BlueApp.settings.foregroundColor, + borderRadius: 4, + backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor, + color: BlueCurrentTheme.colors.foregroundColor, }} autoCorrect={false} autoCapitalize="none" @@ -691,9 +789,9 @@ export class BlueHeader extends Component { export class BlueHeaderDefaultSub extends Component { render() { return ( - +
{this.props.leftText} @@ -731,10 +829,40 @@ export class BlueHeaderDefaultSub extends Component { } } +export const BlueHeaderDefaultSubHooks = props => { + const { colors } = useTheme(); + + return ( + +
+ {props.leftText} + + } + {...props} + /> + + ); +}; + export class BlueHeaderDefaultMain extends Component { render() { return ( - +
; + return ; } } export class BlueSpacing40 extends Component { render() { - return ; + return ; } } @@ -840,13 +970,13 @@ export class BlueUseAllFundsButton extends Component { maxHeight: 44, justifyContent: 'space-between', alignItems: 'center', - backgroundColor: '#eef0f4', + backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor, }} > - - - - + + + ); } } +export const BlueLoadingHook = () => { + const { colors } = useTheme(); + return ( + + + + ); +}; + const stylesBlueIcon = StyleSheet.create({ container: { flex: 1, @@ -988,13 +1125,13 @@ const stylesBlueIcon = StyleSheet.create({ width: 30, height: 30, borderRadius: 15, - backgroundColor: '#ccddf9', + backgroundColor: BlueCurrentTheme.colors.buttonBackgroundColor, }, ballIncoming: { width: 30, height: 30, borderRadius: 15, - backgroundColor: '#d2f8d6', + backgroundColor: BlueCurrentTheme.colors.ballReceive, transform: [{ rotate: '-45deg' }], justifyContent: 'center', }, @@ -1002,20 +1139,20 @@ const stylesBlueIcon = StyleSheet.create({ width: 30, height: 30, borderRadius: 15, - backgroundColor: '#d2f8d6', + backgroundColor: BlueCurrentTheme.colors.ballReceive, }, ballReceive: { width: 30, height: 30, borderBottomLeftRadius: 15, - backgroundColor: '#d2f8d6', + backgroundColor: BlueCurrentTheme.colors.ballReceive, transform: [{ rotate: '-45deg' }], }, ballOutgoing: { width: 30, height: 30, borderRadius: 15, - backgroundColor: '#f8d2d2', + backgroundColor: BlueCurrentTheme.colors.ballOutgoing, transform: [{ rotate: '225deg' }], justifyContent: 'center', }, @@ -1023,13 +1160,13 @@ const stylesBlueIcon = StyleSheet.create({ width: 30, height: 30, borderRadius: 15, - backgroundColor: '#f8d2d2', + backgroundColor: BlueCurrentTheme.colors.ballOutgoing, }, ballOutgoingExpired: { width: 30, height: 30, borderRadius: 15, - backgroundColor: '#EEF0F4', + backgroundColor: BlueCurrentTheme.colors.ballOutgoingExpired, justifyContent: 'center', }, ballTransparrent: { @@ -1056,7 +1193,7 @@ export class BluePlusIcon extends Component { name="ios-add" size={26} style={{ - color: BlueApp.settings.foregroundColor, + color: BlueCurrentTheme.colors.foregroundColor, backgroundColor: 'transparent', left: 8, top: 1, @@ -1075,7 +1212,7 @@ export class BlueTransactionIncomingIcon extends Component { - + @@ -1094,7 +1231,7 @@ export class BlueTransactionPendingIcon extends Component { name="kebab-horizontal" size={16} type="octicon" - color={BlueApp.settings.foregroundColor} + color={BlueCurrentTheme.colors.foregroundColor} iconStyle={{ left: 0, top: 7 }} /> @@ -1129,7 +1266,7 @@ export class BlueTransactionOnchainIcon extends Component { name="link" size={16} type="font-awesome" - color={BlueApp.settings.incomingForegroundColor} + color={BlueCurrentTheme.colors.incomingForegroundColor} iconStyle={{ left: 0, top: 0, transform: [{ rotate: '-45deg' }] }} /> @@ -1150,7 +1287,7 @@ export class BlueTransactionOffchainIcon extends Component { name="bolt" size={16} type="font-awesome" - color={BlueApp.settings.outgoingForegroundColor} + color={BlueCurrentTheme.colors.outgoingForegroundColor} iconStyle={{ left: 0, marginTop: 6 }} /> @@ -1171,7 +1308,7 @@ export class BlueTransactionOffchainIncomingIcon extends Component { name="bolt" size={16} type="font-awesome" - color={BlueApp.settings.incomingForegroundColor} + color={BlueCurrentTheme.colors.incomingForegroundColor} iconStyle={{ left: 0, marginTop: 6 }} /> @@ -1187,7 +1324,7 @@ export class BlueTransactionOutgoingIcon extends Component { - + @@ -1205,7 +1342,7 @@ export class BlueReceiveButtonIcon extends Component { style={{ flex: 1, minWidth: 130, - backgroundColor: BlueApp.settings.buttonBackgroundColor, + backgroundColor: BlueCurrentTheme.colors.buttonBackgroundColor, }} > @@ -1220,11 +1357,17 @@ export class BlueReceiveButtonIcon extends Component { marginBottom: -11, }} > - + - + @@ -1307,11 +1450,17 @@ export class BlueSendButtonIcon extends Component { marginBottom: 11, }} > - + @@ -1347,11 +1496,11 @@ export class ManageFundsBigButton extends Component { transform: [{ rotate: '90deg' }], }} > - + @@ -1394,7 +1543,7 @@ export class NewWalletPanel extends Component { {loc.wallets.list.create_a_wallet1} @@ -1403,13 +1552,13 @@ export class NewWalletPanel extends Component { style={{ backgroundColor: 'transparent', fontSize: 13, - color: BlueApp.settings.alternativeTextColor, + color: BlueCurrentTheme.colors.alternativeTextColor, }} > {loc.wallets.list.create_a_wallet2} - {loc.wallets.list.create_a_button} + {loc.wallets.list.create_a_button} @@ -1453,7 +1602,7 @@ export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = Bitco }; const rowTitleStyle = () => { - let color = BlueApp.settings.successColor; + let color = BlueCurrentTheme.colors.successColor; if (item.type === 'user_invoice' || item.type === 'payment_request') { const currentDate = new Date(); @@ -1461,16 +1610,16 @@ export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = Bitco const invoiceExpiration = item.timestamp + item.expire_time; if (invoiceExpiration > now) { - color = BlueApp.settings.successColor; + color = BlueCurrentTheme.colors.successColor; } else if (invoiceExpiration < now) { if (item.ispaid) { - color = BlueApp.settings.successColor; + color = BlueCurrentTheme.colors.successColor; } else { color = '#9AA0AA'; } } } else if (item.value / 100000000 < 0) { - color = BlueApp.settings.foregroundColor; + color = BlueCurrentTheme.colors.foregroundColor; } return { @@ -1660,7 +1809,7 @@ export class BlueListTransactionItem extends Component { } } } else if (item.value / 100000000 < 0) { - color = BlueApp.settings.foregroundColor; + color = BlueCurrentTheme.colors.foregroundColor; } return { @@ -1835,7 +1984,7 @@ const WalletCarouselItem = ({ item, index, onPress, handleLongPress }) => { }} > { style={{ backgroundColor: 'transparent', fontSize: 19, - color: BlueApp.settings.inverseForegroundColor, + color: BlueCurrentTheme.colors.inverseForegroundColor, }} > {item.getLabel()} @@ -1872,7 +2021,7 @@ const WalletCarouselItem = ({ item, index, onPress, handleLongPress }) => { backgroundColor: 'transparent', fontSize: 19, marginTop: 40, - color: BlueApp.settings.inverseForegroundColor, + color: BlueCurrentTheme.colors.inverseForegroundColor, }} > An error was encountered when attempting to import this wallet. @@ -1904,7 +2053,7 @@ const WalletCarouselItem = ({ item, index, onPress, handleLongPress }) => { }} > { style={{ backgroundColor: 'transparent', fontSize: 19, - color: BlueApp.settings.inverseForegroundColor, + color: BlueCurrentTheme.colors.inverseForegroundColor, }} > {item.getLabel()} @@ -1945,7 +2094,7 @@ const WalletCarouselItem = ({ item, index, onPress, handleLongPress }) => { backgroundColor: 'transparent', fontWeight: 'bold', fontSize: 36, - color: BlueApp.settings.inverseForegroundColor, + color: BlueCurrentTheme.colors.inverseForegroundColor, }} > {loc.formatBalance(Number(item.getBalance()), item.getPreferredBalanceUnit(), true)} @@ -1957,7 +2106,7 @@ const WalletCarouselItem = ({ item, index, onPress, handleLongPress }) => { style={{ backgroundColor: 'transparent', fontSize: 13, - color: BlueApp.settings.inverseForegroundColor, + color: BlueCurrentTheme.colors.inverseForegroundColor, }} > {loc.wallets.list.latest_transaction} @@ -1968,7 +2117,7 @@ const WalletCarouselItem = ({ item, index, onPress, handleLongPress }) => { backgroundColor: 'transparent', fontWeight: 'bold', fontSize: 16, - color: BlueApp.settings.inverseForegroundColor, + color: BlueCurrentTheme.colors.inverseForegroundColor, }} > {loc.transactionTimeToReadable(item.getLatestTransactionTime())} @@ -2050,11 +2199,11 @@ export class BlueAddressInput extends Component { - - {loc.send.details.scan} + + {loc.send.details.scan} ); @@ -2157,42 +2306,42 @@ export class BlueReplaceFeeSuggestions extends Component { Suggestions this.onFeeSelected(NetworkTransactionFeeType.FAST)} - containerStyle={{ paddingHorizontal: 0, marginHorizontal: 0 }} + containerStyle={{ paddingHorizontal: 0, marginHorizontal: 0, backgroundColor: BlueCurrentTheme.colors.transparent }} bottomDivider={false} title="Fast" rightTitle={`${this.state.networkFees.fastestFee} sat/b`} - rightTitleStyle={{ fontSize: 13, color: BlueApp.settings.alternativeTextColor }} + rightTitleStyle={{ fontSize: 13, color: BlueCurrentTheme.colors.alternativeTextColor }} {...(this.state.selectedFeeType === NetworkTransactionFeeType.FAST - ? { rightIcon: } + ? { rightIcon: } : { hideChevron: true })} /> this.onFeeSelected(NetworkTransactionFeeType.MEDIUM)} - containerStyle={{ paddingHorizontal: 0, marginHorizontal: 0 }} + containerStyle={{ paddingHorizontal: 0, marginHorizontal: 0, backgroundColor: BlueCurrentTheme.colors.transparent }} bottomDivider={false} title="Medium" rightTitle={`${this.state.networkFees.mediumFee} sat/b`} - rightTitleStyle={{ fontSize: 13, color: BlueApp.settings.alternativeTextColor }} + rightTitleStyle={{ fontSize: 13, color: BlueCurrentTheme.colors.alternativeTextColor }} {...(this.state.selectedFeeType === NetworkTransactionFeeType.MEDIUM - ? { rightIcon: } + ? { rightIcon: } : { hideChevron: true })} /> this.onFeeSelected(NetworkTransactionFeeType.SLOW)} - containerStyle={{ paddingHorizontal: 0, marginHorizontal: 0 }} + containerStyle={{ paddingHorizontal: 0, marginHorizontal: 0, backgroundColor: BlueCurrentTheme.colors.transparent }} bottomDivider={false} title="Slow" rightTitle={`${this.state.networkFees.slowFee} sat/b`} - rightTitleStyle={{ fontSize: 13, color: BlueApp.settings.alternativeTextColor }} + rightTitleStyle={{ fontSize: 13, color: BlueCurrentTheme.colors.alternativeTextColor }} {...(this.state.selectedFeeType === NetworkTransactionFeeType.SLOW - ? { rightIcon: } + ? { rightIcon: } : { hideChevron: true })} /> )} this.customTextInput.focus()}> - Custom + Custom (this.customTextInput = ref)} maxLength={9} style={{ - borderColor: '#d2d2d2', - borderBottomColor: '#d2d2d2', + borderColor: BlueCurrentTheme.colors.formBorder, + borderBottomColor: BlueCurrentTheme.colors.formBorder, borderWidth: 1.0, borderBottomWidth: 0.5, borderRadius: 4, minHeight: 33, maxWidth: 100, minWidth: 44, - backgroundColor: '#f5f5f5', + backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor, textAlign: 'right', }} onFocus={() => this.onCustomFeeTextChange(this.state.customFeeValue)} @@ -2227,13 +2376,13 @@ export class BlueReplaceFeeSuggestions extends Component { placeholder="Custom sat/b" inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID} /> - sat/b + sat/b {this.state.selectedFeeType === NetworkTransactionFeeType.CUSTOM && } - + The total fee rate (satoshi per byte) you want to pay should be higher than {this.props.transactionMinimum} sat/byte @@ -2391,7 +2540,9 @@ export class BlueBitcoinAmount extends Component { {this.state.unit === BitcoinUnit.LOCAL_CURRENCY && ( 0 || amount === BitcoinUnit.MAX ? amount : undefined} placeholderTextColor={ - this.props.disabled ? BlueApp.settings.buttonDisabledTextColor : BlueApp.settings.alternativeTextColor2 + this.props.disabled ? BlueCurrentTheme.colors.buttonDisabledTextColor : BlueCurrentTheme.colors.alternativeTextColor2 } style={{ - color: this.props.disabled ? BlueApp.settings.buttonDisabledTextColor : BlueApp.settings.alternativeTextColor2, + color: this.props.disabled + ? BlueCurrentTheme.colors.buttonDisabledTextColor + : BlueCurrentTheme.colors.alternativeTextColor2, fontWeight: 'bold', fontSize: amount.length > 10 ? 20 : 36, }} @@ -2470,7 +2623,9 @@ export class BlueBitcoinAmount extends Component { {this.state.unit !== BitcoinUnit.LOCAL_CURRENCY && ( ( style={[ tabsStyles.tabRoot, active === i && { - borderColor: BlueApp.settings.buttonAlternativeTextColor, + borderColor: BlueCurrentTheme.colors.buttonAlternativeTextColor, borderBottomWidth: 2, }, { width: width / tabs.length }, @@ -2644,8 +2799,9 @@ export class DynamicQRCode extends Component { @@ -2700,7 +2856,6 @@ const animatedQRCodeStyle = StyleSheet.create({ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', - backgroundColor: '#ccddf9', borderRadius: 25, height: 45, paddingHorizontal: 18, @@ -2711,6 +2866,8 @@ const animatedQRCodeStyle = StyleSheet.create({ justifyContent: 'center', }, text: { - fontSize: 16, + fontSize: 14, + color: BlueCurrentTheme.colors.foregroundColor, + fontWeight: 'bold', }, }); diff --git a/Navigation.js b/Navigation.js index 8164659da..734166eb7 100644 --- a/Navigation.js +++ b/Navigation.js @@ -62,8 +62,7 @@ import LNDViewInvoice from './screen/lnd/lndViewInvoice'; import LNDViewAdditionalInvoiceInformation from './screen/lnd/lndViewAdditionalInvoiceInformation'; import LoadingScreen from './LoadingScreen'; import UnlockWith from './UnlockWith'; -const BlueApp = require('./BlueApp'); -const loc = require('./loc'); +import { BlueNavigationStyle } from './BlueComponents'; const SCREEN_HEIGHT = Dimensions.get('window').height; const defaultScreenOptions = @@ -103,15 +102,9 @@ const WalletsRoot = () => ( name="Settings" component={Settings} options={{ - headerStyle: { - backgroundColor: '#FFFFFF', - borderBottomWidth: 0, - elevation: 0, - shadowColor: 'transparent', - }, - title: '', - headerBackTitleVisible: false, - headerTintColor: '#0c2550', + ...BlueNavigationStyle(), + + headerTitle: '', }} /> @@ -140,18 +133,8 @@ const WalletsRoot = () => ( component={LNDViewAdditionalInvoiceInformation} options={LNDViewAdditionalInvoiceInformation.navigationOptions} /> - + + ); @@ -189,16 +172,7 @@ const SendDetailsRoot = () => ( }} /> - + ); @@ -206,16 +180,7 @@ const LNDCreateInvoiceStack = createStackNavigator(); const LNDCreateInvoiceRoot = () => ( - + ( ); -const HodlHodlStack = createStackNavigator(); -const HodlHodlRoot = () => ( - - - - - - - -); - // LightningScanInvoiceStackNavigator === ScanLndInvoiceStack const ScanLndInvoiceStack = createStackNavigator(); const ScanLndInvoiceRoot = () => ( - + ); @@ -290,6 +235,13 @@ const UnlockWithScreenRoot = () => ( ); +const HodlHodlLoginStack = createStackNavigator(); +const HodlHodlLoginRoot = () => ( + + + +); + const RootStack = createStackNavigator(); const Navigation = () => ( @@ -306,7 +258,9 @@ const Navigation = () => ( - + + + { + const appearance = Appearance.getColorScheme(); + if (appearance) { + this.setState({ appearance }); + } + }; + successfullyAuthenticated = () => { EV(EV.enum.WALLETS_INITIALIZED); NavigationService.dispatch(StackActions.replace('WalletsRoot')); @@ -94,9 +106,10 @@ export default class UnlockWith extends Component { return ; } - const color = Appearance.getColorScheme() === 'dark' ? '#FFFFFF' : '#000000'; + const color = this.state.appearance === 'dark' ? '#FFFFFF' : '#000000'; return ( + @@ -115,9 +128,7 @@ export default class UnlockWith extends Component { <> diff --git a/class/app-storage.js b/class/app-storage.js index 6ca2fd22c..4e574d275 100644 --- a/class/app-storage.js +++ b/class/app-storage.js @@ -39,32 +39,6 @@ export class AppStorage { this.wallets = []; this.tx_metadata = {}; 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', - }; } /** diff --git a/class/wallet-gradient.js b/class/wallet-gradient.js index 80b480e48..591f7e946 100644 --- a/class/wallet-gradient.js +++ b/class/wallet-gradient.js @@ -9,6 +9,7 @@ import { PlaceholderWallet } from './wallets/placeholder-wallet'; import { SegwitBech32Wallet } from './wallets/segwit-bech32-wallet'; import { HDLegacyElectrumSeedP2PKHWallet } from './wallets/hd-legacy-electrum-seed-p2pkh-wallet'; import { HDSegwitElectrumSeedP2WPKHWallet } from './wallets/hd-segwit-electrum-seed-p2wpkh-wallet'; +import { BlueCurrentTheme } from '../components/themes'; export default class WalletGradient { static hdSegwitP2SHWallet = ['#65ceef', '#68bbe1']; @@ -20,7 +21,7 @@ export default class WalletGradient { static hdLegacyBreadWallet = ['#fe6381', '#f99c42']; static defaultGradients = ['#c65afb', '#9053fe']; static lightningCustodianWallet = ['#f1be07', '#f79056']; - static createWallet = '#eef0f4'; + static createWallet = BlueCurrentTheme.colors.lightButton; static gradientsFor(type) { let gradient; diff --git a/components/themes.js b/components/themes.js new file mode 100644 index 000000000..4564ec52b --- /dev/null +++ b/components/themes.js @@ -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; diff --git a/img/scan-white.png b/img/scan-white.png new file mode 100644 index 000000000..2602b23c8 Binary files /dev/null and b/img/scan-white.png differ diff --git a/img/scan-white@2x.png b/img/scan-white@2x.png new file mode 100644 index 000000000..1547fdd11 Binary files /dev/null and b/img/scan-white@2x.png differ diff --git a/img/scan-white@3x.png b/img/scan-white@3x.png new file mode 100644 index 000000000..f11c274d7 Binary files /dev/null and b/img/scan-white@3x.png differ diff --git a/package.json b/package.json index 9ad42505c..bacdd6062 100644 --- a/package.json +++ b/package.json @@ -60,14 +60,14 @@ ] }, "dependencies": { - "@babel/preset-env": "7.10.2", + "@babel/preset-env": "7.10.3", "@react-native-community/async-storage": "1.11.0", "@react-native-community/blur": "3.6.0", "@react-native-community/clipboard": "1.2.2", "@react-native-community/masked-view": "0.1.10", "@react-native-community/slider": "3.0.0", - "@react-navigation/native": "5.5.1", - "@react-navigation/stack": "5.5.1", + "@react-navigation/native": "5.6.1", + "@react-navigation/stack": "5.6.2", "@remobile/react-native-qrcode-local-image": "git+https://github.com/BlueWallet/react-native-qrcode-local-image.git", "@sentry/react-native": "1.4.5", "amplitude-js": "5.11.0", diff --git a/screen/lnd/browser.js b/screen/lnd/browser.js index ea4b30cf2..92d24f446 100644 --- a/screen/lnd/browser.js +++ b/screen/lnd/browser.js @@ -287,12 +287,6 @@ const styles = StyleSheet.create({ }); export default class Browser extends Component { - static navigationOptions = ({ navigation }) => ({ - ...BlueNavigationStyle(navigation, true), - title: 'Lapp Browser', - headerLeft: null, - }); - constructor(props) { super(props); if (!props.route.params.fromSecret) throw new Error('Invalid param'); @@ -435,7 +429,7 @@ export default class Browser extends Component { return ( - + { @@ -516,3 +510,9 @@ Browser.propTypes = { params: PropTypes.object, }), }; + +Browser.navigationOptions = ({ navigation }) => ({ + ...BlueNavigationStyle(navigation, true), + title: 'Lapp Browser', + headerLeft: null, +}); diff --git a/screen/lnd/lndCreateInvoice.js b/screen/lnd/lndCreateInvoice.js index 4852e0416..a5a89e037 100644 --- a/screen/lnd/lndCreateInvoice.js +++ b/screen/lnd/lndCreateInvoice.js @@ -11,6 +11,7 @@ import { TouchableOpacity, Text, StyleSheet, + Image, } from 'react-native'; import { BlueNavigationStyle, @@ -26,6 +27,7 @@ import { BitcoinUnit, Chain } from '../../models/bitcoinUnits'; import * as NavigationService from '../../NavigationService'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import { Icon } from 'react-native-elements'; +import { BlueCurrentTheme } from '../../components/themes'; const currency = require('../../blue_modules/currency'); const BlueApp = require('../../BlueApp'); const EV = require('../../blue_modules/events'); @@ -37,14 +39,13 @@ const styles = StyleSheet.create({ marginVertical: 16, minHeight: 45, alignContent: 'center', - backgroundColor: '#FFFFFF', }, scanRoot: { height: 36, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', - backgroundColor: '#9AA0AA', + backgroundColor: BlueCurrentTheme.colors.scanLabel, borderRadius: 4, paddingVertical: 4, paddingHorizontal: 8, @@ -52,7 +53,7 @@ const styles = StyleSheet.create({ }, scanClick: { marginLeft: 4, - color: BlueApp.settings.inverseForegroundColor, + color: BlueCurrentTheme.colors.inverseForegroundColor, }, walletRoot: { marginBottom: 16, @@ -78,18 +79,18 @@ const styles = StyleSheet.create({ alignItems: 'center', }, walletNameText: { - color: '#0c2550', + color: BlueCurrentTheme.colors.buttonAlternativeTextColor, fontSize: 14, }, walletNameBalance: { - color: '#0c2550', + color: BlueCurrentTheme.colors.buttonAlternativeTextColor, fontSize: 14, fontWeight: '600', marginLeft: 8, marginRight: 4, }, walletNameSats: { - color: '#0c2550', + color: BlueCurrentTheme.colors.buttonAlternativeTextColor, fontSize: 11, fontWeight: '600', textAlignVertical: 'bottom', @@ -102,19 +103,19 @@ const styles = StyleSheet.create({ root: { flex: 1, justifyContent: 'space-between', - backgroundColor: '#FFFFFF', + backgroundColor: BlueCurrentTheme.colors.elevated, }, amount: { flex: 1, - backgroundColor: '#FFFFFF', + backgroundColor: BlueCurrentTheme.colors.elevated, }, fiat: { flexDirection: 'row', - borderColor: '#d2d2d2', - borderBottomColor: '#d2d2d2', + borderColor: BlueCurrentTheme.colors.formBorder, + borderBottomColor: BlueCurrentTheme.colors.formBorder, borderWidth: 1.0, borderBottomWidth: 0.5, - backgroundColor: '#f5f5f5', + backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor, minHeight: 44, height: 44, marginHorizontal: 20, @@ -131,11 +132,6 @@ const styles = StyleSheet.create({ }); export default class LNDCreateInvoice extends Component { - static navigationOptions = ({ navigation }) => ({ - ...BlueNavigationStyle(navigation, true), - title: loc.receive.header, - }); - constructor(props) { super(props); this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow); @@ -356,7 +352,7 @@ export default class LNDCreateInvoice extends Component { }} style={styles.scanRoot} > - + {loc.send.details.scan} ); @@ -478,3 +474,8 @@ LNDCreateInvoice.propTypes = { }), }), }; +LNDCreateInvoice.navigationOptions = ({ navigation }) => ({ + ...BlueNavigationStyle(navigation, true), + headerTitle: loc.receive.header, + headerLeft: null, +}); diff --git a/screen/lnd/lndViewAdditionalInvoiceInformation.js b/screen/lnd/lndViewAdditionalInvoiceInformation.js index fe356dc1d..91479a878 100644 --- a/screen/lnd/lndViewAdditionalInvoiceInformation.js +++ b/screen/lnd/lndViewAdditionalInvoiceInformation.js @@ -13,7 +13,7 @@ import { import PropTypes from 'prop-types'; import QRCode from 'react-native-qrcode-svg'; /** @type {AppStorage} */ -const BlueApp = require('../../BlueApp'); +import { BlueCurrentTheme } from '../../components/themes'; const loc = require('../../loc'); const styles = StyleSheet.create({ @@ -21,9 +21,11 @@ const styles = StyleSheet.create({ flex: 1, justifyContent: 'center', alignItems: 'center', + backgroundColor: BlueCurrentTheme.colors.elevated, }, root: { flex: 1, + backgroundColor: BlueCurrentTheme.colors.elevated, }, wrapper: { flex: 1, @@ -42,11 +44,6 @@ const styles = StyleSheet.create({ }); export default class LNDViewAdditionalInvoiceInformation extends Component { - static navigationOptions = ({ navigation }) => ({ - ...BlueNavigationStyle(), - title: 'Additional Information', - }); - state = { walletInfo: undefined }; async componentDidMount() { @@ -78,8 +75,9 @@ export default class LNDViewAdditionalInvoiceInformation extends Component { logo={require('../../img/qr-code.png')} size={300} logoSize={90} - color={BlueApp.settings.foregroundColor} - logoBackgroundColor={BlueApp.settings.brandingColor} + color={BlueCurrentTheme.colors.foregroundColor} + logoBackgroundColor={BlueCurrentTheme.colors.brandingColor} + backgroundColor={BlueCurrentTheme.colors.background} /> {loc.lndViewInvoice.open_direct_channel} @@ -90,7 +88,7 @@ export default class LNDViewAdditionalInvoiceInformation extends Component { icon={{ name: 'share-alternative', type: 'entypo', - color: BlueApp.settings.buttonTextColor, + color: BlueCurrentTheme.colors.buttonTextColor, }} onPress={async () => { Share.share({ @@ -111,3 +109,8 @@ LNDViewAdditionalInvoiceInformation.propTypes = { params: PropTypes.object, }), }; + +LNDViewAdditionalInvoiceInformation.navigationOptions = ({ navigation }) => ({ + ...BlueNavigationStyle(), + title: 'Additional Information', +}); diff --git a/screen/lnd/lndViewInvoice.js b/screen/lnd/lndViewInvoice.js index ff8332341..6ed1d5567 100644 --- a/screen/lnd/lndViewInvoice.js +++ b/screen/lnd/lndViewInvoice.js @@ -1,11 +1,12 @@ 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 { BlueLoading, BlueText, SafeBlueArea, BlueButton, + SecondButton, BlueCopyTextToClipboard, BlueNavigationStyle, BlueSpacing20, @@ -16,7 +17,7 @@ import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import { Icon } from 'react-native-elements'; import QRCode from 'react-native-qrcode-svg'; /** @type {AppStorage} */ -const BlueApp = require('../../BlueApp'); +import { BlueCurrentTheme } from '../../components/themes'; const loc = require('../../loc'); const EV = require('../../blue_modules/events'); const { width, height } = Dimensions.get('window'); @@ -41,12 +42,12 @@ const styles = StyleSheet.create({ paddingBottom: 8, }, valueText: { - color: '#0f5cc0', + color: BlueCurrentTheme.colors.alternativeTextColor2, fontSize: 32, fontWeight: '600', }, valueSats: { - color: '#0f5cc0', + color: BlueCurrentTheme.colors.alternativeTextColor2, fontSize: 16, marginHorizontal: 4, paddingBottom: 3, @@ -69,6 +70,7 @@ const styles = StyleSheet.create({ paidMark: { marginTop: -100, marginBottom: 16, + backgroundColor: BlueCurrentTheme.colors.success, }, detailsRoot: { flex: 1, @@ -81,12 +83,12 @@ const styles = StyleSheet.create({ alignItems: 'center', }, detailsText: { - color: '#9aa0aa', + color: BlueCurrentTheme.colors.alternativeTextColor, fontSize: 14, marginRight: 8, }, expired: { - backgroundColor: '#ccddf9', + backgroundColor: BlueCurrentTheme.colors.success, width: 120, height: 120, borderRadius: 60, @@ -108,20 +110,11 @@ const styles = StyleSheet.create({ paddingHorizontal: 16, }, additionalInfo: { - backgroundColor: BlueApp.settings.brandingColor, + backgroundColor: BlueCurrentTheme.colors.brandingColor, }, }); 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) { super(props); const invoice = props.route.params.invoice; @@ -212,6 +205,7 @@ export default class LNDViewInvoice extends Component { if (this.state.showPreimageQr) { return ( + Preimage: @@ -220,8 +214,9 @@ export default class LNDViewInvoice extends Component { logo={require('../../img/qr-code.png')} size={this.state.qrCodeHeight} logoSize={90} - color={BlueApp.settings.foregroundColor} - logoBackgroundColor={BlueApp.settings.brandingColor} + color={BlueCurrentTheme.colors.foregroundColor} + backgroundColor={BlueCurrentTheme.colors.background} + logoBackgroundColor={BlueCurrentTheme.colors.brandingColor} /> + {invoice.type === 'paid_invoice' && invoice.value && ( @@ -259,7 +255,7 @@ export default class LNDViewInvoice extends Component { {invoice.payment_preimage && typeof invoice.payment_preimage === 'string' ? ( this.setState({ showPreimageQr: true })}> {loc.send.create.details} - + ) : ( @@ -271,9 +267,10 @@ export default class LNDViewInvoice extends Component { if (invoiceExpiration < now && !invoice.ispaid) { return ( + - + {loc.lndViewInvoice.wasnt_paid_and_expired} @@ -294,6 +291,7 @@ export default class LNDViewInvoice extends Component { // Invoice has not expired, nor has it been paid for. return ( + @@ -302,8 +300,9 @@ export default class LNDViewInvoice extends Component { logo={require('../../img/qr-code.png')} size={this.state.qrCodeHeight} logoSize={90} - color={BlueApp.settings.foregroundColor} - logoBackgroundColor={BlueApp.settings.brandingColor} + color={BlueCurrentTheme.colors.foregroundColor} + logoBackgroundColor={BlueCurrentTheme.colors.brandingColor} + backgroundColor={BlueCurrentTheme.colors.background} /> @@ -318,15 +317,9 @@ export default class LNDViewInvoice extends Component { )} - { - 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} /> @@ -354,3 +347,21 @@ LNDViewInvoice.propTypes = { 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, + }, + }; diff --git a/screen/lnd/scanLndInvoice.js b/screen/lnd/scanLndInvoice.js index 568468143..fbaf6576a 100644 --- a/screen/lnd/scanLndInvoice.js +++ b/screen/lnd/scanLndInvoice.js @@ -27,6 +27,7 @@ import { BitcoinUnit, Chain } from '../../models/bitcoinUnits'; import { Icon } from 'react-native-elements'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import Biometric from '../../class/biometrics'; +import { BlueCurrentTheme } from '../../components/themes'; /** @type {AppStorage} */ const BlueApp = require('../../BlueApp'); const EV = require('../../blue_modules/events'); @@ -58,18 +59,18 @@ const styles = StyleSheet.create({ alignItems: 'center', }, walletWrapLabel: { - color: '#0c2550', + color: BlueCurrentTheme.colors.buttonAlternativeTextColor, fontSize: 14, }, walletWrapBalance: { - color: '#0c2550', + color: BlueCurrentTheme.colors.buttonAlternativeTextColor, fontSize: 14, fontWeight: '600', marginLeft: 4, marginRight: 4, }, walletWrapSats: { - color: '#0c2550', + color: BlueCurrentTheme.colors.buttonAlternativeTextColor, fontSize: 11, fontWeight: '600', textAlignVertical: 'bottom', @@ -77,6 +78,7 @@ const styles = StyleSheet.create({ }, root: { flex: 1, + backgroundColor: BlueCurrentTheme.colors.elevated, }, scroll: { flex: 1, @@ -106,12 +108,6 @@ const styles = StyleSheet.create({ }); export default class ScanLndInvoice extends React.Component { - static navigationOptions = ({ navigation }) => ({ - ...BlueNavigationStyle(navigation, true), - title: loc.send.header, - headerLeft: null, - }); - state = { isLoading: false, isAmountInitiallyEmpty: false, @@ -465,3 +461,9 @@ ScanLndInvoice.propTypes = { }), }), }; + +ScanLndInvoice.navigationOptions = ({ navigation }) => ({ + ...BlueNavigationStyle(navigation, true), + title: loc.send.header, + headerLeft: null, +}); diff --git a/screen/plausibledeniability.js b/screen/plausibledeniability.js index a341ec66a..38a332519 100644 --- a/screen/plausibledeniability.js +++ b/screen/plausibledeniability.js @@ -17,10 +17,6 @@ const styles = StyleSheet.create({ }); export default class PlausibleDeniability extends Component { - static navigationOptions = { - ...BlueNavigationStyle(), - title: loc.plausibledeniability.title, - }; constructor(props) { super(props); @@ -92,3 +88,8 @@ PlausibleDeniability.propTypes = { popToTop: PropTypes.func, }), }; + +PlausibleDeniability.navigationOptions = ({ navigation, route }) => ({ + ...BlueNavigationStyle(), + title: loc.plausibledeniability.title, +}); diff --git a/screen/receive/aztecoRedeem.js b/screen/receive/aztecoRedeem.js index 334a8d60c..0dedc9c4e 100644 --- a/screen/receive/aztecoRedeem.js +++ b/screen/receive/aztecoRedeem.js @@ -51,11 +51,6 @@ const styles = StyleSheet.create({ }); export default class AztecoRedeem extends Component { - static navigationOptions = ({ navigation }) => ({ - ...BlueCreateTxNavigationStyle(navigation), - title: 'Redeem Azte.co voucher', - }); - state = { isLoading: true }; constructor(props) { @@ -156,7 +151,7 @@ export default class AztecoRedeem extends Component { return ( - + Your voucher code is @@ -187,3 +182,8 @@ AztecoRedeem.propTypes = { }), }), }; + +AztecoRedeem.navigationOptions = ({ navigation }) => ({ + ...BlueCreateTxNavigationStyle(navigation), + title: 'Redeem Azte.co voucher', +}); diff --git a/screen/receive/details.js b/screen/receive/details.js index 322d2b162..908b7cb2a 100644 --- a/screen/receive/details.js +++ b/screen/receive/details.js @@ -11,19 +11,19 @@ import { ScrollView, } from 'react-native'; import QRCode from 'react-native-qrcode-svg'; -import { useNavigation, useRoute } from '@react-navigation/native'; +import { useNavigation, useRoute, useTheme } from '@react-navigation/native'; import { - BlueLoading, - SafeBlueArea, + BlueLoadingHook, BlueCopyTextToClipboard, BlueButton, - BlueButtonLink, - BlueNavigationStyle, + SecondButton, + BlueButtonLinkHook, is, BlueBitcoinAmount, BlueText, BlueSpacing20, BlueAlertWalletExportReminder, + BlueNavigationStyle, } from '../../BlueComponents'; import Privacy from '../../Privacy'; import Share from 'react-native-share'; @@ -32,6 +32,7 @@ import Modal from 'react-native-modal'; import HandoffSettings from '../../class/handoff'; import DeeplinkSchemaMatch from '../../class/deeplink-schema-match'; import Handoff from 'react-native-handoff'; +import { BlueCurrentTheme } from '../../components/themes'; /** @type {AppStorage} */ const BlueApp = require('../../BlueApp'); const loc = require('../../loc'); @@ -49,6 +50,89 @@ const ReceiveDetails = () => { const [isCustom, setIsCustom] = useState(false); const [isCustomModalVisible, setIsCustomModalVisible] = useState(false); 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 () => { console.log('receive/details - componentDidMount'); @@ -144,14 +228,6 @@ const ReceiveDetails = () => { setBip21encoded(DeeplinkSchemaMatch.bip21encode(address, { amount, label: customLabel })); }; - const clearCustomAmount = () => { - setIsCustom(false); - setIsCustomModalVisible(false); - setCustomAmount(''); - setCustomLabel(''); - setBip21encoded(DeeplinkSchemaMatch.bip21encode(address)); - }; - const renderCustomAmountModal = () => { return ( @@ -175,9 +251,8 @@ const ReceiveDetails = () => { - + - @@ -206,7 +281,7 @@ const ReceiveDetails = () => { }; return ( - + {isHandOffUseEnabled && address !== undefined && ( { url={`https://blockstream.info/address/${address}`} /> )} - + {isCustom && ( <> @@ -229,7 +304,7 @@ const ReceiveDetails = () => { )} {bip21encoded === undefined ? ( - + ) : ( { logo={require('../../img/qr-code.png')} size={(is.ipad() && 300) || 300} logoSize={90} - color={BlueApp.settings.foregroundColor} - logoBackgroundColor={BlueApp.settings.brandingColor} + color={colors.foregroundColor} + logoBackgroundColor={colors.brandingColor} + backgroundColor={colors.background} ecl="H" /> )} - + - + - {renderCustomAmountModal()} - + {renderCustomAmountModal()} + ); }; @@ -271,75 +339,3 @@ ReceiveDetails.navigationOptions = ({ navigation }) => ({ }); 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, - }, -}); diff --git a/screen/selftest.js b/screen/selftest.js index 0be1ef21f..d5111909f 100644 --- a/screen/selftest.js +++ b/screen/selftest.js @@ -1,8 +1,9 @@ import React, { Component } from 'react'; 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 { SegwitP2SHWallet, LegacyWallet, HDSegwitP2SHWallet, HDSegwitBech32Wallet } from '../class'; +import { BlueCurrentTheme } from '../components/themes'; const bitcoin = require('bitcoinjs-lib'); const BlueCrypto = require('react-native-blue-crypto'); const encryption = require('../blue_modules/encryption'); @@ -11,6 +12,7 @@ const BlueElectrum = require('../blue_modules/BlueElectrum'); const styles = StyleSheet.create({ root: { flex: 1, + backgroundColor: BlueCurrentTheme.colors.background, }, center: { alignItems: 'center', @@ -18,11 +20,6 @@ const styles = StyleSheet.create({ }); export default class Selftest extends Component { - static navigationOptions = () => ({ - ...BlueNavigationStyle(), - title: 'Self test', - }); - constructor(props) { super(props); this.state = { @@ -213,7 +210,7 @@ export default class Selftest extends Component { render() { if (this.state.isLoading) { - return ; + return ; } return ( @@ -261,3 +258,8 @@ Selftest.propTypes = { goBack: PropTypes.func, }), }; + +Selftest.navigationOptions = () => ({ + ...BlueNavigationStyle(), + title: 'Self test', +}); diff --git a/screen/send/broadcast.js b/screen/send/broadcast.js index 119f41df9..5812e1a77 100644 --- a/screen/send/broadcast.js +++ b/screen/send/broadcast.js @@ -12,7 +12,9 @@ import { BlueFormLabel, BlueTextCentered, BlueBigCheckmark, + BlueNavigationStyle, } from '../../BlueComponents'; +import { BlueCurrentTheme } from '../../components/themes'; import BlueElectrum from '../../blue_modules/BlueElectrum'; const bitcoin = require('bitcoinjs-lib'); @@ -23,7 +25,7 @@ const BROADCAST_RESULT = Object.freeze({ error: 'error', }); -export default function Broadcast() { +const Broadcast = () => { const [tx, setTx] = useState(''); const [txHex, setTxHex] = useState(''); const [broadcastResult, setBroadcastResult] = useState(BROADCAST_RESULT.none); @@ -72,7 +74,7 @@ export default function Broadcast() { /> - + )} {BROADCAST_RESULT.success === broadcastResult && } @@ -80,7 +82,13 @@ export default function Broadcast() { ); -} +}; + +export default Broadcast; +Broadcast.navigationOptions = () => ({ + ...BlueNavigationStyle(), + title: 'Broadcast', +}); const styles = StyleSheet.create({ wrapper: { @@ -101,7 +109,7 @@ const styles = StyleSheet.create({ width: '100%', }, link: { - color: 'blue', + color: BlueCurrentTheme.colors.foregroundColor, }, mainCard: { padding: 0, @@ -128,7 +136,7 @@ const styles = StyleSheet.create({ backgroundColor: '#d2f8d6', borderRadius: 4, marginTop: 20, - color: '#37c0a1', + color: BlueCurrentTheme.colors.foregroundColor, fontWeight: '500', fontSize: 14, paddingHorizontal: 16, diff --git a/screen/send/confirm.js b/screen/send/confirm.js index 0fa5abba9..52e62a706 100644 --- a/screen/send/confirm.js +++ b/screen/send/confirm.js @@ -17,20 +17,15 @@ import { SegwitP2SHWallet, SegwitBech32Wallet, } from '../../class'; +import { BlueCurrentTheme } from '../../components/themes'; const loc = require('../../loc'); const EV = require('../../blue_modules/events'); const currency = require('../../blue_modules/currency'); const BlueElectrum = require('../../blue_modules/BlueElectrum'); const Bignumber = require('bignumber.js'); /** @type {AppStorage} */ -const BlueApp = require('../../BlueApp'); export default class Confirm extends Component { - static navigationOptions = () => ({ - ...BlueNavigationStyle(null, false), - title: loc.send.confirm.header, - }); - constructor(props) { super(props); @@ -207,19 +202,19 @@ export default class Confirm extends Component { const styles = StyleSheet.create({ transactionDetailsTitle: { - color: '#0c2550', + color: BlueCurrentTheme.colors.foregroundColor, fontWeight: '500', fontSize: 17, marginBottom: 2, }, transactionDetailsSubtitle: { - color: '#9aa0aa', + color: BlueCurrentTheme.colors.feeText, fontWeight: '500', fontSize: 15, marginBottom: 20, }, transactionAmountFiat: { - color: '#9aa0aa', + color: BlueCurrentTheme.colors.feeText, fontWeight: '500', fontSize: 15, marginVertical: 20, @@ -230,12 +225,12 @@ const styles = StyleSheet.create({ justifyContent: 'center', }, valueValue: { - color: '#0f5cc0', + color: BlueCurrentTheme.colors.alternativeTextColor2, fontSize: 36, fontWeight: '600', }, valueUnit: { - color: '#0f5cc0', + color: BlueCurrentTheme.colors.alternativeTextColor2, fontSize: 16, marginHorizontal: 4, paddingBottom: 6, @@ -248,19 +243,18 @@ const styles = StyleSheet.create({ marginVertical: 8, }, separator: { - backgroundColor: BlueApp.settings.inputBorderColor, height: 0.5, margin: 16, }, root: { flex: 1, paddingTop: 19, + backgroundColor: BlueCurrentTheme.colors.elevated, }, rootWrap: { marginTop: 16, alignItems: 'center', justifyContent: 'space-between', - backgroundColor: '#FFFFFF', }, flat: { maxHeight: '55%', @@ -270,7 +264,6 @@ const styles = StyleSheet.create({ justifyContent: 'center', paddingTop: 16, paddingBottom: 16, - backgroundColor: '#FFFFFF', }, cardText: { color: '#37c0a1', @@ -284,7 +277,7 @@ const styles = StyleSheet.create({ marginVertical: 24, }, txText: { - color: '#0c2550', + color: BlueCurrentTheme.colors.buttonTextColor, fontSize: 15, fontWeight: '500', alignSelf: 'center', @@ -301,3 +294,8 @@ Confirm.propTypes = { params: PropTypes.object, }), }; + +Confirm.navigationOptions = () => ({ + ...BlueNavigationStyle(null, false), + title: loc.send.confirm.header, +}); diff --git a/screen/send/create.js b/screen/send/create.js index a0bb50927..ce9c40eec 100644 --- a/screen/send/create.js +++ b/screen/send/create.js @@ -22,31 +22,11 @@ import { BitcoinUnit } from '../../models/bitcoinUnits'; import { Icon } from 'react-native-elements'; import Share from 'react-native-share'; import RNFS from 'react-native-fs'; -/** @type {AppStorage} */ -const BlueApp = require('../../BlueApp'); +import { BlueCurrentTheme } from '../../components/themes'; const loc = require('../../loc'); const currency = require('../../blue_modules/currency'); export default class SendCreate extends Component { - static navigationOptions = ({ navigation, route }) => { - let headerRight; - if (route.params.exportTXN) { - headerRight = () => ( - - - - ); - } else { - headerRight = null; - } - - return { - ...BlueNavigationStyle, - title: loc.send.create.details, - headerRight, - }; - }; - constructor(props) { super(props); console.log('send/create constructor'); @@ -183,13 +163,13 @@ export default class SendCreate extends Component { const styles = StyleSheet.create({ transactionDetailsTitle: { - color: '#0c2550', + color: BlueCurrentTheme.colors.feeText, fontWeight: '500', fontSize: 17, marginBottom: 2, }, transactionDetailsSubtitle: { - color: '#9aa0aa', + color: BlueCurrentTheme.colors.foregroundColor, fontWeight: '500', fontSize: 15, marginBottom: 20, @@ -201,20 +181,21 @@ const styles = StyleSheet.create({ alignSelf: 'flex-end', }, separator: { - backgroundColor: BlueApp.settings.inputBorderColor, + backgroundColor: BlueCurrentTheme.colors.inputBorderColor, height: 0.5, marginVertical: 16, }, root: { flex: 1, paddingTop: 19, + backgroundColor: BlueCurrentTheme.colors.elevated, }, card: { alignItems: 'center', flex: 1, }, cardText: { - color: '#0c2550', + color: BlueCurrentTheme.colors.foregroundColor, fontWeight: '500', }, cardTx: { @@ -251,3 +232,22 @@ SendCreate.propTypes = { params: PropTypes.object, }), }; + +SendCreate.navigationOptions = ({ navigation, route }) => { + let headerRight; + if (route.params.exportTXN) { + headerRight = () => ( + + + + ); + } else { + headerRight = null; + } + + return { + ...BlueNavigationStyle, + title: loc.send.create.details, + headerRight, + }; +}; diff --git a/screen/send/details.js b/screen/send/details.js index 8fba292c1..24ffb48d5 100644 --- a/screen/send/details.js +++ b/screen/send/details.js @@ -40,6 +40,7 @@ import { BitcoinTransaction } from '../../models/bitcoinTransactionInfo'; import DocumentPicker from 'react-native-document-picker'; import RNFS from 'react-native-fs'; import DeeplinkSchemaMatch from '../../class/deeplink-schema-match'; +import { BlueCurrentTheme } from '../../components/themes'; const bitcoin = require('bitcoinjs-lib'); const currency = require('../../blue_modules/currency'); const BigNumber = require('bignumber.js'); @@ -53,34 +54,36 @@ const styles = StyleSheet.create({ loading: { flex: 1, paddingTop: 20, - backgroundColor: '#FFFFFF', + backgroundColor: BlueCurrentTheme.colors.background, }, root: { flex: 1, justifyContent: 'space-between', - backgroundColor: '#FFFFFF', + backgroundColor: BlueCurrentTheme.colors.elevated, }, scrollViewContent: { flexWrap: 'wrap', flexDirection: 'row', }, modalContent: { - backgroundColor: '#FFFFFF', + backgroundColor: BlueCurrentTheme.colors.modal, padding: 22, justifyContent: 'center', alignItems: 'center', borderTopLeftRadius: 16, borderTopRightRadius: 16, - borderColor: 'rgba(0, 0, 0, 0.1)', + borderTopColor: BlueCurrentTheme.colors.borderTopColor, + borderWidth: BlueCurrentTheme.colors.borderWidth, minHeight: 200, height: 200, }, advancedTransactionOptionsModalContent: { - backgroundColor: '#FFFFFF', + backgroundColor: BlueCurrentTheme.colors.modal, padding: 22, borderTopLeftRadius: 16, borderTopRightRadius: 16, - borderColor: 'rgba(0, 0, 0, 0.1)', + borderTopColor: BlueCurrentTheme.colors.borderTopColor, + borderWidth: BlueCurrentTheme.colors.borderWidth, minHeight: 130, }, bottomModal: { @@ -88,7 +91,7 @@ const styles = StyleSheet.create({ margin: 0, }, feeSliderInput: { - backgroundColor: '#d2f8d6', + backgroundColor: BlueCurrentTheme.colors.feeLabel, minWidth: 127, height: 60, borderRadius: 8, @@ -98,7 +101,7 @@ const styles = StyleSheet.create({ }, feeSliderText: { fontWeight: '600', - color: '#37c0a1', + color: BlueCurrentTheme.colors.feeValue, marginBottom: 0, marginRight: 4, textAlign: 'right', @@ -106,7 +109,7 @@ const styles = StyleSheet.create({ }, feeSliderUnit: { fontWeight: '600', - color: '#37c0a1', + color: BlueCurrentTheme.colors.feeValue, paddingRight: 4, textAlign: 'left', fontSize: 16, @@ -137,7 +140,6 @@ const styles = StyleSheet.create({ marginHorizontal: 56, marginVertical: 16, alignContent: 'center', - backgroundColor: '#FFFFFF', minHeight: 44, }, select: { @@ -159,21 +161,22 @@ const styles = StyleSheet.create({ marginVertical: 4, }, selectLabel: { - color: '#0c2550', + color: BlueCurrentTheme.colors.buttonTextColor, fontSize: 14, }, of: { alignSelf: 'flex-end', marginRight: 18, marginVertical: 8, + color: BlueCurrentTheme.colors.feeText, }, memo: { flexDirection: 'row', - borderColor: '#d2d2d2', - borderBottomColor: '#d2d2d2', + borderColor: BlueCurrentTheme.colors.formBorder, + borderBottomColor: BlueCurrentTheme.colors.formBorder, borderWidth: 1, borderBottomWidth: 0.5, - backgroundColor: '#f5f5f5', + backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor, minHeight: 44, height: 44, marginHorizontal: 20, @@ -194,11 +197,11 @@ const styles = StyleSheet.create({ alignItems: 'center', }, feeLabel: { - color: '#81868e', + color: BlueCurrentTheme.colors.feeText, fontSize: 14, }, feeRow: { - backgroundColor: '#d2f8d6', + backgroundColor: BlueCurrentTheme.colors.feeLabel, minWidth: 40, height: 25, borderRadius: 4, @@ -208,24 +211,19 @@ const styles = StyleSheet.create({ paddingHorizontal: 10, }, feeValue: { - color: '#37c0a1', + color: BlueCurrentTheme.colors.feeValue, marginBottom: 0, marginRight: 4, textAlign: 'right', }, feeUnit: { - color: '#37c0a1', + color: BlueCurrentTheme.colors.feeValue, paddingRight: 4, textAlign: 'left', }, }); 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 }; constructor(props) { @@ -1082,3 +1080,8 @@ SendDetails.propTypes = { }), }), }; + +SendDetails.navigationOptions = ({ navigation, route }) => ({ + ...BlueCreateTxNavigationStyle(navigation, route.params.withAdvancedOptionsMenuButton, route.params.advancedOptionsMenuButtonAction), + title: loc.send.header, +}); diff --git a/screen/send/psbtWithHardwareWallet.js b/screen/send/psbtWithHardwareWallet.js index 5e80e73fb..11d89d71b 100644 --- a/screen/send/psbtWithHardwareWallet.js +++ b/screen/send/psbtWithHardwareWallet.js @@ -17,6 +17,7 @@ import { import Clipboard from '@react-native-community/clipboard'; import { BlueButton, + SecondButton, BlueText, SafeBlueArea, BlueCard, @@ -34,6 +35,7 @@ import RNFS from 'react-native-fs'; import DocumentPicker from 'react-native-document-picker'; import { decodeUR, extractSingleWorkload } from 'bc-ur/dist'; import { Psbt } from 'bitcoinjs-lib'; +import { BlueCurrentTheme } from '../../components/themes'; const loc = require('../../loc'); const EV = require('../../blue_modules/events'); const BlueElectrum = require('../../blue_modules/BlueElectrum'); @@ -45,6 +47,7 @@ const { height, width } = Dimensions.get('window'); const styles = StyleSheet.create({ root: { flex: 1, + backgroundColor: BlueCurrentTheme.colors.elevated, }, scrollViewContent: { flexGrow: 1, @@ -86,15 +89,15 @@ const styles = StyleSheet.create({ flex: 1, }, hexLabel: { - color: '#0c2550', + color: BlueCurrentTheme.colors.foregroundColor, fontWeight: '500', }, hexInput: { - borderColor: '#ebebeb', - backgroundColor: '#d2f8d6', + borderColor: BlueCurrentTheme.colors.formBorder, + backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor, borderRadius: 4, marginTop: 20, - color: '#37c0a1', + color: BlueCurrentTheme.colors.foregroundColor, fontWeight: '500', fontSize: 14, paddingHorizontal: 16, @@ -105,7 +108,7 @@ const styles = StyleSheet.create({ marginVertical: 24, }, hexText: { - color: '#9aa0aa', + color: BlueCurrentTheme.colors.foregroundColor, fontSize: 15, fontWeight: '500', alignSelf: 'center', @@ -117,11 +120,6 @@ const styles = StyleSheet.create({ }); export default class PsbtWithHardwareWallet extends Component { - static navigationOptions = () => ({ - ...BlueNavigationStyle(null, false), - title: loc.send.header, - }); - cameraRef = null; _onReadUniformResource = ur => { @@ -319,7 +317,7 @@ export default class PsbtWithHardwareWallet extends Component { Verify on coinb.in - + ); @@ -394,36 +392,36 @@ export default class PsbtWithHardwareWallet extends Component { - 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. - this.setState({ renderScanner: true, animatedQRCodeData: [] })} title="Scan Signed Transaction" /> - - ({ + ...BlueNavigationStyle(null, false), + title: loc.send.header, +}); diff --git a/screen/send/success.js b/screen/send/success.js index fe28ed773..c0b10bb87 100644 --- a/screen/send/success.js +++ b/screen/send/success.js @@ -6,12 +6,14 @@ import { Text } from 'react-native-elements'; import { BlueButton, SafeBlueArea, BlueCard } from '../../BlueComponents'; import { BitcoinUnit } from '../../models/bitcoinUnits'; import PropTypes from 'prop-types'; +import { BlueCurrentTheme } from '../../components/themes'; const loc = require('../../loc'); const styles = StyleSheet.create({ root: { flex: 1, paddingTop: 19, + backgroundColor: BlueCurrentTheme.colors.elevated, }, amout: { alignItems: 'center', @@ -24,12 +26,12 @@ const styles = StyleSheet.create({ paddingBottom: 16, }, amountValue: { - color: '#0f5cc0', + color: BlueCurrentTheme.colors.alternativeTextColor2, fontSize: 36, fontWeight: '600', }, amountUnit: { - color: '#0f5cc0', + color: BlueCurrentTheme.colors.alternativeTextColor2, fontSize: 16, marginHorizontal: 4, paddingBottom: 6, @@ -61,11 +63,6 @@ const styles = StyleSheet.create({ }); export default class Success extends Component { - static navigationOptions = { - headerShown: false, - gesturesEnabled: false, - }; - constructor(props) { super(props); console.log('send/success constructor'); @@ -103,7 +100,26 @@ export default class Success extends Component { )} - + { const [isAdancedModeEnabled, setIsAdancedModeEnabled] = useState(false); const [isHandoffUseEnabled, setIsHandoffUseEnabled] = useState(false); const { navigate } = useNavigation(); + const { colors } = useTheme(); const onAdvancedModeSwitch = async value => { await BlueApp.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 ? ( ) : ( - - - {BlueApp.getWallets().length > 1 && ( - <> - navigate('DefaultView')} title="On Launch" chevron /> - - )} - {Platform.OS === 'ios' ? ( - <> - - - - When enabled, you will be able to view selected wallets, and transactions, using your other Apple iCloud connected devices. - - - - - ) : null} - - - - When enabled, you will see advanced options such as different wallet types, the ability to specify the LNDHub instance you wish - to connect to and custom entropy during wallet creation. - - - - - + + {BlueApp.getWallets().length > 1 && ( + <> + navigate('DefaultView')} title="On Launch" chevron /> + + )} + {Platform.OS === 'ios' ? ( + <> + + + + When enabled, you will be able to view selected wallets, and transactions, using your other Apple iCloud connected devices. + + + + + ) : null} + + + + When enabled, you will see advanced options such as different wallet types, the ability to specify the LNDHub instance you wish to + connect to and custom entropy during wallet creation. + + + + ); }; @@ -85,12 +98,4 @@ GeneralSettings.navigationOptions = () => ({ title: 'General', }); -GeneralSettings.propTypes = { - navigation: PropTypes.shape({ - navigate: PropTypes.func, - popToTop: PropTypes.func, - goBack: PropTypes.func, - }), -}; - export default GeneralSettings; diff --git a/screen/settings/NetworkSettings.js b/screen/settings/NetworkSettings.js index 27429adc7..551e42492 100644 --- a/screen/settings/NetworkSettings.js +++ b/screen/settings/NetworkSettings.js @@ -1,42 +1,48 @@ import React, { useEffect, useState } from 'react'; -import { ScrollView, TouchableOpacity, StyleSheet } from 'react-native'; -import { BlueNavigationStyle, BlueLoading, SafeBlueArea, BlueListItem } from '../../BlueComponents'; -import { useNavigation } from '@react-navigation/native'; +import { ScrollView, StyleSheet } from 'react-native'; +import { SafeBlueArea, BlueListItemHooks, BlueNavigationStyle, BlueLoadingHook } from '../../BlueComponents'; +import { useNavigation, useTheme } from '@react-navigation/native'; const loc = require('../../loc'); - -const styles = StyleSheet.create({ - root: { - flex: 1, - }, -}); - const NetworkSettings = () => { const [isLoading, setIsLoading] = useState(true); const { navigate } = useNavigation(); + const { colors } = useTheme(); + const styles = StyleSheet.create({ + root: { + flex: 1, + backgroundColor: colors.background, + }, + }); useEffect(() => { setIsLoading(false); }, []); + const navigateToElectrumSettings = () => { + navigate('ElectrumSettings'); + }; + + const navigateToLightningSettings = () => { + navigate('LightningSettings'); + }; + + const navigateToBroadcast = () => { + navigate('Broadcast'); + }; return isLoading ? ( - + ) : ( - navigate('ElectrumSettings')} chevron /> - navigate('LightningSettings')} - chevron - /> - navigate('Broadcast')} chevron /> + + + ); }; -NetworkSettings.navigationOptions = { +NetworkSettings.navigationOptions = () => ({ ...BlueNavigationStyle(), title: 'Network', -}; +}); export default NetworkSettings; diff --git a/screen/settings/about.js b/screen/settings/about.js index 5021d21fe..53ad3e3aa 100644 --- a/screen/settings/about.js +++ b/screen/settings/about.js @@ -1,15 +1,15 @@ import React, { useEffect, useState } from 'react'; 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 { BlueTextCentered, - BlueLoading, BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, + BlueListItemHooks, BlueNavigationStyle, - BlueListItem, + BlueLoadingHook, } from '../../BlueComponents'; import { getApplicationName, getVersion, getBundleId, getBuildNumber } from 'react-native-device-info'; import Rate, { AndroidMarket } from 'react-native-rate'; @@ -17,46 +17,46 @@ import Rate, { AndroidMarket } from 'react-native-rate'; const { width, height } = Dimensions.get('window'); const loc = require('../../loc/'); -const styles = StyleSheet.create({ - root: { - flex: 1, - }, - center: { - justifyContent: 'center', - alignItems: 'center', - marginTop: 54, - }, - logo: { - width: 102, - height: 124, - }, - textFree: { - maxWidth: 260, - marginVertical: 24, - color: '#9AA0AA', - fontSize: 15, - textAlign: 'center', - fontWeight: '500', - }, - textBackup: { - maxWidth: 260, - marginBottom: 40, - color: '#0C2550', - fontSize: 15, - textAlign: 'center', - fontWeight: '500', - }, - buildWith: { - backgroundColor: '#f9f9f9', - padding: 16, - paddingTop: 0, - borderRadius: 8, - }, -}); - const About = () => { const [isLoading, setIsLoading] = useState(true); const { navigate } = useNavigation(); + const { colors } = useTheme(); + const styles = StyleSheet.create({ + root: { + flex: 1, + }, + center: { + justifyContent: 'center', + alignItems: 'center', + marginTop: 54, + }, + logo: { + width: 102, + height: 124, + }, + textFree: { + maxWidth: 260, + marginVertical: 24, + color: '#9AA0AA', + fontSize: 15, + textAlign: 'center', + fontWeight: '500', + }, + textBackup: { + maxWidth: 260, + marginBottom: 40, + color: colors.foregroundColor, + fontSize: 15, + textAlign: 'center', + fontWeight: '500', + }, + buildWith: { + backgroundColor: colors.inputBackgroundColor, + padding: 16, + paddingTop: 0, + borderRadius: 8, + }, + }); useEffect(() => { setIsLoading(false); @@ -103,7 +103,7 @@ const About = () => { }; return isLoading ? ( - + ) : ( @@ -115,7 +115,7 @@ const About = () => { - { onPress={handleOnTwitterPress} title="Follow us on Twitter" /> - { onPress={handleOnTelegramPress} title="Telegram chat" /> - { Electrum server - { onPress={handleOnReleaseNotesPress} title="Release notes" /> - - { About.navigationOptions = () => ({ ...BlueNavigationStyle(), - title: loc.settings.about, + headerTitle: loc.settings.about, }); export default About; diff --git a/screen/settings/currency.js b/screen/settings/currency.js index 5db59df8e..499386aa7 100644 --- a/screen/settings/currency.js +++ b/screen/settings/currency.js @@ -1,28 +1,31 @@ import React, { useState, useEffect } from 'react'; 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 { Icon } from 'react-native-elements'; import { FiatUnit } from '../../models/fiatUnit'; +import { useTheme } from '@react-navigation/native'; const loc = require('../../loc'); const currency = require('../../blue_modules/currency'); const data = Object.values(FiatUnit); -const styles = StyleSheet.create({ - flex: { - flex: 1, - }, - activity: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - }, -}); - const Currency = () => { const [isSavingNewPreferredCurrency, setIsSavingNewPreferredCurrency] = useState(false); const [selectedCurrency, setSelectedCurrency] = useState(null); + const { colors } = useTheme(); + const styles = StyleSheet.create({ + flex: { + flex: 1, + backgroundColor: colors.background, + }, + activity: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: colors.background, + }, + }); useEffect(() => { const fetchCurrency = async () => { @@ -49,7 +52,7 @@ const Currency = () => { extraData={data} renderItem={({ item }) => { return ( - { }} /> - Prices are obtained from CoinDesk + Prices are obtained from CoinDesk ); diff --git a/screen/settings/defaultView.js b/screen/settings/defaultView.js index 795523ef0..17b5922d3 100644 --- a/screen/settings/defaultView.js +++ b/screen/settings/defaultView.js @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react'; -import { TouchableOpacity, View, TouchableWithoutFeedback, StyleSheet } from 'react-native'; -import { SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle, BlueListItem } from '../../BlueComponents'; +import { View, TouchableWithoutFeedback, StyleSheet } from 'react-native'; +import { SafeBlueArea, BlueCard, BlueNavigationStyle, BlueListItemHooks, BlueTextHooks } from '../../BlueComponents'; import OnAppLaunch from '../../class/on-app-launch'; import { useNavigation } from '@react-navigation/native'; const BlueApp = require('../../BlueApp'); @@ -56,7 +56,7 @@ const DefaultView = () => { return ( - { }} /> - When disabled, BlueWallet will immediately open the selected wallet at launch. + When disabled, BlueWallet will immediately open the selected wallet at launch. {!viewAllWalletsEnabled && ( - + )} diff --git a/screen/settings/electrumSettings.js b/screen/settings/electrumSettings.js index 5d38cd503..37ce6e276 100644 --- a/screen/settings/electrumSettings.js +++ b/screen/settings/electrumSettings.js @@ -4,8 +4,9 @@ import { View, TextInput, StyleSheet } from 'react-native'; import { AppStorage } from '../../class'; import AsyncStorage from '@react-native-community/async-storage'; import { ScrollView } from 'react-native-gesture-handler'; -import { BlueLoading, BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueNavigationStyle, BlueText } from '../../BlueComponents'; -import PropTypes from 'prop-types'; +import { BlueLoading, BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../../BlueComponents'; +import { BlueCurrentTheme } from '../../components/themes'; + const loc = require('../../loc'); const BlueElectrum = require('../../blue_modules/BlueElectrum'); @@ -15,7 +16,7 @@ const styles = StyleSheet.create({ }, status: { textAlign: 'center', - color: '#9AA0AA', + color: BlueCurrentTheme.colors.feeText, marginBottom: 4, }, connectWrap: { @@ -33,13 +34,13 @@ const styles = StyleSheet.create({ borderRadius: 20, }, containerConnected: { - backgroundColor: '#D2F8D6', + backgroundColor: BlueCurrentTheme.colors.feeLabel, }, containerDisconnected: { backgroundColor: '#F8D2D2', }, textConnected: { - color: '#37C0A1', + color: BlueCurrentTheme.colors.feeValue, fontWeight: 'bold', }, textDisconnected: { @@ -48,19 +49,19 @@ const styles = StyleSheet.create({ }, hostname: { textAlign: 'center', - color: '#0C2550', + color: BlueCurrentTheme.colors.foregroundColor, }, explain: { - color: '#9AA0AA', + color: BlueCurrentTheme.colors.feeText, marginBottom: -24, }, inputWrap: { flexDirection: 'row', - borderColor: '#d2d2d2', - borderBottomColor: '#d2d2d2', + borderColor: BlueCurrentTheme.colors.formBorder, + borderBottomColor: BlueCurrentTheme.colors.formBorder, borderWidth: 1, borderBottomWidth: 0.5, - backgroundColor: '#f5f5f5', + backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor, minHeight: 44, height: 44, alignItems: 'center', @@ -76,11 +77,6 @@ const styles = StyleSheet.create({ }); export default class ElectrumSettings extends Component { - static navigationOptions = () => ({ - ...BlueNavigationStyle(), - title: loc.settings.electrum_settings, - }); - constructor(props) { super(props); this.state = { @@ -223,9 +219,7 @@ export default class ElectrumSettings extends Component { } } -ElectrumSettings.propTypes = { - navigation: PropTypes.shape({ - navigate: PropTypes.func, - goBack: PropTypes.func, - }), -}; +ElectrumSettings.navigationOptions = () => ({ + ...BlueNavigationStyle(), + title: loc.settings.electrum_settings, +}); diff --git a/screen/settings/encryptStorage.js b/screen/settings/encryptStorage.js index 97251f9dc..f305bf340 100644 --- a/screen/settings/encryptStorage.js +++ b/screen/settings/encryptStorage.js @@ -1,106 +1,100 @@ /* 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 { - BlueLoading, - BlueHeaderDefaultSub, - BlueListItem, + BlueLoadingHook, SafeBlueArea, - BlueNavigationStyle, BlueSpacing20, BlueCard, - BlueText, + BlueListItemHooks, + BlueHeaderDefaultSubHooks, + BlueTextHooks, + BlueNavigationStyle, } from '../../BlueComponents'; -import PropTypes from 'prop-types'; import { AppStorage } from '../../class'; +import { useNavigation, StackActions } from '@react-navigation/native'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import Biometric from '../../class/biometrics'; +import { colors } from 'react-native-elements'; const BlueApp: AppStorage = require('../../BlueApp'); const prompt = require('../../blue_modules/prompt'); const loc = require('../../loc'); -const styles = StyleSheet.create({ - root: { - flex: 1, - }, -}); - -export default class EncryptStorage extends Component { - static navigationOptions = () => ({ - ...BlueNavigationStyle(), - title: 'Security', +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({ + root: { + flex: 1, + backgroundColor: colors.background, + }, }); - constructor(props) { - super(props); - this.state = { - isLoading: true, - language: loc.getLanguage(), - deleteWalletsAfterUninstall: false, - biometrics: { isDeviceBiometricCapable: false, isBiometricsEnabled: false, biometricsType: '' }, - }; - } - - async componentDidMount() { + const initialState = useCallback(async () => { const isBiometricsEnabled = await Biometric.isBiometricUseEnabled(); const isDeviceBiometricCapable = await Biometric.isDeviceBiometricCapable(); const biometricsType = (await Biometric.biometricType()) || 'biometrics'; - this.setState({ - isLoading: false, - advancedModeEnabled: await BlueApp.isAdancedModeEnabled(), - storageIsEncrypted: await BlueApp.storageIsEncrypted(), - deleteWalletsAfterUninstall: await BlueApp.isDeleteWalletAfterUninstallEnabled(), - biometrics: { isBiometricsEnabled, isDeviceBiometricCapable, biometricsType }, - }); - } + const deleteWalletsAfterUninstall = await BlueApp.isDeleteWalletAfterUninstallEnabled(); + const isStorageEncrypted = await BlueApp.storageIsEncrypted(); + setBiometrics(biometrics); + setStorageIsEncrypted(isStorageEncrypted); + setDeleteWalletsAfterUninstall(deleteWalletsAfterUninstall); + 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(() => { - this.setState({ isLoading: false }); + setIsLoading(false); }); try { await BlueApp.decryptStorage(password); - this.props.navigation.popToTop(); + dispatch(StackActions.popToTop()); } catch (e) { if (password) { alert(loc._.bad_password); ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); } - this.setState({ - isLoading: false, - storageIsEncrypted: await BlueApp.storageIsEncrypted(), - deleteWalletAfterUninstall: await BlueApp.isDeleteWalletAfterUninstallEnabled(), - }); + + setIsLoading(false); + setStorageIsEncrypted(await BlueApp.storageIsEncrypted()); + setDeleteWalletsAfterUninstall(await BlueApp.isDeleteWalletAfterUninstallEnabled()); } - }; + }, [dispatch]); - onDeleteWalletsAfterUninstallSwitch = async value => { + const onDeleteWalletsAfterUninstallSwitch = useCallback(async value => { await BlueApp.setResetOnAppUninstallTo(value); - this.setState({ deleteWalletsAfterUninstall: value }); - }; + setDeleteWalletsAfterUninstall(value); + }, []); - onEncryptStorageSwitch = value => { - this.setState({ isLoading: true }, async () => { + const onEncryptStorageSwitch = useCallback( + async value => { + setIsLoading(true); if (value === true) { let p1 = await prompt(loc.settings.password, loc.settings.password_explain).catch(() => { - this.setState({ isLoading: false }); + setIsLoading(false); p1 = undefined; }); if (!p1) { - this.setState({ isLoading: false }); + setIsLoading(false); return; } const p2 = await prompt(loc.settings.password, loc.settings.retype_password).catch(() => { - this.setState({ isLoading: false }); + setIsLoading(false); }); if (p1 === p2) { await BlueApp.encryptStorage(p1); - this.setState({ - isLoading: false, - storageIsEncrypted: await BlueApp.storageIsEncrypted(), - }); + setIsLoading(false); + setStorageIsEncrypted(await BlueApp.storageIsEncrypted()); } else { - this.setState({ isLoading: false }); + setIsLoading(false); alert(loc.settings.passwords_do_not_match); } } else { @@ -111,93 +105,100 @@ export default class EncryptStorage extends Component { { text: loc.send.details.cancel, style: 'cancel', - onPress: () => this.setState({ isLoading: false }), + onPress: () => setIsLoading(false), }, { text: loc._.ok, style: 'destructive', - onPress: this.decryptStorage, + onPress: decryptStorage, }, ], { cancelable: false }, ); } - }); + }, + [decryptStorage], + ); + + const onUseBiometricSwitch = useCallback( + async value => { + const isBiometricsEnabled = { + isDeviceBiometricCapable: biometrics.isDeviceBiometricCapable, + isBiometricsEnabled: biometrics.isBiometricsEnabled, + biometricsType: biometrics.biometricsType, + }; + if (await Biometric.unlockWithBiometrics()) { + isBiometricsEnabled.isBiometricsEnabled = value; + await Biometric.setBiometricUseEnabled(value); + setBiometrics(isBiometricsEnabled); + } + }, + [biometrics], + ); + + const navigateToPlausibleDeniability = () => { + navigate('PlausibleDeniability'); }; - onUseBiometricSwitch = async value => { - const isBiometricsEnabled = this.state.biometrics; - if (await Biometric.unlockWithBiometrics()) { - isBiometricsEnabled.isBiometricsEnabled = value; - await Biometric.setBiometricUseEnabled(value); - this.setState({ biometrics: isBiometricsEnabled }); - } - }; - - render() { - if (this.state.isLoading) { - return ; - } - - return ( - - - {this.state.biometrics.isDeviceBiometricCapable && ( - <> - - - - - {this.state.biometrics.biometricsType} will be used to confirm your identity prior to making a transaction, unlocking, - exporting or deleting a wallet. {this.state.biometrics.biometricsType} will not be used to unlock an encrypted storage. - - - - - )} - - - {Platform.OS === 'ios' && ( - + + + ) : ( + + + {biometrics.isDeviceBiometricCapable && ( + <> + + - )} - {this.state.storageIsEncrypted && ( - this.props.navigation.navigate('PlausibleDeniability')} - disabled={!this.state.storageIsEncrypted} - title={loc.settings.plausible_deniability} - chevron - testID="PlausibleDeniabilityButton" - Component={TouchableOpacity} - /> - )} - - - ); - } -} - -EncryptStorage.propTypes = { - navigation: PropTypes.shape({ - navigate: PropTypes.func, - popToTop: PropTypes.func, - goBack: PropTypes.func, - }), + + + {biometrics.biometricsType} will be used to confirm your identity prior to making a transaction, unlocking, exporting or + deleting a wallet. {biometrics.biometricsType} will not be used to unlock an encrypted storage. + + + + + )} + + + {Platform.OS === 'ios' && ( + + )} + {storageIsEncrypted && ( + + )} + + + ); }; + +export default EncryptStorage; +EncryptStorage.navigationOptions = () => ({ + ...BlueNavigationStyle(), + headerTitle: 'Security', +}); diff --git a/screen/settings/language.js b/screen/settings/language.js index f1f709c53..2116048f6 100644 --- a/screen/settings/language.js +++ b/screen/settings/language.js @@ -1,81 +1,59 @@ -import React, { Component } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { FlatList, StyleSheet } from 'react-native'; -import { BlueLoading, BlueText, SafeBlueArea, BlueListItem, BlueCard, BlueNavigationStyle } from '../../BlueComponents'; -import PropTypes from 'prop-types'; +import { SafeBlueArea, BlueListItemHooks, BlueCard, BlueLoadingHook, BlueNavigationStyle, BlueTextHooks } from '../../BlueComponents'; import { Icon } from 'react-native-elements'; import { AvailableLanguages } from '../../loc/languages'; const loc = require('../../loc'); -const styles = StyleSheet.create({ - flex: { - flex: 1, - }, -}); - -export default class Language extends Component { - static navigationOptions = () => ({ - ...BlueNavigationStyle(), - title: loc.settings.language, +const Language = () => { + const [isLoading, setIsLoading] = useState(true); + const [language, setLanguage] = useState(loc.getLanguage()); + const styles = StyleSheet.create({ + flex: { + flex: 1, + }, }); - constructor(props) { - super(props); - this.state = { - isLoading: true, - language: loc.getLanguage(), - availableLanguages: AvailableLanguages, - }; - } + useEffect(() => { + setIsLoading(false); + }, []); - async componentDidMount() { - this.setState({ - isLoading: false, - }); - } - - renderItem = ({ item }) => { - return ( - { - console.log('setLanguage', item.value); - loc.saveLanguage(item.value); - return this.setState({ language: item.value }); - }} - title={item.label} - {...(this.state.language === item.value - ? { - rightIcon: , - } - : { hideChevron: true })} - /> - ); - }; - - render() { - if (this.state.isLoading) { - return ; - } - - return ( - - `${index}`} - data={this.state.availableLanguages} - extraData={this.state.availableLanguages} - renderItem={this.renderItem} + const renderItem = useCallback( + ({ item }) => { + return ( + { + console.log('setLanguage', item.value); + loc.saveLanguage(item.value); + setLanguage(item.value); + }} + title={item.label} + {...(language === item.value + ? { + rightIcon: , + } + : { hideChevron: true })} /> - - When selecting a new language, restarting BlueWallet may be required for the change to take effect. - - - ); - } -} + ); + }, + [language], + ); -Language.propTypes = { - navigation: PropTypes.shape({ - navigate: PropTypes.func, - goBack: PropTypes.func, - }), + return isLoading ? ( + + ) : ( + + `${index}`} data={AvailableLanguages} renderItem={renderItem} /> + + When selecting a new language, restarting BlueWallet may be required for the change to take effect. + + + ); }; + +Language.navigationOptions = () => ({ + ...BlueNavigationStyle(), + headerTitle: loc.settings.language, +}); + +export default Language; diff --git a/screen/settings/licensing.js b/screen/settings/licensing.js index 39af6124d..bd6dc5053 100644 --- a/screen/settings/licensing.js +++ b/screen/settings/licensing.js @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; 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} */ const styles = StyleSheet.create({ @@ -17,34 +17,34 @@ const Licensing = () => { }, []); return isLoading ? ( - + ) : ( - MIT License + MIT License - Copyright (c) 2018-2020 BlueWallet Services + Copyright (c) 2018-2020 BlueWallet Services - + 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, 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: - + - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + - + 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 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. - + diff --git a/screen/settings/lightningSettings.js b/screen/settings/lightningSettings.js index 6705971ac..e44bc62bb 100644 --- a/screen/settings/lightningSettings.js +++ b/screen/settings/lightningSettings.js @@ -1,14 +1,22 @@ /* global alert */ -import React, { Component } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { View, TextInput, Linking, StyleSheet } from 'react-native'; import { AppStorage } from '../../class'; import AsyncStorage from '@react-native-community/async-storage'; -import { BlueLoading, BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueNavigationStyle, BlueText } from '../../BlueComponents'; -import PropTypes from 'prop-types'; +import { + BlueSpacing20, + BlueButton, + SafeBlueArea, + BlueCard, + BlueNavigationStyle, + BlueLoadingHook, + BlueTextHooks, +} from '../../BlueComponents'; import { Button } from 'react-native-elements'; import { LightningCustodianWallet } from '../../class/wallets/lightning-custodian-wallet'; -/** @type {AppStorage} */ -const BlueApp = require('../../BlueApp'); +import { useTheme } from '@react-navigation/native'; +import { BlueCurrentTheme } from '../../components/themes'; + const loc = require('../../loc'); const styles = StyleSheet.create({ @@ -17,11 +25,11 @@ const styles = StyleSheet.create({ }, uri: { flexDirection: 'row', - borderColor: '#d2d2d2', - borderBottomColor: '#d2d2d2', + borderColor: BlueCurrentTheme.colors.formBorder, + borderBottomColor: BlueCurrentTheme.colors.formBorder, borderWidth: 1, borderBottomWidth: 0.5, - backgroundColor: '#f5f5f5', + backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor, minHeight: 44, height: 44, alignItems: 'center', @@ -39,94 +47,80 @@ const styles = StyleSheet.create({ }, }); -export default class LightningSettings extends Component { - static navigationOptions = () => ({ - ...BlueNavigationStyle(), - title: loc.settings.lightning_settings, - }); +const LightningSettings = () => { + const [isLoading, setIsLoading] = useState(true); + const [URI, setURI] = useState(); + const { colors } = useTheme(); - constructor(props) { - super(props); - this.state = { - isLoading: true, - }; - } + useEffect(() => { + AsyncStorage.getItem(AppStorage.LNDHUB) + .then(setURI) + .then(() => setIsLoading(false)) + .catch(() => setIsLoading(false)); + }, []); - async componentDidMount() { - const URI = await AsyncStorage.getItem(AppStorage.LNDHUB); - - this.setState({ - isLoading: false, - URI, - }); - } - - save = () => { - this.setState({ isLoading: true }, async () => { - this.state.URI = this.state.URI ? this.state.URI : ''; - try { - if (this.state.URI) { - await LightningCustodianWallet.isValidNodeAddress(this.state.URI); - // validating only if its not empty. empty means use default - } - await AsyncStorage.setItem(AppStorage.LNDHUB, this.state.URI); - alert('Your changes have been saved successfully'); - } catch (error) { - alert('Not a valid LndHub URI'); - console.log(error); + const save = useCallback(async () => { + setIsLoading(true); + try { + if (URI) { + await LightningCustodianWallet.isValidNodeAddress(URI); + // validating only if its not empty. empty means use default } - this.setState({ isLoading: false }); - }); - }; + await AsyncStorage.setItem(AppStorage.LNDHUB, URI); + alert('Your changes have been saved successfully'); + } catch (error) { + alert('Not a valid LndHub URI'); + console.log(error); + } + setIsLoading(false); + }, [URI]); - render() { - return ( - - - {loc.settings.lightning_settings_explain} - + return ( + + + {loc.settings.lightning_settings_explain} + -