Merge pull request #2699 from BlueWallet/tooltipadd

ADD: Long press Transaction Row to get shortcuts
This commit is contained in:
Marcos Rodriguez Vélez 2021-02-25 22:39:54 -05:00 committed by GitHub
commit 36c17a708b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 150 additions and 38 deletions

View File

@ -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,15 +1442,101 @@ 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 (
<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}
@ -1462,14 +1544,15 @@ export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = Bitco
subtitle={subtitle}
subtitleProps={subtitleProps}
onPress={onPress}
onLongPress={onLongPress}
chevron={false}
Component={TouchableOpacity}
rightTitle={rowTitle}
rightTitleStyle={rowTitleStyle}
containerStyle={containerStyle}
onLongPress={onLongPress}
/>
</View>
</TouchableWithoutFeedback>
);
});

View File

@ -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,
};

View File

@ -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 (

View File

@ -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);

View File

@ -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.",

View File

@ -171,7 +171,6 @@ const ReceiveDetails = () => {
onPress: handleShareQRCode,
},
]}
onPress={handleShareQRCode}
/>
<QRCode

View File

@ -204,7 +204,6 @@ const TransactionsDetails = () => {
onPress: handleCopyPress,
},
]}
onPress={handleCopyPress}
/>
<TouchableOpacity
ref={openTransactionOnBlockExplorerRef}