2024-10-27 19:06:14 +01:00
|
|
|
import React, { useCallback } from 'react';
|
2024-09-24 03:36:45 +02:00
|
|
|
import { Keyboard, StyleSheet, TextInput, View } from 'react-native';
|
2024-05-20 11:54:13 +02:00
|
|
|
import loc from '../loc';
|
2024-09-24 03:36:45 +02:00
|
|
|
import { AddressInputScanButton } from './AddressInputScanButton';
|
2024-10-22 20:02:53 +02:00
|
|
|
import { useTheme } from './themes';
|
|
|
|
import DeeplinkSchemaMatch from '../class/deeplink-schema-match';
|
|
|
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../blue_modules/hapticFeedback';
|
2021-02-25 17:13:34 +01:00
|
|
|
|
2024-01-06 09:04:23 +01:00
|
|
|
interface AddressInputProps {
|
|
|
|
isLoading?: boolean;
|
|
|
|
address?: string;
|
|
|
|
placeholder?: string;
|
|
|
|
onChangeText: (text: string) => void;
|
2024-01-07 14:55:55 +01:00
|
|
|
onBarScanned: (ret: { data?: any }) => void;
|
2024-01-06 09:04:23 +01:00
|
|
|
scanButtonTapped?: () => void;
|
|
|
|
launchedBy?: string;
|
|
|
|
editable?: boolean;
|
|
|
|
inputAccessoryViewID?: string;
|
|
|
|
onBlur?: () => void;
|
2024-09-24 03:36:45 +02:00
|
|
|
onFocus?: () => void;
|
2024-09-27 01:21:47 +02:00
|
|
|
testID?: string;
|
2024-01-06 09:04:23 +01:00
|
|
|
keyboardType?:
|
|
|
|
| 'default'
|
|
|
|
| 'numeric'
|
|
|
|
| 'email-address'
|
|
|
|
| 'ascii-capable'
|
|
|
|
| 'numbers-and-punctuation'
|
|
|
|
| 'url'
|
|
|
|
| 'number-pad'
|
|
|
|
| 'phone-pad'
|
|
|
|
| 'name-phone-pad'
|
|
|
|
| 'decimal-pad'
|
|
|
|
| 'twitter'
|
|
|
|
| 'web-search'
|
|
|
|
| 'visible-password';
|
|
|
|
}
|
2021-02-25 17:13:34 +01:00
|
|
|
|
|
|
|
const AddressInput = ({
|
|
|
|
isLoading = false,
|
|
|
|
address = '',
|
2024-09-27 01:21:47 +02:00
|
|
|
testID = 'AddressInput',
|
2021-02-25 17:13:34 +01:00
|
|
|
placeholder = loc.send.details_address,
|
|
|
|
onChangeText,
|
|
|
|
onBarScanned,
|
2021-09-09 13:00:11 +02:00
|
|
|
scanButtonTapped = () => {},
|
2021-02-25 17:13:34 +01:00
|
|
|
launchedBy,
|
2021-09-09 13:00:11 +02:00
|
|
|
editable = true,
|
|
|
|
inputAccessoryViewID,
|
2021-09-02 20:18:58 +02:00
|
|
|
onBlur = () => {},
|
2024-09-24 03:36:45 +02:00
|
|
|
onFocus = () => {},
|
2021-10-15 16:52:25 +02:00
|
|
|
keyboardType = 'default',
|
2024-01-06 09:04:23 +01:00
|
|
|
}: AddressInputProps) => {
|
2021-02-25 17:13:34 +01:00
|
|
|
const { colors } = useTheme();
|
|
|
|
const stylesHook = StyleSheet.create({
|
|
|
|
root: {
|
|
|
|
borderColor: colors.formBorder,
|
|
|
|
borderBottomColor: colors.formBorder,
|
|
|
|
backgroundColor: colors.inputBackgroundColor,
|
|
|
|
},
|
2024-09-24 03:36:45 +02:00
|
|
|
input: {
|
|
|
|
color: colors.foregroundColor,
|
2021-02-25 17:13:34 +01:00
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2024-10-27 19:06:14 +01:00
|
|
|
const validateAddressWithFeedback = useCallback((value: string) => {
|
2024-10-27 21:35:29 +01:00
|
|
|
const isBitcoinAddress = DeeplinkSchemaMatch.isBitcoinAddress(value);
|
|
|
|
const isLightningInvoice = DeeplinkSchemaMatch.isLightningInvoice(value);
|
|
|
|
const isValid = isBitcoinAddress || isLightningInvoice;
|
2024-10-23 00:26:36 +02:00
|
|
|
|
2024-10-27 19:06:14 +01:00
|
|
|
triggerHapticFeedback(isValid ? HapticFeedbackTypes.NotificationSuccess : HapticFeedbackTypes.NotificationError);
|
2024-10-27 21:35:29 +01:00
|
|
|
return {
|
|
|
|
isValid,
|
2024-10-28 03:05:14 +01:00
|
|
|
type: isBitcoinAddress ? 'bitcoin' : isLightningInvoice ? 'lightning' : 'invalid',
|
2024-10-27 21:35:29 +01:00
|
|
|
};
|
2024-10-27 19:06:14 +01:00
|
|
|
}, []);
|
2024-10-22 23:15:20 +02:00
|
|
|
|
2024-10-27 19:06:14 +01:00
|
|
|
const onBlurEditing = () => {
|
|
|
|
validateAddressWithFeedback(address);
|
2021-09-02 20:18:58 +02:00
|
|
|
onBlur();
|
|
|
|
Keyboard.dismiss();
|
|
|
|
};
|
|
|
|
|
2021-02-25 17:13:34 +01:00
|
|
|
return (
|
|
|
|
<View style={[styles.root, stylesHook.root]}>
|
|
|
|
<TextInput
|
2024-09-27 01:21:47 +02:00
|
|
|
testID={testID}
|
2021-02-25 17:13:34 +01:00
|
|
|
onChangeText={onChangeText}
|
|
|
|
placeholder={placeholder}
|
|
|
|
placeholderTextColor="#81868e"
|
|
|
|
value={address}
|
2024-09-24 03:36:45 +02:00
|
|
|
style={[styles.input, stylesHook.input]}
|
2021-09-09 13:00:11 +02:00
|
|
|
editable={!isLoading && editable}
|
|
|
|
multiline={!editable}
|
|
|
|
inputAccessoryViewID={inputAccessoryViewID}
|
|
|
|
clearButtonMode="while-editing"
|
2021-09-02 20:18:58 +02:00
|
|
|
onBlur={onBlurEditing}
|
2024-09-24 03:36:45 +02:00
|
|
|
onFocus={onFocus}
|
2021-09-07 16:18:25 +02:00
|
|
|
autoCapitalize="none"
|
2021-09-02 20:18:58 +02:00
|
|
|
autoCorrect={false}
|
2021-10-15 16:52:25 +02:00
|
|
|
keyboardType={keyboardType}
|
2021-02-25 17:13:34 +01:00
|
|
|
/>
|
2021-09-09 13:00:11 +02:00
|
|
|
{editable ? (
|
2024-09-24 03:36:45 +02:00
|
|
|
<AddressInputScanButton
|
|
|
|
isLoading={isLoading}
|
|
|
|
launchedBy={launchedBy}
|
|
|
|
scanButtonTapped={scanButtonTapped}
|
|
|
|
onBarScanned={onBarScanned}
|
|
|
|
onChangeText={onChangeText}
|
|
|
|
/>
|
2021-09-09 13:00:11 +02:00
|
|
|
) : null}
|
2021-02-25 17:13:34 +01:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
|
|
|
root: {
|
|
|
|
flexDirection: 'row',
|
|
|
|
borderWidth: 1.0,
|
|
|
|
borderBottomWidth: 0.5,
|
|
|
|
minHeight: 44,
|
|
|
|
height: 44,
|
|
|
|
alignItems: 'center',
|
|
|
|
marginVertical: 8,
|
2024-10-28 03:05:14 +01:00
|
|
|
marginHorizontal: 18,
|
2021-02-25 17:13:34 +01:00
|
|
|
borderRadius: 4,
|
|
|
|
},
|
|
|
|
input: {
|
|
|
|
flex: 1,
|
2024-10-28 03:05:14 +01:00
|
|
|
paddingHorizontal: 8,
|
2021-02-25 17:13:34 +01:00
|
|
|
minHeight: 33,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
export default AddressInput;
|