mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-01-19 05:45:15 +01:00
Merge pull request #2699 from BlueWallet/tooltipadd
ADD: Long press Transaction Row to get shortcuts
This commit is contained in:
commit
36c17a708b
@ -1,5 +1,5 @@
|
||||
/* eslint react/prop-types: "off", react-native/no-inline-styles: "off" */
|
||||
import React, { Component, useState, useMemo, useCallback, useContext } from 'react';
|
||||
import React, { Component, useState, useMemo, useCallback, useContext, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Icon, Input, Text, Header, ListItem, Avatar } from 'react-native-elements';
|
||||
import {
|
||||
@ -11,6 +11,7 @@ import {
|
||||
InputAccessoryView,
|
||||
Keyboard,
|
||||
KeyboardAvoidingView,
|
||||
Linking,
|
||||
PixelRatio,
|
||||
Platform,
|
||||
PlatformColor,
|
||||
@ -42,6 +43,7 @@ import loc, { formatBalance, formatBalanceWithoutSuffix, formatBalancePlain, rem
|
||||
import Lnurl from './class/lnurl';
|
||||
import { BlueStorageContext } from './blue_modules/storage-context';
|
||||
import ToolTipMenu from './components/TooltipMenu';
|
||||
|
||||
/** @type {AppStorage} */
|
||||
const { height, width } = Dimensions.get('window');
|
||||
const aspectRatio = height / width;
|
||||
@ -300,15 +302,6 @@ export class BlueWalletNavigationHeader extends Component {
|
||||
this.tooltip.current.showMenu();
|
||||
};
|
||||
|
||||
handleToolTipOnPress = item => {
|
||||
console.warn(item);
|
||||
if (item === 'copyToClipboard') {
|
||||
this.handleCopyPress();
|
||||
} else if (item === 'walletBalanceVisibility') {
|
||||
this.handleBalanceVisibility();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const balance =
|
||||
!this.state.wallet.hideBalance &&
|
||||
@ -374,7 +367,6 @@ export class BlueWalletNavigationHeader extends Component {
|
||||
},
|
||||
]
|
||||
}
|
||||
onPress={this.handleToolTipOnPress}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
style={styles.balance}
|
||||
@ -610,6 +602,7 @@ export const BlueListItem = React.memo(props => {
|
||||
topDivider={props.topDivider !== undefined ? props.topDivider : false}
|
||||
testID={props.testID}
|
||||
onPress={props.onPress}
|
||||
onLongPress={props.onLongPress}
|
||||
disabled={props.disabled}
|
||||
>
|
||||
{props.leftAvatar && <Avatar>{props.leftAvatar}</Avatar>}
|
||||
@ -1260,6 +1253,9 @@ export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = Bitco
|
||||
}),
|
||||
[colors.lightBorder],
|
||||
);
|
||||
const toolTip = useRef();
|
||||
const copyToolTip = useRef();
|
||||
const listItemRef = useRef();
|
||||
|
||||
const title = useMemo(() => {
|
||||
if (item.confirmations === 0) {
|
||||
@ -1446,30 +1442,117 @@ export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = Bitco
|
||||
}, [item, wallets]);
|
||||
|
||||
const onLongPress = useCallback(() => {
|
||||
toolTip.current.showMenu();
|
||||
}, []);
|
||||
|
||||
const handleOnExpandNote = useCallback(() => {
|
||||
if (subtitleNumberOfLines === 1) {
|
||||
setSubtitleNumberOfLines(0);
|
||||
}
|
||||
}, [subtitleNumberOfLines]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const subtitleProps = useMemo(() => ({ numberOfLines: subtitleNumberOfLines }), [subtitleNumberOfLines]);
|
||||
const handleOnCopyTap = useCallback(() => {
|
||||
toolTip.current.hideMenu();
|
||||
setTimeout(copyToolTip.current.showMenu, 400);
|
||||
}, []);
|
||||
const handleOnCopyAmountTap = useCallback(() => Clipboard.setString(rowTitle), [rowTitle]);
|
||||
const handleOnCopyTransactionID = useCallback(() => Clipboard.setString(item.hash), [item.hash]);
|
||||
const handleOnCopyNote = useCallback(() => Clipboard.setString(subtitle), [subtitle]);
|
||||
const handleOnViewOnBlockExplorer = useCallback(() => {
|
||||
const url = `https://blockstream.info/tx/${item.hash}`;
|
||||
Linking.canOpenURL(url).then(supported => {
|
||||
if (supported) {
|
||||
Linking.openURL(url);
|
||||
}
|
||||
});
|
||||
}, [item.hash]);
|
||||
const handleCopyOpenInBlockExplorerPress = useCallback(() => {
|
||||
Clipboard.setString(`https://blockstream.info/tx/${item.hash}`);
|
||||
}, [item.hash]);
|
||||
const toolTipActions = useMemo(() => {
|
||||
const actions = [
|
||||
{
|
||||
id: 'copy',
|
||||
text: loc.transactions.details_copy,
|
||||
onPress: handleOnCopyTap,
|
||||
},
|
||||
];
|
||||
if (item.hash) {
|
||||
actions.push({
|
||||
id: 'open_in_blockExplorer',
|
||||
text: loc.transactions.details_show_in_block_explorer,
|
||||
onPress: handleOnViewOnBlockExplorer,
|
||||
});
|
||||
}
|
||||
if (subtitle && subtitleNumberOfLines === 1) {
|
||||
actions.push({
|
||||
id: 'expandNote',
|
||||
text: loc.transactions.expand_note,
|
||||
onPress: handleOnExpandNote,
|
||||
});
|
||||
}
|
||||
return actions;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [item.hash, subtitle, rowTitle, subtitleNumberOfLines, txMetadata]);
|
||||
|
||||
const copyToolTipActions = useMemo(() => {
|
||||
const actions = [];
|
||||
if (rowTitle !== loc.lnd.expired) {
|
||||
actions.push({
|
||||
id: 'copyAmount',
|
||||
text: loc.send.create_amount,
|
||||
onPress: handleOnCopyAmountTap,
|
||||
});
|
||||
}
|
||||
|
||||
if (item.hash) {
|
||||
actions.push(
|
||||
{
|
||||
id: 'copyTX_ID',
|
||||
text: loc.transactions.transaction_id,
|
||||
onPress: handleOnCopyTransactionID,
|
||||
},
|
||||
{
|
||||
id: 'copy_blockExplorer',
|
||||
text: loc.transactions.block_explorer_link,
|
||||
onPress: handleCopyOpenInBlockExplorerPress,
|
||||
},
|
||||
);
|
||||
}
|
||||
if (subtitle) {
|
||||
actions.push({
|
||||
id: 'copyNote',
|
||||
text: loc.transactions.note,
|
||||
onPress: handleOnCopyNote,
|
||||
});
|
||||
}
|
||||
return actions;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [toolTipActions]);
|
||||
|
||||
return (
|
||||
<View style={{ marginHorizontal: 4 }}>
|
||||
<BlueListItem
|
||||
leftAvatar={avatar}
|
||||
title={title}
|
||||
titleNumberOfLines={subtitleNumberOfLines}
|
||||
subtitle={subtitle}
|
||||
subtitleProps={subtitleProps}
|
||||
onPress={onPress}
|
||||
onLongPress={onLongPress}
|
||||
chevron={false}
|
||||
Component={TouchableOpacity}
|
||||
rightTitle={rowTitle}
|
||||
rightTitleStyle={rowTitleStyle}
|
||||
containerStyle={containerStyle}
|
||||
/>
|
||||
</View>
|
||||
<TouchableWithoutFeedback ref={listItemRef}>
|
||||
<View style={{ marginHorizontal: 4 }}>
|
||||
<ToolTipMenu ref={toolTip} anchorRef={listItemRef} actions={toolTipActions} />
|
||||
<ToolTipMenu ref={copyToolTip} anchorRef={listItemRef} actions={copyToolTipActions} />
|
||||
<BlueListItem
|
||||
leftAvatar={avatar}
|
||||
title={title}
|
||||
titleNumberOfLines={subtitleNumberOfLines}
|
||||
subtitle={subtitle}
|
||||
subtitleProps={subtitleProps}
|
||||
onPress={onPress}
|
||||
chevron={false}
|
||||
Component={TouchableOpacity}
|
||||
rightTitle={rowTitle}
|
||||
rightTitleStyle={rowTitleStyle}
|
||||
containerStyle={containerStyle}
|
||||
onLongPress={onLongPress}
|
||||
/>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -5,7 +5,8 @@ import showPopupMenu from 'react-native-popup-menu-android';
|
||||
|
||||
const ToolTipMenu = (props, ref) => {
|
||||
const handleToolTipSelection = selection => {
|
||||
props.onPress(selection.id);
|
||||
const action = props.actions.find(action => action.id === selection.id);
|
||||
action.onPress();
|
||||
};
|
||||
|
||||
const showMenu = () => {
|
||||
@ -13,18 +14,21 @@ const ToolTipMenu = (props, ref) => {
|
||||
showPopupMenu(actions, handleToolTipSelection, props.anchorRef.current);
|
||||
};
|
||||
|
||||
const hideMenu = () => {
|
||||
console.log('not implemented');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
ref.current.showMenu = showMenu;
|
||||
ref.current.hideMenu = hideMenu;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [ref]);
|
||||
}, [ref, props.actions]);
|
||||
|
||||
return <View ref={ref}>{props.children}</View>;
|
||||
return <View ref={ref} />;
|
||||
};
|
||||
|
||||
export default forwardRef(ToolTipMenu);
|
||||
ToolTipMenu.propTypes = {
|
||||
actions: PropTypes.arrayOf(PropTypes.shape).isRequired,
|
||||
anchorRef: PropTypes.node,
|
||||
children: PropTypes.node,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
};
|
||||
|
@ -11,8 +11,14 @@ const ToolTipMenu = (props, ref) => {
|
||||
toolTip.current?.showMenu();
|
||||
};
|
||||
|
||||
const hideMenu = () => {
|
||||
console.log('Hiding ToolTip');
|
||||
toolTip.current?.hideMenu();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
ref.current.showMenu = showMenu;
|
||||
ref.current.hideMenu = hideMenu;
|
||||
}, [ref]);
|
||||
|
||||
return (
|
||||
|
@ -1,5 +1,22 @@
|
||||
const ToolTipMenu = props => {
|
||||
return props.children;
|
||||
import React, { forwardRef, useEffect } from 'react';
|
||||
import { View } from 'react-native';
|
||||
|
||||
const ToolTipMenu = (props, ref) => {
|
||||
const showMenu = () => {
|
||||
console.log('not implemented');
|
||||
};
|
||||
|
||||
const hideMenu = () => {
|
||||
console.log('not implemented');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
ref.current.showMenu = showMenu;
|
||||
ref.current.hideMenu = hideMenu;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [ref]);
|
||||
|
||||
return <View ref={ref} />;
|
||||
};
|
||||
|
||||
export default ToolTipMenu;
|
||||
export default forwardRef(ToolTipMenu);
|
||||
|
@ -333,6 +333,10 @@
|
||||
"cancel_no": "This transaction is not replaceable.",
|
||||
"cancel_title": "Cancel this transaction (RBF)",
|
||||
"confirmations_lowercase": "{confirmations} confirmations",
|
||||
"transaction_id": "Transaction ID",
|
||||
"note": "Note",
|
||||
"expand_note": "Expand Note",
|
||||
"block_explorer_link": "Block Explorer Link",
|
||||
"cpfp_create": "Create",
|
||||
"cpfp_exp": "We will create another transaction that spends your unconfirmed transaction. The total fee will be higher than the original transaction fee, so it should be mined faster. This is called CPFP—Child Pays for Parent.",
|
||||
"cpfp_no_bump": "This transaction is not bumpable.",
|
||||
|
@ -171,7 +171,6 @@ const ReceiveDetails = () => {
|
||||
onPress: handleShareQRCode,
|
||||
},
|
||||
]}
|
||||
onPress={handleShareQRCode}
|
||||
/>
|
||||
|
||||
<QRCode
|
||||
|
@ -204,7 +204,6 @@ const TransactionsDetails = () => {
|
||||
onPress: handleCopyPress,
|
||||
},
|
||||
]}
|
||||
onPress={handleCopyPress}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
ref={openTransactionOnBlockExplorerRef}
|
||||
|
Loading…
Reference in New Issue
Block a user