BlueWallet/components/AddressInputScanButton.tsx

190 lines
5.6 KiB
TypeScript
Raw Normal View History

2025-01-03 06:14:09 -04:00
import React, { useCallback, useEffect, useMemo } from 'react';
2024-09-23 21:36:45 -04:00
import { Image, Keyboard, Platform, StyleSheet, Text } from 'react-native';
import Clipboard from '@react-native-clipboard/clipboard';
import ToolTipMenu from './TooltipMenu';
import loc from '../loc';
import { showFilePickerAndReadFile, showImagePickerAndReadImage } from '../blue_modules/fs';
import presentAlert from './Alert';
import { useTheme } from './themes';
2024-10-26 12:30:21 -04:00
import RNQRGenerator from 'rn-qr-generator';
import { CommonToolTipActions } from '../typings/CommonToolTipActions';
import { useSettings } from '../hooks/context/useSettings';
2025-01-03 06:14:09 -04:00
import { useRoute } from '@react-navigation/native';
import { useExtendedNavigation } from '../hooks/useExtendedNavigation';
2024-09-23 21:36:45 -04:00
interface AddressInputScanButtonProps {
isLoading: boolean;
launchedBy?: string;
scanButtonTapped: () => void;
onBarScanned: (ret: { data?: any }) => void;
onChangeText: (text: string) => void;
}
2025-01-03 06:14:09 -04:00
interface RouteParams {
onBarScanned?: any;
}
2024-09-23 21:36:45 -04:00
export const AddressInputScanButton = ({
isLoading,
launchedBy,
scanButtonTapped,
onBarScanned,
onChangeText,
}: AddressInputScanButtonProps) => {
const { colors } = useTheme();
2024-10-26 12:30:21 -04:00
const { isClipboardGetContentEnabled } = useSettings();
2025-01-03 06:14:09 -04:00
const navigation = useExtendedNavigation();
const params = useRoute().params as RouteParams;
2024-09-23 21:36:45 -04:00
const stylesHook = StyleSheet.create({
scan: {
backgroundColor: colors.scanLabel,
},
scanText: {
color: colors.inverseForegroundColor,
},
});
const toolTipOnPress = useCallback(async () => {
await scanButtonTapped();
Keyboard.dismiss();
2025-01-03 06:14:09 -04:00
navigation.navigate('ScanQRCode', {
showFileImportButton: true,
});
}, [navigation, scanButtonTapped]);
2024-09-23 21:36:45 -04:00
2024-10-26 12:30:21 -04:00
const actions = useMemo(() => {
const availableActions = [
CommonToolTipActions.ScanQR,
CommonToolTipActions.ChoosePhoto,
CommonToolTipActions.ImportFile,
{
...CommonToolTipActions.PasteFromClipboard,
hidden: !isClipboardGetContentEnabled,
},
];
return availableActions;
}, [isClipboardGetContentEnabled]);
2025-01-03 06:14:09 -04:00
useEffect(() => {
const data = params.onBarScanned;
if (data) {
onBarScanned({ data });
navigation.setParams({ onBarScanned: undefined });
}
});
2024-09-23 21:36:45 -04:00
const onMenuItemPressed = useCallback(
2024-10-26 12:30:21 -04:00
async (action: string) => {
if (onBarScanned === undefined) throw new Error('onBarScanned is required');
2024-09-23 21:36:45 -04:00
switch (action) {
2024-10-26 12:30:21 -04:00
case CommonToolTipActions.ScanQR.id:
2024-09-23 21:36:45 -04:00
scanButtonTapped();
2025-01-03 06:14:09 -04:00
navigation.navigate('ScanQRCode', {
showFileImportButton: true,
});
2024-09-23 21:36:45 -04:00
break;
2024-10-26 12:30:21 -04:00
case CommonToolTipActions.PasteFromClipboard.id:
try {
let getImage: string | null = null;
let hasImage = false;
2024-10-26 12:30:21 -04:00
if (Platform.OS === 'android') {
hasImage = true;
2024-10-26 12:30:21 -04:00
} else {
hasImage = await Clipboard.hasImage();
}
if (hasImage) {
getImage = await Clipboard.getImage();
2024-10-26 12:30:21 -04:00
}
if (getImage) {
try {
const base64Data = getImage.replace(/^data:image\/(png|jpeg|jpg);base64,/, '');
2024-10-26 12:30:21 -04:00
const values = await RNQRGenerator.detect({
base64: base64Data,
});
if (values && values.values.length > 0) {
onChangeText(values.values[0]);
} else {
presentAlert({ message: loc.send.qr_error_no_qrcode });
}
} catch (error) {
presentAlert({ message: (error as Error).message });
}
} else {
const clipboardText = await Clipboard.getString();
onChangeText(clipboardText);
}
} catch (error) {
presentAlert({ message: (error as Error).message });
}
2024-09-23 21:36:45 -04:00
break;
2024-10-26 12:30:21 -04:00
case CommonToolTipActions.ChoosePhoto.id:
2024-09-23 21:36:45 -04:00
showImagePickerAndReadImage()
.then(value => {
if (value) {
onChangeText(value);
}
})
.catch(error => {
presentAlert({ message: error.message });
});
break;
2024-10-26 12:30:21 -04:00
case CommonToolTipActions.ImportFile.id:
2024-09-23 21:36:45 -04:00
showFilePickerAndReadFile()
.then(value => {
if (value.data) {
onChangeText(value.data);
}
})
.catch(error => {
presentAlert({ message: error.message });
});
break;
}
Keyboard.dismiss();
},
2025-01-03 06:14:09 -04:00
[navigation, onBarScanned, onChangeText, scanButtonTapped],
2024-09-23 21:36:45 -04:00
);
const buttonStyle = useMemo(() => [styles.scan, stylesHook.scan], [stylesHook.scan]);
return (
<ToolTipMenu
actions={actions}
isButton
onPressMenuItem={onMenuItemPressed}
testID="BlueAddressInputScanQrButton"
disabled={isLoading}
onPress={toolTipOnPress}
buttonStyle={buttonStyle}
accessibilityLabel={loc.send.details_scan}
accessibilityHint={loc.send.details_scan_hint}
>
<Image source={require('../img/scan-white.png')} accessible={false} />
<Text style={[styles.scanText, stylesHook.scanText]} accessible={false}>
{loc.send.details_scan}
</Text>
</ToolTipMenu>
);
};
const styles = StyleSheet.create({
scan: {
height: 36,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
borderRadius: 4,
paddingVertical: 4,
paddingHorizontal: 8,
marginHorizontal: 4,
},
scanText: {
marginLeft: 4,
},
});