REF: BlueCopyToClipboardButton and BlueCopyToClipboard to TSX

This commit is contained in:
Marcos Rodriguez Velez 2024-03-27 00:37:43 -04:00
parent d5b4e7e9c1
commit 8d6c8e00aa
No known key found for this signature in database
GPG Key ID: 6030B2F48CCE86D7
19 changed files with 128 additions and 115 deletions

View File

@ -863,7 +863,7 @@ export class AppStorage {
if (doNotTrackValue) {
await DefaultPreference.set(AppStorage.DO_NOT_TRACK, '1');
AsyncStorage.removeItem(AppStorage.DO_NOT_TRACK);
}
}
} catch (_) {}
return false;
};

View File

@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
import { Icon, Text, Header } from 'react-native-elements';
import {
ActivityIndicator,
Animated,
Dimensions,
Image,
InputAccessoryView,
@ -204,80 +203,6 @@ export const BluePrivateBalance = () => {
);
};
export const BlueCopyToClipboardButton = ({ stringToCopy, displayText = false }) => {
return (
<TouchableOpacity accessibilityRole="button" onPress={() => Clipboard.setString(stringToCopy)}>
<Text style={{ fontSize: 13, fontWeight: '400', color: '#68bbe1' }}>{displayText || loc.transactions.details_copy}</Text>
</TouchableOpacity>
);
};
export class BlueCopyTextToClipboard extends Component {
static propTypes = {
text: PropTypes.string,
truncated: PropTypes.bool,
};
static defaultProps = {
text: '',
truncated: false,
};
constructor(props) {
super(props);
this.state = { hasTappedText: false, address: props.text };
}
static getDerivedStateFromProps(props, state) {
if (state.hasTappedText) {
return { hasTappedText: state.hasTappedText, address: state.address, truncated: props.truncated };
} else {
return { hasTappedText: state.hasTappedText, address: props.text, truncated: props.truncated };
}
}
copyToClipboard = () => {
this.setState({ hasTappedText: true }, () => {
Clipboard.setString(this.props.text);
this.setState({ address: loc.wallets.xpub_copiedToClipboard }, () => {
setTimeout(() => {
this.setState({ hasTappedText: false, address: this.props.text });
}, 1000);
});
});
};
render() {
return (
<View style={{ justifyContent: 'center', alignItems: 'center', paddingHorizontal: 16 }}>
<TouchableOpacity
accessibilityRole="button"
onPress={this.copyToClipboard}
disabled={this.state.hasTappedText}
testID="BlueCopyTextToClipboard"
>
<Animated.Text
style={styleCopyTextToClipboard.address}
{...(this.props.truncated ? { numberOfLines: 1, ellipsizeMode: 'middle' } : { numberOfLines: 0 })}
testID="AddressValue"
>
{this.state.address}
</Animated.Text>
</TouchableOpacity>
</View>
);
}
}
const styleCopyTextToClipboard = StyleSheet.create({
address: {
marginVertical: 32,
fontSize: 15,
color: '#9aa0aa',
textAlign: 'center',
},
});
export const BlueCard = props => {
return <View {...props} style={{ padding: 20 }} />;
};

View File

@ -0,0 +1,60 @@
import Clipboard from '@react-native-clipboard/clipboard';
import React, { useState, useEffect } from 'react';
import { View, TouchableOpacity, Animated, StyleSheet } from 'react-native';
import loc from '../loc';
type CopyTextToClipboardProps = {
text: string;
truncated?: boolean;
};
const styleCopyTextToClipboard = StyleSheet.create({
address: {
marginVertical: 32,
fontSize: 15,
color: '#9aa0aa',
textAlign: 'center',
},
});
export const CopyTextToClipboard: React.FC<CopyTextToClipboardProps> = ({ text, truncated }) => {
const [hasTappedText, setHasTappedText] = useState(false);
const [address, setAddress] = useState(text);
// Replace `getDerivedStateFromProps`
useEffect(() => {
if (!hasTappedText) {
setAddress(text);
}
}, [text, hasTappedText]);
const copyToClipboard = () => {
setHasTappedText(true);
Clipboard.setString(text);
setAddress(loc.wallets.xpub_copiedToClipboard); // Replace with your localization logic if needed
setTimeout(() => {
setHasTappedText(false);
setAddress(text);
}, 1000);
};
return (
<View style={styles.container}>
<TouchableOpacity accessibilityRole="button" onPress={copyToClipboard} disabled={hasTappedText} testID="CopyTextToClipboard">
<Animated.Text
style={styleCopyTextToClipboard.address}
{...(truncated ? { numberOfLines: 1, ellipsizeMode: 'middle' } : { numberOfLines: 0 })}
testID="AddressValue"
>
{address}
</Animated.Text>
</TouchableOpacity>
</View>
);
};
export default CopyTextToClipboard;
const styles = StyleSheet.create({
container: { justifyContent: 'center', alignItems: 'center', paddingHorizontal: 16 },
});

View File

@ -0,0 +1,27 @@
import Clipboard from '@react-native-clipboard/clipboard';
import React from 'react';
import { TouchableOpacity, Text, StyleSheet } from 'react-native';
import loc from '../loc';
type CopyToClipboardButtonProps = {
stringToCopy: string;
displayText?: string;
};
export const CopyToClipboardButton: React.FC<CopyToClipboardButtonProps> = ({ stringToCopy, displayText }) => {
const onPress = () => {
Clipboard.setString(stringToCopy);
};
return (
<TouchableOpacity accessibilityRole="button" onPress={onPress}>
<Text style={styles.text}>{displayText && displayText.length > 0 ? displayText : loc.transactions.details_copy}</Text>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
text: { fontSize: 13, fontWeight: '400', color: '#68bbe1' },
});
export default CopyToClipboardButton;

View File

@ -1,7 +1,7 @@
import React, { useContext, useEffect, useState } from 'react';
import { View, Share, StyleSheet } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native';
import { BlueCopyTextToClipboard, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import { BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
@ -10,6 +10,7 @@ import presentAlert from '../../components/Alert';
import { useTheme } from '../../components/themes';
import Button from '../../components/Button';
import SafeArea from '../../components/SafeArea';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
const LNDViewAdditionalInvoiceInformation = () => {
const { walletID } = useRoute().params;
@ -60,7 +61,7 @@ const LNDViewAdditionalInvoiceInformation = () => {
</View>
<BlueSpacing20 />
<BlueText>{loc.lndViewInvoice.open_direct_channel}</BlueText>
<BlueCopyTextToClipboard text={walletInfo.uris[0]} />
<CopyTextToClipboard text={walletInfo.uris[0]} />
<View style={styles.share}>
<Button
icon={{

View File

@ -1,12 +1,13 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { useRoute } from '@react-navigation/native';
import { BlueCopyTextToClipboard, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import { BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import loc from '../../loc';
import QRCodeComponent from '../../components/QRCodeComponent';
import { useTheme } from '../../components/themes';
import SafeArea from '../../components/SafeArea';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
const LNDViewAdditionalInvoicePreImage = () => {
// state = { walletInfo: undefined };
@ -27,7 +28,7 @@ const LNDViewAdditionalInvoicePreImage = () => {
<QRCodeComponent value={preImageData} size={300} logoSize={90} />
</View>
<BlueSpacing20 />
<BlueCopyTextToClipboard text={preImageData} />
<CopyTextToClipboard text={preImageData} />
</View>
</SafeArea>
);

View File

@ -4,7 +4,7 @@ import Share from 'react-native-share';
import { Icon } from 'react-native-elements';
import QRCodeComponent from '../../components/QRCodeComponent';
import { useNavigation, useNavigationState, useRoute } from '@react-navigation/native';
import { BlueLoading, BlueText, BlueCopyTextToClipboard, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import { BlueLoading, BlueText, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
@ -15,6 +15,7 @@ import { useTheme } from '../../components/themes';
import Button from '../../components/Button';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
import SafeArea from '../../components/SafeArea';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
const LNDViewInvoice = () => {
const { invoice, walletID } = useRoute().params;
@ -252,7 +253,7 @@ const LNDViewInvoice = () => {
{loc.lndViewInvoice.for} {invoice.description}
</BlueText>
)}
<BlueCopyTextToClipboard truncated text={invoice.payment_request} />
<CopyTextToClipboard truncated text={invoice.payment_request} />
<Button onPress={handleOnSharePressed} title={loc.receive.details_share} />

View File

@ -13,15 +13,7 @@ import {
import { useRoute, useFocusEffect } from '@react-navigation/native';
import Share from 'react-native-share';
import QRCodeComponent from '../../components/QRCodeComponent';
import {
BlueLoading,
BlueCopyTextToClipboard,
BlueButtonLink,
BlueText,
BlueSpacing20,
BlueCard,
BlueSpacing40,
} from '../../BlueComponents';
import { BlueLoading, BlueButtonLink, BlueText, BlueSpacing20, BlueCard, BlueSpacing40 } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import BottomModal from '../../components/BottomModal';
import { Chain, BitcoinUnit } from '../../models/bitcoinUnits';
@ -39,6 +31,7 @@ import Button from '../../components/Button';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
import { fiatToBTC, satoshiToBTC } from '../../blue_modules/currency';
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
const ReceiveDetails = () => {
const { walletID, address } = useRoute().params;
@ -271,7 +264,7 @@ const ReceiveDetails = () => {
)}
<QRCodeComponent value={bip21encoded} />
<BlueCopyTextToClipboard text={isCustom ? bip21encoded : address} ref={receiveAddressButton} />
<CopyTextToClipboard text={isCustom ? bip21encoded : address} ref={receiveAddressButton} />
</View>
<View style={styles.share}>
<BlueCard>

View File

@ -6,7 +6,7 @@ import { useNavigation, useRoute, useIsFocused } from '@react-navigation/native'
import RNFS from 'react-native-fs';
import Biometric from '../../class/biometrics';
import { BlueText, BlueCard, BlueSpacing20, BlueCopyToClipboardButton } from '../../BlueComponents';
import { BlueText, BlueCard, BlueSpacing20 } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
@ -18,6 +18,7 @@ import { useTheme } from '../../components/themes';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
import SafeArea from '../../components/SafeArea';
import { SecondButton } from '../../components/SecondButton';
import CopyToClipboardButton from '../../components/CopyToClipboardButton';
const BlueElectrum = require('../../blue_modules/BlueElectrum');
const bitcoin = require('bitcoinjs-lib');
const fs = require('../../blue_modules/fs');
@ -275,7 +276,7 @@ const PsbtWithHardwareWallet = () => {
/>
<BlueSpacing20 />
<View style={styles.copyToClipboard}>
<BlueCopyToClipboardButton
<CopyToClipboardButton
stringToCopy={typeof psbt === 'string' ? psbt : psbt.toBase64()}
displayText={loc.send.psbt_clipboard}
/>

View File

@ -4,13 +4,14 @@ import { ScrollView, TouchableWithoutFeedback, I18nManager, StyleSheet, Linking,
import { Button as ButtonRNElements } from 'react-native-elements';
import navigationStyle from '../../components/navigationStyle';
import { BlueCard, BlueCopyToClipboardButton, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import { BlueCard, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import loc from '../../loc';
import { BlueCurrentTheme, useTheme } from '../../components/themes';
import Notifications from '../../blue_modules/notifications';
import presentAlert from '../../components/Alert';
import { Button } from '../../components/Button';
import ListItem from '../../components/ListItem';
import CopyToClipboardButton from '../../components/CopyToClipboardButton';
const NotificationSettings = () => {
const [isLoading, setIsLoading] = useState(true);
@ -147,7 +148,7 @@ const NotificationSettings = () => {
{isShowTokenInfo >= 9 && (
<View>
<BlueCopyToClipboardButton stringToCopy={tokenInfo} displayText={tokenInfo} />
<CopyToClipboardButton stringToCopy={tokenInfo} displayText={tokenInfo} />
</View>
)}

View File

@ -2,7 +2,7 @@ import React, { useContext, useEffect, useLayoutEffect, useState } from 'react';
import { View, ScrollView, TouchableOpacity, Text, TextInput, Linking, StyleSheet, Keyboard } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native';
import Clipboard from '@react-native-clipboard/clipboard';
import { BlueCard, BlueCopyToClipboardButton, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import { BlueCard, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import HandoffComponent from '../../components/handoff';
import loc from '../../loc';
@ -11,6 +11,7 @@ import ToolTipMenu from '../../components/TooltipMenu';
import presentAlert from '../../components/Alert';
import { useTheme } from '../../components/themes';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
import CopyToClipboardButton from '../../components/CopyToClipboardButton';
const dayjs = require('dayjs');
function onlyUnique(value, index, self) {
@ -240,7 +241,7 @@ const TransactionsDetails = () => {
<>
<View style={styles.rowHeader}>
<BlueText style={styles.rowCaption}>{loc.transactions.details_from}</BlueText>
<BlueCopyToClipboardButton stringToCopy={from.filter(onlyUnique).join(', ')} />
<CopyToClipboardButton stringToCopy={from.filter(onlyUnique).join(', ')} />
</View>
{renderSection(from.filter(onlyUnique))}
<View style={styles.marginBottom18} />
@ -251,7 +252,7 @@ const TransactionsDetails = () => {
<>
<View style={styles.rowHeader}>
<BlueText style={styles.rowCaption}>{loc.transactions.details_to}</BlueText>
<BlueCopyToClipboardButton stringToCopy={to.filter(onlyUnique).join(', ')} />
<CopyToClipboardButton stringToCopy={to.filter(onlyUnique).join(', ')} />
</View>
{renderSection(arrDiff(from, to.filter(onlyUnique)))}
<View style={styles.marginBottom18} />
@ -270,7 +271,7 @@ const TransactionsDetails = () => {
<>
<View style={styles.rowHeader}>
<BlueText style={styles.txid}>{loc.transactions.txid}</BlueText>
<BlueCopyToClipboardButton stringToCopy={tx.hash} />
<CopyToClipboardButton stringToCopy={tx.hash} />
</View>
<BlueText style={styles.rowValue}>{tx.hash}</BlueText>
<View style={styles.marginBottom18} />

View File

@ -1,7 +1,7 @@
import React, { useState, useCallback, useContext, useRef, useEffect } from 'react';
import { InteractionManager, ScrollView, ActivityIndicator, View, StyleSheet, AppState } from 'react-native';
import { useNavigation, useFocusEffect, useRoute } from '@react-navigation/native';
import { BlueSpacing20, BlueText, BlueCopyTextToClipboard, BlueCard } from '../../BlueComponents';
import { BlueSpacing20, BlueText, BlueCard } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import { LegacyWallet, LightningCustodianWallet, SegwitBech32Wallet, SegwitP2SHWallet, WatchOnlyWallet } from '../../class';
import loc from '../../loc';
@ -11,6 +11,7 @@ import HandoffComponent from '../../components/handoff';
import { useTheme } from '../../components/themes';
import SafeArea from '../../components/SafeArea';
import usePrivacy from '../../hooks/usePrivacy';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
const WalletExport = () => {
const { wallets, saveToDisk } = useContext(BlueStorageContext);
@ -108,7 +109,7 @@ const WalletExport = () => {
)}
<BlueSpacing20 />
{wallet.type === LightningCustodianWallet.type || wallet.type === WatchOnlyWallet.type ? (
<BlueCopyTextToClipboard text={wallet.getSecret()} />
<CopyTextToClipboard text={wallet.getSecret()} />
) : (
<BlueText style={[styles.secret, styles.secretWritingDirection, stylesHook.secret]} testID="Secret">
{wallet.getSecret()}

View File

@ -1,10 +1,10 @@
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { BlueCopyTextToClipboard } from '../../BlueComponents';
import { PaymentCodeStackParamList } from '../../Navigation';
import QRCodeComponent from '../../components/QRCodeComponent';
import loc from '../../loc';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
type Props = NativeStackScreenProps<PaymentCodeStackParamList, 'PaymentCode'>;
@ -17,7 +17,7 @@ export default function PaymentCode({ route }: Props) {
{paymentCode && (
<>
<QRCodeComponent value={paymentCode} />
<BlueCopyTextToClipboard text={paymentCode} />
<CopyTextToClipboard text={paymentCode} truncated={false} />
</>
)}
</View>

View File

@ -1,10 +1,10 @@
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import React, { useContext, useEffect, useState } from 'react';
import { SectionList, StyleSheet, Text, View } from 'react-native';
import { BlueCopyTextToClipboard } from '../../BlueComponents';
import { PaymentCodeStackParamList } from '../../Navigation';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import loc from '../../loc';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
interface DataSection {
title: string;
@ -45,7 +45,7 @@ export default function PaymentCodesList({ route }: Props) {
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => (
<View>
<BlueCopyTextToClipboard truncated text={item} />
<CopyTextToClipboard truncated text={item} />
</View>
)}
renderSectionHeader={({ section: { title } }) => <Text style={styles.titleText}>{title}</Text>}

View File

@ -2,7 +2,7 @@ import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useNavigation, useRoute } from '@react-navigation/native';
import { View, StyleSheet, ScrollView, BackHandler } from 'react-native';
import { BlueCopyTextToClipboard, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import { CopyTextToClipboard, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
@ -63,7 +63,7 @@ const PleaseBackupLNDHub = () => {
</View>
<BlueSpacing20 />
<QRCodeComponent value={wallet.getSecret()} size={qrCodeSize} />
<BlueCopyTextToClipboard text={wallet.getSecret()} />
<CopyTextToClipboard text={wallet.getSecret()} />
<BlueSpacing20 />
<Button onPress={pop} title={loc.pleasebackup.ok_lnd} />
</ScrollView>

View File

@ -2,7 +2,7 @@ import React, { useCallback, useContext, useEffect } from 'react';
import { useNavigation, useRoute } from '@react-navigation/native';
import { View, useWindowDimensions, StyleSheet, BackHandler, ScrollView } from 'react-native';
import QRCode from 'react-native-qrcode-svg';
import { BlueCopyTextToClipboard, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import { CopyTextToClipboard, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
@ -71,7 +71,7 @@ const PleaseBackupLdk = () => {
ecl="H"
/>
</View>
<BlueCopyTextToClipboard text={wallet.getSecret()} />
<CopyTextToClipboard text={wallet.getSecret()} />
<BlueSpacing20 />
<Button onPress={pop} title={loc.pleasebackup.ok_lnd} />
</ScrollView>

View File

@ -2,7 +2,7 @@ import { NavigationProp, RouteProp, useFocusEffect, useNavigation, useRoute } fr
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
import { ActivityIndicator, InteractionManager, View } from 'react-native';
import Share from 'react-native-share';
import { BlueCopyTextToClipboard, BlueSpacing20, BlueText } from '../../BlueComponents';
import { BlueSpacing20, BlueText } from '../../BlueComponents';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import Button from '../../components/Button';
import QRCodeComponent from '../../components/QRCodeComponent';
@ -11,6 +11,7 @@ import HandoffComponent from '../../components/handoff';
import usePrivacy from '../../hooks/usePrivacy';
import loc from '../../loc';
import { styles, useDynamicStyles } from './xpub.styles';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
type WalletXpubRouteProp = RouteProp<{ params: { walletID: string; xpub: string } }, 'params'>;
export type RootStackParamList = {
@ -91,7 +92,7 @@ const WalletXpub: React.FC = () => {
<QRCodeComponent value={xpub} size={qrCodeSize} />
<BlueSpacing20 />
<BlueCopyTextToClipboard text={xPubText} />
{xPubText && <CopyTextToClipboard text={xPubText} />}
</View>
<HandoffComponent title={loc.wallets.xpub_title} type={HandoffComponent.activityTypes.Xpub} userInfo={{ xpub: xPubText }} />
<View style={styles.share}>

View File

@ -206,7 +206,7 @@ describe('BlueWallet UI Tests - no wallets', () => {
await element(by.text(`No, and do not ask me again.`)).tap();
} catch (_) {}
await yo('BitcoinAddressQRCodeContainer');
await yo('BlueCopyTextToClipboard');
await yo('CopyTextToClipboard');
await element(by.id('SetCustomAmountButton')).tap();
await element(by.id('BitcoinAmountInput')).replaceText('1');
await element(by.id('CustomAmountDescription')).typeText('test');
@ -214,7 +214,7 @@ describe('BlueWallet UI Tests - no wallets', () => {
await sup('1 BTC');
await sup('test');
await yo('BitcoinAddressQRCodeContainer');
await yo('BlueCopyTextToClipboard');
await yo('CopyTextToClipboard');
await device.pressBack();
await device.pressBack();
await helperDeleteWallet('cr34t3d');

View File

@ -402,7 +402,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
// XPUB
await element(by.id('WalletDetailsScroll')).swipe('up', 'fast', 1);
await element(by.id('XPub')).tap();
await expect(element(by.id('BlueCopyTextToClipboard'))).toBeVisible();
await expect(element(by.id('CopyTextToClipboard'))).toBeVisible();
await device.pressBack();
process.env.TRAVIS && require('fs').writeFileSync(lockFile, '1');