check NFC support and enabled state before NFC operations
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { View, StyleSheet, Text } from 'react-native';
|
||||
import { inject, observer } from 'mobx-react';
|
||||
import NfcManager from 'react-native-nfc-manager';
|
||||
|
||||
import Button from '../Button';
|
||||
import ModalBox from '../ModalBox';
|
||||
@@ -24,7 +25,11 @@ export default class AndroidNfcModal extends React.Component<
|
||||
> {
|
||||
render() {
|
||||
const { ModalStore } = this.props;
|
||||
const { showAndroidNfcModal, toggleAndroidNfcModal } = ModalStore;
|
||||
const {
|
||||
showAndroidNfcModal,
|
||||
toggleAndroidNfcModal,
|
||||
androidNfcModalIsNfcEnabled
|
||||
} = ModalStore;
|
||||
|
||||
return (
|
||||
<ModalBox
|
||||
@@ -67,9 +72,15 @@ export default class AndroidNfcModal extends React.Component<
|
||||
marginBottom: 30
|
||||
}}
|
||||
>
|
||||
{localeString('components.AndroidNfcModal.ready')}
|
||||
{androidNfcModalIsNfcEnabled
|
||||
? localeString(
|
||||
'components.AndroidNfcModal.ready'
|
||||
)
|
||||
: localeString(
|
||||
'components.AndroidNfcModal.nfcDisabled'
|
||||
)}
|
||||
</Text>
|
||||
<NFC />
|
||||
{androidNfcModalIsNfcEnabled && <NFC />}
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 18,
|
||||
@@ -79,14 +90,33 @@ export default class AndroidNfcModal extends React.Component<
|
||||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
{localeString('components.AndroidNfcModal.hold')}
|
||||
{androidNfcModalIsNfcEnabled
|
||||
? localeString(
|
||||
'components.AndroidNfcModal.hold'
|
||||
)
|
||||
: localeString(
|
||||
'components.AndroidNfcModal.enableInstructions'
|
||||
)}
|
||||
</Text>
|
||||
<View style={styles.buttons}>
|
||||
{!androidNfcModalIsNfcEnabled && (
|
||||
<View style={styles.button}>
|
||||
<Button
|
||||
title={localeString(
|
||||
'general.openNfcSettings'
|
||||
)}
|
||||
onPress={() => {
|
||||
toggleAndroidNfcModal(false);
|
||||
NfcManager.goToNfcSetting();
|
||||
}}
|
||||
quaternary
|
||||
></Button>
|
||||
</View>
|
||||
)}
|
||||
<View style={styles.button}>
|
||||
<Button
|
||||
title={localeString('general.cancel')}
|
||||
onPress={() => toggleAndroidNfcModal(false)}
|
||||
quaternary
|
||||
></Button>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { Platform, TouchableOpacity } from 'react-native';
|
||||
import { inject, observer } from 'mobx-react';
|
||||
import { checkNfcEnabled } from '../utils/NFCUtils';
|
||||
|
||||
import HCESession, { NFCContentType, NFCTagType4 } from 'react-native-hce';
|
||||
|
||||
@@ -7,6 +9,8 @@ import NfcIcon from '../assets/images/SVG/NFC-alt.svg';
|
||||
|
||||
import Button from './../components/Button';
|
||||
|
||||
import ModalStore from '../stores/ModalStore';
|
||||
|
||||
import { localeString } from '../utils/LocaleUtils';
|
||||
import { themeColor } from '../utils/ThemeUtils';
|
||||
|
||||
@@ -15,12 +19,15 @@ interface NFCButtonProps {
|
||||
icon?: any;
|
||||
noUppercase?: boolean;
|
||||
iconOnly?: boolean;
|
||||
ModalStore?: ModalStore;
|
||||
}
|
||||
|
||||
interface NFCButtonState {
|
||||
nfcBroadcast: boolean;
|
||||
}
|
||||
|
||||
@inject('ModalStore')
|
||||
@observer
|
||||
export default class NFCButton extends React.Component<
|
||||
NFCButtonProps,
|
||||
NFCButtonState
|
||||
@@ -43,7 +50,13 @@ export default class NFCButton extends React.Component<
|
||||
this.stopSimulation();
|
||||
}
|
||||
}
|
||||
toggleNfc = () => {
|
||||
toggleNfc = async () => {
|
||||
const { ModalStore } = this.props;
|
||||
|
||||
if (!this.state.nfcBroadcast) {
|
||||
if (!(await checkNfcEnabled(ModalStore!))) return;
|
||||
}
|
||||
|
||||
if (this.state.nfcBroadcast) {
|
||||
this.stopSimulation();
|
||||
} else {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"general.request": "Request",
|
||||
"general.scan": "Scan",
|
||||
"general.enableNfc": "Enable NFC",
|
||||
"general.openNfcSettings": "Open NFC Settings",
|
||||
"general.receiveNfc": "Receive via NFC",
|
||||
"general.payNfc": "Pay via NFC",
|
||||
"general.confirm": "Confirm",
|
||||
@@ -288,6 +289,8 @@
|
||||
"components.ExternalLinkModal.copied": "Copied!",
|
||||
"components.AndroidNfcModal.ready": "Ready to scan",
|
||||
"components.AndroidNfcModal.hold": "Hold your Android phone near an NFC tag to read it",
|
||||
"components.AndroidNfcModal.nfcDisabled": "NFC is disabled",
|
||||
"components.AndroidNfcModal.enableInstructions": "Please enable NFC in your device settings to use this feature",
|
||||
"components.QRCodeScanner.chooseFromGallery": "Choose from gallery",
|
||||
"components.QRCodeScanner.flashOn": "Flash on",
|
||||
"components.QRCodeScanner.flashOff": "Flash off",
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
export default class ModalStore {
|
||||
@observable public showExternalLinkModal: boolean = false;
|
||||
@observable public showAndroidNfcModal: boolean = false;
|
||||
@observable public androidNfcModalIsNfcEnabled: boolean = false;
|
||||
@observable public showInfoModal: boolean = false;
|
||||
@observable public showAlertModal: boolean = false;
|
||||
@observable public showShareModal: boolean = false;
|
||||
@@ -181,8 +182,14 @@ export default class ModalStore {
|
||||
|
||||
/* Android NFC Modal */
|
||||
@action
|
||||
public toggleAndroidNfcModal = (status: boolean) => {
|
||||
public toggleAndroidNfcModal = (
|
||||
status: boolean,
|
||||
nfcEnabled: boolean = true
|
||||
) => {
|
||||
this.showAndroidNfcModal = status;
|
||||
if (status) {
|
||||
this.androidNfcModalIsNfcEnabled = nfcEnabled;
|
||||
}
|
||||
};
|
||||
|
||||
@action
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
import NfcManager from 'react-native-nfc-manager';
|
||||
import ModalStore from '../stores/ModalStore';
|
||||
|
||||
/**
|
||||
* Checks whether NFC is enabled on the device.
|
||||
* If not, shows the AndroidNfcModal with the disabled state and returns false.
|
||||
* On iOS, NfcManager.isEnabled() always returns true, so this function
|
||||
* only ever returns false on Android.
|
||||
*/
|
||||
export async function checkNfcEnabled(
|
||||
modalStore: ModalStore
|
||||
): Promise<boolean> {
|
||||
const nfcEnabled = await NfcManager.isEnabled();
|
||||
if (!nfcEnabled) {
|
||||
modalStore.toggleAndroidNfcModal(true, false);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class NFCUtils {
|
||||
nfcUtf8ArrayToStr = (data: any) => {
|
||||
const extraByteMap = [1, 1, 1, 1, 2, 2, 3, 0];
|
||||
|
||||
@@ -56,7 +56,7 @@ import UnitsStore from '../../stores/UnitsStore';
|
||||
import CashuInvoice from '../../models/CashuInvoice';
|
||||
|
||||
import { localeString } from '../../utils/LocaleUtils';
|
||||
import NFCUtils from '../../utils/NFCUtils';
|
||||
import NFCUtils, { checkNfcEnabled } from '../../utils/NFCUtils';
|
||||
import { themeColor } from '../../utils/ThemeUtils';
|
||||
import { getAmountFromSats } from '../../utils/AmountUtils';
|
||||
|
||||
@@ -269,6 +269,9 @@ export default class ReceiveEcash extends React.Component<
|
||||
|
||||
enableNfc = async () => {
|
||||
const { ModalStore } = this.props;
|
||||
|
||||
if (!(await checkNfcEnabled(ModalStore))) return;
|
||||
|
||||
this.disableNfc();
|
||||
await NfcManager.start().catch((e) => console.warn(e.message));
|
||||
|
||||
|
||||
+31
-18
@@ -30,7 +30,7 @@ import TextInput from '../components/TextInput';
|
||||
import UTXOPicker from '../components/UTXOPicker';
|
||||
|
||||
import handleAnything from '../utils/handleAnything';
|
||||
import NFCUtils from '../utils/NFCUtils';
|
||||
import NFCUtils, { checkNfcEnabled } from '../utils/NFCUtils';
|
||||
import NodeUriUtils from '../utils/NodeUriUtils';
|
||||
import BackendUtils from '../utils/BackendUtils';
|
||||
import ValidationUtils from '../utils/ValidationUtils';
|
||||
@@ -91,6 +91,7 @@ interface OpenChannelState {
|
||||
additionalChannels: Array<AdditionalChannel>;
|
||||
isNodePubkeyValid: boolean;
|
||||
isNodeHostValid: boolean;
|
||||
nfcSupported: boolean;
|
||||
}
|
||||
|
||||
@inject(
|
||||
@@ -132,7 +133,8 @@ export default class OpenChannel extends React.Component<
|
||||
account: 'default',
|
||||
additionalChannels: [],
|
||||
isNodePubkeyValid: true,
|
||||
isNodeHostValid: true
|
||||
isNodeHostValid: true,
|
||||
nfcSupported: false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -173,6 +175,9 @@ export default class OpenChannel extends React.Component<
|
||||
if (this.props.ChannelsStore.channelsView === ChannelsView.Peers) {
|
||||
this.setState({ connectPeerOnly: true });
|
||||
}
|
||||
|
||||
const nfcSupported = await NfcManager.isSupported();
|
||||
this.setState({ nfcSupported });
|
||||
}
|
||||
|
||||
disableNfc = () => {
|
||||
@@ -182,6 +187,9 @@ export default class OpenChannel extends React.Component<
|
||||
|
||||
enableNfc = async () => {
|
||||
const { ModalStore } = this.props;
|
||||
|
||||
if (!(await checkNfcEnabled(ModalStore))) return;
|
||||
|
||||
this.disableNfc();
|
||||
await NfcManager.start();
|
||||
|
||||
@@ -336,7 +344,8 @@ export default class OpenChannel extends React.Component<
|
||||
advancedSettingsToggle,
|
||||
additionalChannels,
|
||||
isNodePubkeyValid,
|
||||
isNodeHostValid
|
||||
isNodeHostValid,
|
||||
nfcSupported
|
||||
} = this.state;
|
||||
const { implementation } = SettingsStore;
|
||||
|
||||
@@ -1361,21 +1370,25 @@ export default class OpenChannel extends React.Component<
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={styles.button}>
|
||||
<Button
|
||||
title={localeString('general.enableNfc')}
|
||||
icon={
|
||||
<NfcIcon
|
||||
stroke={themeColor('highlight')}
|
||||
width={25}
|
||||
height={25}
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
}
|
||||
onPress={() => this.enableNfc()}
|
||||
secondary
|
||||
/>
|
||||
</View>
|
||||
{nfcSupported && (
|
||||
<View style={styles.button}>
|
||||
<Button
|
||||
title={localeString(
|
||||
'general.enableNfc'
|
||||
)}
|
||||
icon={
|
||||
<NfcIcon
|
||||
stroke={themeColor('highlight')}
|
||||
width={25}
|
||||
height={25}
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
}
|
||||
onPress={() => this.enableNfc()}
|
||||
secondary
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</ScrollView>
|
||||
)}
|
||||
|
||||
+5
-1
@@ -79,7 +79,7 @@ import BalanceStore from '../stores/BalanceStore';
|
||||
import { localeString } from '../utils/LocaleUtils';
|
||||
import BackendUtils from '../utils/BackendUtils';
|
||||
import Base64Utils from '../utils/Base64Utils';
|
||||
import NFCUtils from '../utils/NFCUtils';
|
||||
import NFCUtils, { checkNfcEnabled } from '../utils/NFCUtils';
|
||||
import { themeColor } from '../utils/ThemeUtils';
|
||||
import { SATS_PER_BTC } from '../utils/UnitsUtils';
|
||||
import { getAmountFromSats } from '../utils/AmountUtils';
|
||||
@@ -193,6 +193,7 @@ const LOCKED_EXPIRY_SECONDS = '3600';
|
||||
@inject(
|
||||
'ChannelsStore',
|
||||
'InvoicesStore',
|
||||
'ModalStore',
|
||||
'SettingsStore',
|
||||
'UnitsStore',
|
||||
'PosStore',
|
||||
@@ -680,6 +681,9 @@ export default class Receive extends React.Component<
|
||||
|
||||
enableNfc = async () => {
|
||||
const { ModalStore } = this.props;
|
||||
|
||||
if (!(await checkNfcEnabled(ModalStore))) return;
|
||||
|
||||
this.disableNfc();
|
||||
await NfcManager.start().catch((e) => console.warn(e.message));
|
||||
|
||||
|
||||
+25
-14
@@ -53,7 +53,7 @@ import UTXOPicker from '../components/UTXOPicker';
|
||||
|
||||
import BackendUtils from '../utils/BackendUtils';
|
||||
import { errorToUserFriendly } from '../utils/ErrorUtils';
|
||||
import NFCUtils from '../utils/NFCUtils';
|
||||
import NFCUtils, { checkNfcEnabled } from '../utils/NFCUtils';
|
||||
import { localeString } from '../utils/LocaleUtils';
|
||||
import { themeColor } from '../utils/ThemeUtils';
|
||||
import { getUnformattedAmount, getAmountFromSats } from '../utils/AmountUtils';
|
||||
@@ -121,6 +121,7 @@ interface SendState {
|
||||
additionalOutputs: Array<AdditionalOutput>;
|
||||
fundMax: boolean;
|
||||
validAmountToSwap: boolean;
|
||||
nfcSupported: boolean;
|
||||
}
|
||||
|
||||
@inject(
|
||||
@@ -191,7 +192,8 @@ export default class Send extends React.Component<SendProps, SendState> {
|
||||
account: 'default',
|
||||
additionalOutputs: [],
|
||||
fundMax: false,
|
||||
validAmountToSwap: false
|
||||
validAmountToSwap: false,
|
||||
nfcSupported: false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -333,6 +335,9 @@ export default class Send extends React.Component<SendProps, SendState> {
|
||||
'hardwareBackPress',
|
||||
this.backPressed.bind(this)
|
||||
);
|
||||
|
||||
const nfcSupported = await NfcManager.isSupported();
|
||||
this.setState({ nfcSupported });
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
@@ -371,6 +376,9 @@ export default class Send extends React.Component<SendProps, SendState> {
|
||||
|
||||
enableNfc = async () => {
|
||||
const { ModalStore } = this.props;
|
||||
|
||||
if (!(await checkNfcEnabled(ModalStore))) return;
|
||||
|
||||
this.disableNfc();
|
||||
await NfcManager.start().catch((e) => console.warn(e.message));
|
||||
|
||||
@@ -746,7 +754,8 @@ export default class Send extends React.Component<SendProps, SendState> {
|
||||
fundMax,
|
||||
account,
|
||||
validAmountToSwap,
|
||||
utxos
|
||||
utxos,
|
||||
nfcSupported
|
||||
} = this.state;
|
||||
const {
|
||||
confirmedBlockchainBalance,
|
||||
@@ -846,17 +855,19 @@ export default class Send extends React.Component<SendProps, SendState> {
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
<View style={{ marginRight: 15 }}>
|
||||
<TouchableOpacity
|
||||
onPress={() => this.enableNfc()}
|
||||
>
|
||||
<NFC
|
||||
stroke={themeColor('text')}
|
||||
width={30}
|
||||
height={30}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
{nfcSupported && (
|
||||
<View style={{ marginRight: 15 }}>
|
||||
<TouchableOpacity
|
||||
onPress={() => this.enableNfc()}
|
||||
>
|
||||
<NFC
|
||||
stroke={themeColor('text')}
|
||||
width={30}
|
||||
height={30}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
<View>
|
||||
<TouchableOpacity
|
||||
onPress={() =>
|
||||
|
||||
Reference in New Issue
Block a user