Skip to content

fix: check NFC support and enabled state before NFC operations#3821

Merged
kaloudis merged 2 commits intoZeusLN:masterfrom
myxmaster:fix/nfc-availability-checks
Apr 4, 2026
Merged

fix: check NFC support and enabled state before NFC operations#3821
kaloudis merged 2 commits intoZeusLN:masterfrom
myxmaster:fix/nfc-availability-checks

Conversation

@myxmaster
Copy link
Copy Markdown
Collaborator

@myxmaster myxmaster commented Mar 10, 2026

Description

Bugs fixes:

  • NFC scanning could be triggered on devices where NFC is not supported (Send, OpenChannel), because NfcManager.isSupported() was not checked before rendering the NFC icon/button
  • On all NFC entry points (Send, OpenChannel, Receive, ReceiveEcash, NFC broadcast in CollapsedQR), initiating an NFC operation while NFC is disabled in Android settings would silently fail or show a misleading "Ready to scan" state
  • ModalStore was declared in Receive's props interface but missing from the @inject(...) decorator, causing a crash when attempting NFC scanning in the advanced receive options
  • Removed dead code in ChannelsPane.tsx (disableNfc, enableNfc)

Changed behavior:

  • NFC icons and buttons are now only shown when the device reports NFC hardware support via NfcManager.isSupported()
  • When NFC is supported but disabled in Android settings, tapping any NFC icon or button now shows a modal informing the user that NFC is disabled, with a direct link to the Android NFC settings and a Cancel option (instead of entering the scan/broadcast flow)
grafik

Note:
On iOS NfcManager.isEnabled() always returns true, so the disabled-NFC code path is Android-only. The iOS experience should be unchanged, please test this.

This pull request is categorized as a:

  • New feature
  • Bug fix
  • Code refactor
  • Configuration change
  • Locales update
  • Quality assurance
  • Other

Checklist

  • I’ve run yarn run tsc and made sure my code compiles correctly
  • I’ve run yarn run lint and made sure my code didn’t contain any problematic patterns
  • I’ve run yarn run prettier and made sure my code is formatted correctly
  • I’ve run yarn run test and made sure all of the tests pass

Testing

If you modified or added a utility file, did you add new unit tests?

  • No, I’m a fool :)
  • Yes
  • N/A

I have tested this PR on the following platforms (please specify OS version and phone model/VM):

  • Android
  • iOS

I have tested this PR with the following types of nodes (please specify node version and API version where appropriate):

  • Embedded LND
  • LND (REST)
  • LND (Lightning Node Connect)
  • Core Lightning (CLNRest)
  • Nostr Wallet Connect
  • LndHub

Locales

  • I’ve added new locale text that requires translations
  • I’m aware that new translations should be made on the ZEUS Transfix page and not directly to this repo

Third Party Dependencies and Packages

  • Contributors will need to run yarn after this PR is merged in
  • 3rd party dependencies have been modified:
    • verify that package.json and yarn.lock have been properly updated
    • verify that dependencies are installed for both iOS and Android platforms

Other:

  • Changes were made that require an update to the README
  • Changes were made that require an update to onboarding

@myxmaster
Copy link
Copy Markdown
Collaborator Author

/gemini summary

@myxmaster
Copy link
Copy Markdown
Collaborator Author

/gemini review

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

This pull request significantly refines the NFC functionality across the application, addressing several critical issues related to NFC support and enabled states. It ensures a more robust and user-friendly experience by dynamically adapting the UI based on device capabilities and providing clear, actionable feedback when NFC is disabled, thereby preventing silent failures and crashes.

Highlights

  • Improved NFC User Experience: NFC icons and buttons are now only displayed on devices that support NFC hardware, preventing attempts to use NFC on incompatible devices.
  • Enhanced NFC State Handling: When NFC is supported but disabled in Android settings, users are now presented with a modal that informs them of the disabled state and provides a direct link to the Android NFC settings.
  • Critical Bug Fix: Resolved a crash in the Receive view caused by ModalStore not being properly injected, which previously occurred when attempting NFC scanning in advanced receive options.
  • New Utility Function: Introduced a checkNfcEnabled utility to centralize the logic for verifying NFC status and displaying the appropriate user feedback.
Changelog
  • components/Modals/AndroidNfcModal.tsx
    • Added NfcManager import.
    • Updated modal to display different messages and actions based on NFC enabled status.
    • Introduced a button to directly open NFC settings when NFC is disabled.
  • components/NFCButton.tsx
    • Integrated ModalStore and checkNfcEnabled to verify NFC status before initiating broadcast.
  • locales/en.json
    • Added new localization strings for NFC disabled state and settings link.
  • stores/ModalStore.ts
    • Added androidNfcModalIsNfcEnabled observable to track NFC enabled status for the modal.
    • Modified toggleAndroidNfcModal to accept and set the NFC enabled status.
  • utils/NFCUtils.ts
    • Created checkNfcEnabled function to encapsulate NFC status checks and modal display logic.
  • views/Cashu/ReceiveEcash.tsx
    • Implemented checkNfcEnabled before enabling NFC.
  • views/OpenChannel.tsx
    • Added nfcSupported state and checked NfcManager.isSupported() on component mount.
    • Integrated checkNfcEnabled before enabling NFC.
    • Conditionally rendered the NFC enable button based on nfcSupported state.
  • views/Receive.tsx
    • Injected ModalStore and integrated checkNfcEnabled before enabling NFC.
  • views/Send.tsx
    • Added nfcSupported state and checked NfcManager.isSupported() on component mount.
    • Integrated checkNfcEnabled before enabling NFC.
    • Conditionally rendered the NFC icon based on nfcSupported state.
Activity
  • myxmaster requested a summary of the pull request.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses several bugs related to NFC functionality by implementing checks for NFC support and its enabled state. The introduction of the checkNfcEnabled utility and the informative modal for when NFC is disabled on Android significantly improves the user experience. The fixes are consistently applied across various views, and the code is well-structured. I've included a couple of suggestions for minor improvements related to code duplication and UI consistency.

Comment on lines 117 to 120
<Button
title={localeString('general.cancel')}
onPress={() => toggleAndroidNfcModal(false)}
quaternary
></Button>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better UI consistency, consider making the 'Cancel' button quaternary when it's the only button available (i.e., when NFC is enabled). This was its style before this change. When NFC is disabled, making it a primary button next to the quaternary 'Open NFC Settings' button is a good choice to guide the user. Adding the quaternary prop conditionally would achieve this.

                                <Button
                                    title={localeString('general.cancel')}
                                    onPress={() => toggleAndroidNfcModal(false)}
                                    quaternary={androidNfcModalIsNfcEnabled}
                                ></Button>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think CANCEL should keep the style of other CANCEL buttons (when there are other options). Besides there is a margin problem if it is quaternary and the only button.

Comment thread views/OpenChannel.tsx
Comment on lines +177 to +178
const nfcSupported = await NfcManager.isSupported();
this.setState({ nfcSupported });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This logic to check for NFC support is also added in views/Send.tsx in this PR (and is also present in views/Receive.tsx). To avoid code duplication and improve maintainability, you could extract this into a reusable component, for example a Higher-Order Component (HOC) that would wrap these views and provide nfcSupported as a prop.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The shared logic is two lines... A HOC would add substantially more boilerplate than it removes. A useNfcSupported hook would be the cleaner solution, but that requires migrating class components to functional components, which is out of scope here.

@kaloudis kaloudis added Android Android issues NFC labels Mar 11, 2026
@ajaysehwal
Copy link
Copy Markdown
Contributor

ajaysehwal commented Apr 1, 2026

@myxmaster, Please rebase

@myxmaster myxmaster force-pushed the fix/nfc-availability-checks branch from 58aa838 to 691b842 Compare April 1, 2026 09:21
Copy link
Copy Markdown
Contributor

@shubhamkmr04 shubhamkmr04 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tACK

Copy link
Copy Markdown
Contributor

@ajaysehwal ajaysehwal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@myxmaster, I think we missed ChannelsPane.enableNfc for the NFC enabled check.

@ajaysehwal
Copy link
Copy Markdown
Contributor

@myxmaster Another suggestion: the enableNfc method is duplicated across several components. I think we should extract it into a single shared implementation, perhaps in a separate PR. cc @kaloudis

@myxmaster
Copy link
Copy Markdown
Collaborator Author

I think we missed ChannelsPane.enableNfc for the NFC enabled check.

It is never called from anywhere, so I will remove it.

And yes, in a separate PR I will centralize the enableNfc method.

Copy link
Copy Markdown
Contributor

@ajaysehwal ajaysehwal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tACK

@kaloudis kaloudis added the UX label Apr 4, 2026
@kaloudis kaloudis added this to the v13.0.0 milestone Apr 4, 2026
@kaloudis kaloudis merged commit f85ed85 into ZeusLN:master Apr 4, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Android Android issues NFC UX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants