diff --git a/dist/BUNDLE_ID b/dist/BUNDLE_ID index 47f9682c..98a02fda 100644 --- a/dist/BUNDLE_ID +++ b/dist/BUNDLE_ID @@ -1 +1 @@ -019aee8e-ae33-77d0-a617-530181bcc686 \ No newline at end of file +019b0359-9f11-775c-a6eb-a2562f2f15ad \ No newline at end of file diff --git a/package.json b/package.json index f02e3348..b40e64f8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "minibits_wallet", - "version": "0.3.4-beta.3", + "version": "0.3.4-beta.4", "private": true, "scripts": { "android:clean": "cd android && ./gradlew clean", diff --git a/src/screens/DeveloperScreen.tsx b/src/screens/DeveloperScreen.tsx index e4ced383..5d4b5e8e 100644 --- a/src/screens/DeveloperScreen.tsx +++ b/src/screens/DeveloperScreen.tsx @@ -34,6 +34,7 @@ import RNExitApp from 'react-native-exit-app' import { TransactionStatus } from '../models/Transaction' import { maxTransactionsInHistory } from '../models/TransactionsStore' import { StaticScreenProps, useNavigation } from '@react-navigation/native' +// refresh // refresh type Props = StaticScreenProps @@ -295,6 +296,7 @@ export const DeveloperScreen = observer(function DeveloperScreen({ route }: Prop tx="developerScreen_info" subText={`Environment: ${APP_ENV} JS Bundle version: ${JS_BUNDLE_VERSION} +${Platform.OS === 'android' ? 'Android version code:' + ANDROID_VERSION_CODE : ''} Commit: ${COMMIT} DB version: ${dbVersion} State size: ${walletStateSize.toLocaleString()} bytes diff --git a/src/screens/NfcPayScreen.tsx b/src/screens/NfcPayScreen.tsx index 166078b4..49babd07 100644 --- a/src/screens/NfcPayScreen.tsx +++ b/src/screens/NfcPayScreen.tsx @@ -5,9 +5,10 @@ import { TextStyle, Alert, ColorValue, + Platform, } from 'react-native' import { PaymentRequest as CashuPaymentRequest, MeltQuoteResponse, PaymentRequestTransport, PaymentRequestTransportType, decodePaymentRequest, getDecodedToken } from '@cashu/cashu-ts' -import NfcManager, { NfcTech, Ndef, NfcEvents } from 'react-native-nfc-manager' +import NfcManager, { NfcTech, Ndef, NfcEvents, TagEvent } from 'react-native-nfc-manager' import { colors, spacing, typography, useThemeColor } from '../theme' import EventEmitter from '../utils/eventEmitter' import { log } from '../services/logService' @@ -182,6 +183,7 @@ export const NfcPayScreen = observer(function NfcPayScreen({ route }: Props) { return () => { NfcManager.cancelTechnologyRequest().catch(() => {}) NfcManager.setEventListener(NfcEvents.DiscoverTag, null) + NfcManager.setEventListener(NfcEvents.SessionClosed, null) } }, []) @@ -524,17 +526,97 @@ export const NfcPayScreen = observer(function NfcPayScreen({ route }: Props) { }, [handleTransferTaskResult]) + + const readNdefOnce = function () { + const cleanUp = () => { + NfcManager.setEventListener(NfcEvents.DiscoverTag, null); + NfcManager.setEventListener(NfcEvents.SessionClosed, null); + }; + + return new Promise((resolve) => { + let tagFound: TagEvent | null = null; + + NfcManager.setEventListener(NfcEvents.DiscoverTag, (tag: TagEvent) => { + tagFound = tag; + resolve(tagFound); + + NfcManager.unregisterTagEvent().catch(() => 0); + }); + + NfcManager.setEventListener(NfcEvents.SessionClosed, (e: any) => { + if (e) { + log.error(Err.NFC_ERROR, 'NFC Session closed with error', e.message); + } + + cleanUp() + + if (!tagFound) { + resolve(null) + } + }); + + NfcManager.registerTagEvent(); + }); + } + + + const readTag = async function() { + try { + await NfcManager.requestTechnology([NfcTech.Ndef]); + + const tag = await NfcManager.getTag(); + return tag + + } catch (e: any) { + // for tag reading, we don't actually need to show any error + log.error(Err.NFC_ERROR, 'Failed to read NFC tag', e.message); + } finally { + NfcManager.cancelTechnologyRequest(); + } + } + + const startNfcSession = async () => { try { log.debug('Starting NFC session for payment request reading...', {caller: 'startNfcSession'}) - await NfcManager.requestTechnology(NfcTech.Ndef, { + const tag = await readNdefOnce() + // const tag = await readTag() + + if (!tag) { + return + } + + log.warn('Tag found', {tag}); + + /*await NfcManager.requestTechnology(NfcTech.Ndef, { alertMessage: 'Hold phone near the device...', - //invalidateAfterFirstRead: false, + invalidateAfterFirstRead: false, }) + const tag = await NfcManager.getTag(); + log.warn('Tag found', {tag}); + + if(!tag || !tag.ndefMessage || tag.ndefMessage.length === 0) { + setInfo('No NDEF message found on the NFC tag') + return + } + + const bytes = new Uint8Array( + tag.ndefMessage[0].payload + ); + + let payload: string + + const decoded = Ndef.text.decodePayload(bytes); + + log.warn('NFC tag decoded', { decoded })*/ + + + // setNfcInfo('Reading payment request...') + // Listen for tag discovery - NfcManager.setEventListener(NfcEvents.DiscoverTag, async (tag: any) => { + /*NfcManager.setEventListener(NfcEvents.DiscoverTag, async (tag: any) => { if (isProcessing) return setIsProcessing(true) setNfcInfo('Reading payment request...') @@ -568,10 +650,12 @@ export const NfcPayScreen = observer(function NfcPayScreen({ route }: Props) { } finally { setIsProcessing(false) } - }) + })*/ } catch (e: any) { log.error(Err.NFC_ERROR, e.message) handleError(e) + } finally { + NfcManager.cancelTechnologyRequest().catch(() => {}) } } @@ -974,7 +1058,7 @@ export const NfcPayScreen = observer(function NfcPayScreen({ route }: Props) { ) }) -// Styles remain unchanged + const $screen: ViewStyle = { flex: 1 } const $contentContainer: ViewStyle = { flex: 1, marginTop: -spacing.extraLarge * 2, padding: spacing.extraSmall } const $headerContainer: TextStyle = { alignItems: 'center', paddingBottom: spacing.medium, height: spacing.screenHeight * 0.15 } diff --git a/src/screens/WalletScreen.tsx b/src/screens/WalletScreen.tsx index 5ac38a98..2532d1e8 100644 --- a/src/screens/WalletScreen.tsx +++ b/src/screens/WalletScreen.tsx @@ -825,7 +825,7 @@ export const WalletScreen = observer(function WalletScreen({ route }: Props) { gotoNfcPay()} /> diff --git a/src/services/minibitsService.ts b/src/services/minibitsService.ts index 36fddaa5..f57ef3d3 100644 --- a/src/services/minibitsService.ts +++ b/src/services/minibitsService.ts @@ -417,7 +417,7 @@ const fetchApi = async (url: string, options: MinibitsRequestOptions, timeout = } // legacy headers -const getHeaders = () => { +/*const getHeaders = () => { return { 'Content-Type': 'application/json', 'Accept': 'application/json', @@ -425,7 +425,7 @@ const getHeaders = () => { 'Authorization': `Bearer ${MINIBITS_SERVER_API_KEY}`, 'User-Agent': `Minibits/${JS_BUNDLE_VERSION}` } -} +}*/ const getPublicHeaders = () => { return {