diff --git a/components/BlurredBalanceView.tsx b/components/BlurredBalanceView.tsx
index 23e369c29d..82cd75b45a 100644
--- a/components/BlurredBalanceView.tsx
+++ b/components/BlurredBalanceView.tsx
@@ -1,18 +1,27 @@
import React from 'react';
-import { ImageBackground, StyleSheet, View } from 'react-native';
+import { StyleSheet, View } from 'react-native';
import { Icon } from '@rneui/themed';
export const BlurredBalanceView = () => {
return (
- {/* @ts-ignore: We just want the blur effect. No source prop needed */}
-
+
);
};
const styles = StyleSheet.create({
- container: { flexDirection: 'row', alignItems: 'center', borderRadius: 9 },
- background: { backgroundColor: '#FFFFFF', opacity: 0.5, height: 30, width: 110, marginRight: 8, borderRadius: 9 },
+ container: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ borderRadius: 9,
+ },
+ background: {
+ backgroundColor: 'rgba(255, 255, 255, 0.5)',
+ height: 30,
+ width: 110,
+ marginRight: 8,
+ borderRadius: 9,
+ },
});
diff --git a/components/HeaderMenuButton.tsx b/components/HeaderMenuButton.tsx
new file mode 100644
index 0000000000..ac4dc38b99
--- /dev/null
+++ b/components/HeaderMenuButton.tsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import ToolTipMenu from './TooltipMenu';
+import { useTheme } from './themes';
+import { Icon } from '@rneui/themed';
+import { Platform } from 'react-native';
+import { Action } from './types';
+
+interface HeaderMenuButtonProps {
+ onPressMenuItem: (id: string) => void;
+ actions: Action[];
+ disabled?: boolean;
+}
+
+const HeaderMenuButton: React.FC = ({ onPressMenuItem, actions, disabled }) => {
+ const { colors } = useTheme();
+ const styleProps = Platform.OS === 'android' ? { iconStyle: { transform: [{ rotate: '90deg' }] } } : {};
+ return (
+
+
+
+ );
+};
+
+export default HeaderMenuButton;
diff --git a/components/TransactionsNavigationHeader.tsx b/components/TransactionsNavigationHeader.tsx
index 98b86f98d9..89417af70f 100644
--- a/components/TransactionsNavigationHeader.tsx
+++ b/components/TransactionsNavigationHeader.tsx
@@ -1,6 +1,6 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import Clipboard from '@react-native-clipboard/clipboard';
-import { I18nManager, Image, LayoutAnimation, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
+import { I18nManager, Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import { LightningCustodianWallet, MultisigHDWallet } from '../class';
import WalletGradient from '../class/wallet-gradient';
@@ -11,6 +11,7 @@ import { FiatUnit } from '../models/fiatUnit';
import { BlurredBalanceView } from './BlurredBalanceView';
import { useSettings } from '../hooks/context/useSettings';
import ToolTipMenu from './TooltipMenu';
+import useAnimateOnChange from '../hooks/useAnimateOnChange';
interface TransactionsNavigationHeaderProps {
wallet: TWallet;
@@ -36,16 +37,14 @@ const TransactionsNavigationHeader: React.FC
wallet
.allowOnchainAddress()
.then((value: boolean) => setAllowOnchainAddress(value))
- .catch((e: Error) => {
- console.log('This LNDhub wallet does not have an onchain address API.');
+ .catch(() => {
+ console.error('This LNDhub wallet does not have an onchain address API.');
setAllowOnchainAddress(false);
});
}
}, [wallet]);
useEffect(() => {
- LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
-
setWallet(initialWallet);
}, [initialWallet]);
@@ -61,7 +60,6 @@ const TransactionsNavigationHeader: React.FC
}, [unit, wallet]);
const handleBalanceVisibility = useCallback(() => {
- LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
onWalletBalanceVisibilityChange?.(!wallet.hideBalance);
}, [onWalletBalanceVisibilityChange, wallet.hideBalance]);
@@ -76,7 +74,6 @@ const TransactionsNavigationHeader: React.FC
newWalletPreferredUnit = BitcoinUnit.BTC;
}
- LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
onWalletUnitChange(newWalletPreferredUnit);
};
@@ -116,7 +113,6 @@ const TransactionsNavigationHeader: React.FC
}, []);
const balance = useMemo(() => {
- LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
const hideBalance = wallet.hideBalance;
const balanceFormatted =
unit === BitcoinUnit.LOCAL_CURRENCY
@@ -165,6 +161,11 @@ const TransactionsNavigationHeader: React.FC
}
}, [wallet.type]);
+ useAnimateOnChange(balance);
+ useAnimateOnChange(wallet.hideBalance);
+ useAnimateOnChange(unit);
+ useAnimateOnChange(wallet.getID?.());
+
return (
) : (
(value: T) => {
+ const prevValue = useRef(undefined);
+ useEffect(() => {
+ if (prevValue.current !== undefined && prevValue.current !== value) {
+ LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
+ }
+ prevValue.current = value;
+ }, [value]);
+};
+export default useAnimateOnChange;
diff --git a/package-lock.json b/package-lock.json
index cac898f9f5..1c78a28ff0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -89,7 +89,7 @@
"react-native-quick-actions": "0.3.13",
"react-native-randombytes": "3.6.1",
"react-native-rate": "1.2.12",
- "react-native-reanimated": "3.15.3",
+ "react-native-reanimated": "3.15.4",
"react-native-safe-area-context": "4.11.0",
"react-native-screens": "3.34.0",
"react-native-secure-key-store": "github:BlueWallet/react-native-secure-key-store#2076b4849e88aa0a78e08bfbb4ce3923e0925cbc",
@@ -20882,9 +20882,9 @@
}
},
"node_modules/react-native-reanimated": {
- "version": "3.15.3",
- "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.15.3.tgz",
- "integrity": "sha512-5QBk/7PZvZ98Adxm4MRyglwzsRzReTQIe4Hd2wbBBAZ68IC4OYKvsc8cPEjgx3/1mG8HgHFYhbcDe5U2RjeFqw==",
+ "version": "3.15.4",
+ "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.15.4.tgz",
+ "integrity": "sha512-jcpHE+MnsvSbClhHgAFoken7SnaHrUJ5gVA8BUw8S1j6rkrw2VzRpht6cxn14NlqYx5ytjfG9IXJDOzq8tFvfw==",
"license": "MIT",
"dependencies": {
"@babel/plugin-transform-arrow-functions": "^7.0.0-0",
diff --git a/package.json b/package.json
index 50f6883ef2..3bf239ca15 100644
--- a/package.json
+++ b/package.json
@@ -153,7 +153,7 @@
"react-native-quick-actions": "0.3.13",
"react-native-randombytes": "3.6.1",
"react-native-rate": "1.2.12",
- "react-native-reanimated": "3.15.3",
+ "react-native-reanimated": "3.15.4",
"react-native-safe-area-context": "4.11.0",
"react-native-screens": "3.34.0",
"react-native-secure-key-store": "github:BlueWallet/react-native-secure-key-store#2076b4849e88aa0a78e08bfbb4ce3923e0925cbc",
diff --git a/screen/receive/details.js b/screen/receive/details.js
index 5b0a48c781..0c78a1f5d1 100644
--- a/screen/receive/details.js
+++ b/screen/receive/details.js
@@ -35,9 +35,8 @@ import { SuccessView } from '../send/success';
import { useStorage } from '../../hooks/context/useStorage';
import { HandOffActivityType } from '../../components/types';
import SegmentedControl from '../../components/SegmentControl';
-import ToolTipMenu from '../../components/TooltipMenu';
-import { Icon } from '@rneui/themed';
import { CommonToolTipActions } from '../../typings/CommonToolTipActions';
+import HeaderMenuButton from '../../components/HeaderMenuButton';
const segmentControlValues = [loc.wallets.details_address, loc.bip47.payment_code];
@@ -157,7 +156,7 @@ const ReceiveDetails = () => {
const toolTipActions = useMemo(() => {
const action = CommonToolTipActions.PaymentCode;
- action.menuState = wallet.isBIP47Enabled();
+ action.menuState = wallet?.isBIP47Enabled();
return [action];
}, [wallet]);
@@ -167,12 +166,9 @@ const ReceiveDetails = () => {
}, [onEnablePaymentsCodeSwitchValue]);
const HeaderRight = useMemo(
- () => (
-
-
-
- ),
- [colors.foregroundColor, onPressMenuItem, toolTipActions],
+ () => ,
+
+ [onPressMenuItem, toolTipActions],
);
const handleClose = useCallback(() => {
@@ -195,11 +191,11 @@ const ReceiveDetails = () => {
);
useEffect(() => {
- wallet.allowBIP47() &&
- !wallet.isBIP47Enabled() &&
+ wallet?.allowBIP47() &&
+ wallet?.isBIP47Enabled() &&
setOptions({
- headerLeft: () => (wallet.isBIP47Enabled() ? null : HeaderLeft),
- headerRight: () => (wallet.isBIP47Enabled() ? HeaderLeft : HeaderRight),
+ headerLeft: () => (wallet?.isBIP47Enabled() ? null : HeaderLeft),
+ headerRight: () => (wallet?.isBIP47Enabled() ? HeaderLeft : HeaderRight),
});
}, [HeaderLeft, HeaderRight, colors.foregroundColor, setOptions, wallet]);
@@ -480,7 +476,7 @@ const ReceiveDetails = () => {
contentContainerStyle={[styles.root, stylesHook.root]}
keyboardShouldPersistTaps="always"
>
- {wallet?.allowBIP47() && wallet.isBIP47Enabled() && (
+ {wallet?.allowBIP47() && wallet?.isBIP47Enabled() && (
{
const setHeaderRightOptions = () => {
navigation.setOptions({
// eslint-disable-next-line react/no-unstable-nested-components
- headerRight: () => (
-
-
-
- ),
+ headerRight: () => ,
});
};
@@ -1499,11 +1487,6 @@ const styles = StyleSheet.create({
alignItems: 'center',
paddingHorizontal: 10,
},
- advancedOptions: {
- minWidth: 40,
- height: 40,
- justifyContent: 'center',
- },
frozenContainer: {
flexDirection: 'row',
justifyContent: 'center',
diff --git a/screen/send/psbtMultisigQRCode.js b/screen/send/psbtMultisigQRCode.js
index 0bff5a4a72..c06143f8e4 100644
--- a/screen/send/psbtMultisigQRCode.js
+++ b/screen/send/psbtMultisigQRCode.js
@@ -60,7 +60,7 @@ const PsbtMultisigQRCode = () => {
};
const openScanner = async () => {
- const scanned = await scanQrHelper(name, true, undefined);
+ const scanned = await scanQrHelper(name, true);
onBarScanned({ data: scanned });
};
diff --git a/screen/wallets/Add.tsx b/screen/wallets/Add.tsx
index 1e6b6355c2..5a9021a8ee 100644
--- a/screen/wallets/Add.tsx
+++ b/screen/wallets/Add.tsx
@@ -25,11 +25,10 @@ import WalletButton from '../../components/WalletButton';
import loc from '../../loc';
import { Chain } from '../../models/bitcoinUnits';
import { useStorage } from '../../hooks/context/useStorage';
-import ToolTipMenu from '../../components/TooltipMenu';
-import { Icon } from '@rneui/themed';
import { CommonToolTipActions } from '../../typings/CommonToolTipActions';
import { Action } from '../../components/types';
import { getLNDHub } from '../../helpers/lndHub';
+import HeaderMenuButton from '../../components/HeaderMenuButton';
enum ButtonSelected {
// @ts-ignore: Return later to update
@@ -228,9 +227,7 @@ const WalletsAdd: React.FC = () => {
const HeaderRight = useMemo(
() => (
- {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
if (id === HDSegwitBech32Wallet.type) {
@@ -246,11 +243,9 @@ const WalletsAdd: React.FC = () => {
}
}}
actions={toolTipActions}
- >
-
-
+ />
),
- [colors.foregroundColor, handleOnLightningButtonPressed, navigateToEntropy, toolTipActions],
+ [handleOnLightningButtonPressed, navigateToEntropy, toolTipActions],
);
useEffect(() => {
diff --git a/screen/wallets/import.js b/screen/wallets/import.js
index 6455620be0..efbcdd1be6 100644
--- a/screen/wallets/import.js
+++ b/screen/wallets/import.js
@@ -11,11 +11,10 @@ import {
DoneAndDismissKeyboardInputAccessory,
DoneAndDismissKeyboardInputAccessoryViewID,
} from '../../components/DoneAndDismissKeyboardInputAccessory';
-import { Icon } from '@rneui/themed';
import { CommonToolTipActions } from '../../typings/CommonToolTipActions';
import { useKeyboard } from '../../hooks/useKeyboard';
-import ToolTipMenu from '../../components/TooltipMenu';
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
+import HeaderMenuButton from '../../components/HeaderMenuButton';
const WalletsImport = () => {
const navigation = useExtendedNavigation();
@@ -140,18 +139,8 @@ const WalletsImport = () => {
}, [askPassphrase, searchAccounts]);
const HeaderRight = useMemo(
- () => (
-
-
-
- ),
- [toolTipOnPressMenuItem, toolTipActions, colors.foregroundColor],
+ () => ,
+ [toolTipOnPressMenuItem, toolTipActions],
);
// Adding the ToolTipMenu to the header
diff --git a/tests/e2e/bluewallet.spec.js b/tests/e2e/bluewallet.spec.js
index a62828594e..bacf3ff3f4 100644
--- a/tests/e2e/bluewallet.spec.js
+++ b/tests/e2e/bluewallet.spec.js
@@ -677,9 +677,9 @@ describe('BlueWallet UI Tests - no wallets', () => {
await element(by.id('MnemonicInput')).replaceText(
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
);
- await element(by.id('HeaderRightButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Passphrase')).tap();
- await element(by.id('HeaderRightButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Search accounts')).tap();
await element(by.id('DoImport')).tap();
await sleep(1000);
diff --git a/tests/e2e/bluewallet2.spec.js b/tests/e2e/bluewallet2.spec.js
index c75a53107e..3320bc4ed4 100644
--- a/tests/e2e/bluewallet2.spec.js
+++ b/tests/e2e/bluewallet2.spec.js
@@ -202,23 +202,23 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await element(by.text('OK')).tap();
// lest add another two outputs
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Add Recipient')).tap();
await yo('Transaction1'); // adding a recipient autoscrolls it to the last one
await element(by.id('AddressInput').withAncestor(by.id('Transaction1'))).replaceText('grs1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnp8h967');
await element(by.id('BitcoinAmountInput').withAncestor(by.id('Transaction1'))).replaceText('0.0002\n');
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Add Recipient')).tap();
await yo('Transaction2'); // adding a recipient autoscrolls it to the last one
// remove last output, check if second output is shown
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Remove Recipient')).tap();
await yo('Transaction1');
// adding it again
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Add Recipient')).tap();
await yo('Transaction2'); // adding a recipient autoscrolls it to the last one
await element(by.id('AddressInput').withAncestor(by.id('Transaction2'))).replaceText('grs1qh6tf004ty7z7un2v5ntu4mkf630545gv2pf49l');
@@ -227,7 +227,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
// remove second output
await element(by.id('Transaction2')).swipe('right', 'fast', NaN, 0.2);
await sleep(5000);
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Remove Recipient')).tap();
// creating and verifying. tx should have 3 outputs
@@ -275,7 +275,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
// first send MAX output
await element(by.id('AddressInput')).replaceText('grs1qnapskphjnwzw2w3dk4anpxntunc77v6q7dpwsl');
await element(by.id('BitcoinAmountInput')).typeText('0.0001\n');
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Use Full Balance')).tap();
await element(by.text('OK')).tap();
@@ -294,7 +294,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
// add second output with amount
await device.pressBack();
await device.pressBack();
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Add Recipient')).tap();
await yo('Transaction1');
await element(by.id('AddressInput').withAncestor(by.id('Transaction1'))).replaceText('grs1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnp8h967');
@@ -334,7 +334,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await element(by.text('Imported HD SegWit (BIP84 Bech32 Native)')).tap();
await element(by.id('SendButton')).tap();
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Sign a transaction')).tap();
// tapping 5 times invisible button is a backdoor:
@@ -452,14 +452,14 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await device.pressBack();
await element(by.text('Imported HD SegWit (BIP84 Bech32 Native)')).tap();
await element(by.id('SendButton')).tap();
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Insert Contact')).tap();
await element(by.id('ContactListItem0')).tap();
await element(by.id('BitcoinAmountInput')).typeText('0.0001\n');
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Add Recipient')).tap();
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Insert Contact')).tap();
await element(by.id('ContactListItem1')).tap();
await element(by.id('BitcoinAmountInput')).atIndex(1).typeText('0.0002\n');
@@ -601,7 +601,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await yo('WalletsList');
await element(by.text('Imported HD SegWit (BIP84 Bech32 Native)')).tap();
await element(by.id('SendButton')).tap();
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Coin Control')).tap();
await waitFor(element(by.id('Loading'))) // wait for outputs to be loaded
.not.toExist()
@@ -620,7 +620,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await element(by.text('test2')).atIndex(0).tap();
await element(by.id('UseCoin')).tap();
await element(by.id('AddressInput')).replaceText('grs1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnp8h967');
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Use Full Balance')).tap();
await element(by.text('OK')).tap();
// setting fee rate:
@@ -649,7 +649,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
// create tx with unfrozen input
await element(by.id('SendButton')).tap();
await element(by.id('AddressInput')).replaceText('grs1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnp8h967');
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Use Full Balance')).tap();
await element(by.text('OK')).tap();
// setting fee rate:
diff --git a/tests/e2e/bluewallet3.spec.js b/tests/e2e/bluewallet3.spec.js
index a080d54e5c..85a9068b8f 100644
--- a/tests/e2e/bluewallet3.spec.js
+++ b/tests/e2e/bluewallet3.spec.js
@@ -55,7 +55,7 @@ describe('BlueWallet UI Tests - import Watch-only wallet (zpub)', () => {
await element(by.id('SendButton')).tap();
await element(by.text('OK')).tap();
- await element(by.id('advancedOptionsMenuButton')).tap();
+ await element(by.id('HeaderMenuButton')).tap();
await element(by.text('Import Transaction (QR)')).tap(); // opens camera
// produced by real Keystone device using MNEMONICS_KEYSTONE