Skip to content

Align NFC contact import and share dialogs with Design Standards v1.4#6332

Open
thebentern wants to merge 2 commits into
mainfrom
feat/nfc-tag-alignment
Open

Align NFC contact import and share dialogs with Design Standards v1.4#6332
thebentern wants to merge 2 commits into
mainfrom
feat/nfc-tag-alignment

Conversation

@thebentern

@thebentern thebentern commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Implements the Android side of the cross-platform NFC tag alignment (audit: design#125, parent: design#126). Android is already the NFC reference implementation — these are Design-Standards-v1.4 conformance fixes plus one cross-platform semantic alignment.

What changes

  • Honor the encoded manually_verified bit on importMessagingControllerImpl.importContact no longer forces manually_verified = true; the flag encoded by the sharer is passed through to both the AdminMessage(add_contact) and the local NodeDB update. (Outbound sendSharedContact already propagated the local flag; unchanged.) This matches iOS, where addContactFromURL honors the encoded bit.
  • §7 write-feedback colors — the post-write result dialog now colors its message: success = SemanticColors.Success (Green 600 #3FB86D), failure = MaterialTheme.colorScheme.error. MeshtasticDialog gained an optional message-color parameter (default keeps all existing call sites unchanged).
  • §6 plain-language subtext — new write_nfc_subtext explains what writing a tag does before the write starts (the existing write_nfc_text only appears mid-write).
  • §1 circular identifier — the contact-import confirmation now shows the node identity badge (NodeChip) instead of text only.
  • Tests: importContact passthrough (false→false, true→true) with the sent AdminMessage payload asserted; screenshot previews for the colored success/failure dialogs and the import confirm.

Design standards

Conforms to Meshtastic Client Design Standards v1.4 §1 (node identity), §6 (plain language), §7 (semantic colors — Success is Green 600, never the accent green).

Verification

  • spotlessCheck + detekt clean; kmpSmokeCompile passes
  • :core:service:allTests + :core:ui:allTests pass — including the new importContact passthrough tests (false→false and true→true), which capture and assert the sent AdminMessage.add_contact.manually_verified
  • 6 new screenshot goldens recorded and :screenshot-tests:validateDebugScreenshotTest passes (light + dark for the success, failure, and import dialogs)
  • Adversarial diff review: no blockers; nits addressed

Note: the .skills/compose-ui/strings-index.txt diff includes catch-up entries for the pre-existing firmware_update_* strings — the index on main was stale (#6309 didn't regenerate it), and running the required scripts/sort-strings.py swept them in.

Tracks meshtastic/design#126.

🤖 Generated with Claude Code

Closes #6331.

Summary by CodeRabbit

  • New Features
    • Added new firmware update notification and “open” flow strings.
    • Improved NFC UX with added write subtext and NFC support messaging in QR dialogs.
    • Added themed plain-text dialog message coloring.
  • Bug Fixes
    • Import now preserves an incoming shared contact’s verification state instead of forcing it to a default value.
  • Tests
    • Expanded screenshot/golden coverage for NFC write success/failure and shared contact import dialogs.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0983bf67-bf20-4e94-b960-3a837aecf8d0

📥 Commits

Reviewing files that changed from the base of the PR and between 4bc1658 and 896d582.

⛔ Files ignored due to path filters (6)
  • screenshot-tests/src/screenshotTestDebug/reference/org/meshtastic/screenshots/core/AlertScreenshotTestsKt/ScreenshotNfcWriteFailedAlert_Dark_d19fbf1f_0.png is excluded by !**/*.png, !**/*.png
  • screenshot-tests/src/screenshotTestDebug/reference/org/meshtastic/screenshots/core/AlertScreenshotTestsKt/ScreenshotNfcWriteFailedAlert_Light_b29dc7a7_0.png is excluded by !**/*.png, !**/*.png
  • screenshot-tests/src/screenshotTestDebug/reference/org/meshtastic/screenshots/core/AlertScreenshotTestsKt/ScreenshotNfcWriteSuccessAlert_Dark_d19fbf1f_0.png is excluded by !**/*.png, !**/*.png
  • screenshot-tests/src/screenshotTestDebug/reference/org/meshtastic/screenshots/core/AlertScreenshotTestsKt/ScreenshotNfcWriteSuccessAlert_Light_b29dc7a7_0.png is excluded by !**/*.png, !**/*.png
  • screenshot-tests/src/screenshotTestDebug/reference/org/meshtastic/screenshots/core/AlertScreenshotTestsKt/ScreenshotSharedContactImportAlert_Dark_d19fbf1f_0.png is excluded by !**/*.png, !**/*.png
  • screenshot-tests/src/screenshotTestDebug/reference/org/meshtastic/screenshots/core/AlertScreenshotTestsKt/ScreenshotSharedContactImportAlert_Light_b29dc7a7_0.png is excluded by !**/*.png, !**/*.png
📒 Files selected for processing (9)
  • .skills/compose-ui/strings-index.txt
  • core/resources/src/commonMain/composeResources/values/strings.xml
  • core/service/src/commonMain/kotlin/org/meshtastic/core/service/MessagingControllerImpl.kt
  • core/service/src/commonTest/kotlin/org/meshtastic/core/service/RadioControllerImplTest.kt
  • core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/AlertDialogs.kt
  • core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/QrDialog.kt
  • core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/share/SharedContactDialog.kt
  • core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/util/AlertPreviews.kt
  • screenshot-tests/src/screenshotTest/kotlin/org/meshtastic/screenshots/core/AlertScreenshotTests.kt
🚧 Files skipped from review as they are similar to previous changes (7)
  • screenshot-tests/src/screenshotTest/kotlin/org/meshtastic/screenshots/core/AlertScreenshotTests.kt
  • .skills/compose-ui/strings-index.txt
  • core/resources/src/commonMain/composeResources/values/strings.xml
  • core/service/src/commonMain/kotlin/org/meshtastic/core/service/MessagingControllerImpl.kt
  • core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/QrDialog.kt
  • core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/share/SharedContactDialog.kt
  • core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/AlertDialogs.kt

📝 Walkthrough

Walkthrough

The changes preserve encoded NFC contact verification state, add NFC dialog colors and explanatory text, refactor shared-contact alert composition, and add preview and screenshot coverage.

Changes

NFC alignment updates

Layer / File(s) Summary
Contact verification passthrough
core/service/src/commonMain/kotlin/org/meshtastic/core/service/MessagingControllerImpl.kt, core/service/src/commonTest/kotlin/org/meshtastic/core/service/RadioControllerImplTest.kt
importContact preserves incoming manually_verified values in admin messages and node updates, with false and true cases tested.
NFC alert presentation
.skills/compose-ui/strings-index.txt, core/resources/.../strings.xml, core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/AlertDialogs.kt, core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/QrDialog.kt, core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/util/AlertPreviews.kt, screenshot-tests/src/screenshotTest/kotlin/org/meshtastic/screenshots/core/AlertScreenshotTests.kt
NFC resources and firmware-update keys are indexed, dialog message colors are configurable, NFC success/failure styling and subtext are added, and screenshot previews cover the new alerts.
Shared contact import alert
core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/share/SharedContactDialog.kt
The dialog passes the matching node explicitly, separates import handling, and adds a preview entry point used by screenshot tests.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

Suggested reviewers: jamesarich

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main NFC dialog alignment work and is specific enough for history scanning.
Linked Issues check ✅ Passed The summarized changes satisfy the linked NFC conformance items, including verification passthrough, colors, subtext, NodeChip, and tests.
Out of Scope Changes check ✅ Passed The changes are all directly related to the NFC contact import/share dialog polish and supporting tests or resources.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (2)
core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/share/SharedContactDialog.kt (2)

97-97: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove unnecessary parentheses.

The parentheses around node.user.public_key.size are redundant and can be safely removed for cleaner syntax.

♻️ Proposed refactor
-                    if ((node.user.public_key.size) > 0 && node.user.public_key != sharedContact.user?.public_key) {
+                    if (node.user.public_key.size > 0 && node.user.public_key != sharedContact.user?.public_key) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/share/SharedContactDialog.kt`
at line 97, Update the condition in SharedContactDialog to remove the redundant
parentheses around node.user.public_key.size while preserving the existing
comparison and logical behavior.

56-56: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Avoid obtaining koinViewModel() as a default parameter in reusable composables.

As per coding guidelines, obtain koinViewModel() inside entry<T> blocks so ViewModels follow backstack lifetime. Providing it as a default parameter here can lead to incorrect scoping if this dialog is instantiated outside of its intended navigation destination context. Consider removing the default parameter to require the caller (which should be an entry<T>) to explicitly pass the ViewModel instance.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/share/SharedContactDialog.kt`
at line 56, Remove the koinViewModel() default from the SharedContactDialog
viewModel parameter, requiring callers to provide the instance explicitly.
Ensure the intended entry<T> navigation block obtains the ViewModel and passes
it to SharedContactDialog, preserving backstack-scoped lifetime.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/share/SharedContactDialog.kt`:
- Line 97: Update the condition in SharedContactDialog to remove the redundant
parentheses around node.user.public_key.size while preserving the existing
comparison and logical behavior.
- Line 56: Remove the koinViewModel() default from the SharedContactDialog
viewModel parameter, requiring callers to provide the instance explicitly.
Ensure the intended entry<T> navigation block obtains the ViewModel and passes
it to SharedContactDialog, preserving backstack-scoped lifetime.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5850b20e-9573-4307-822b-6cd619576b15

📥 Commits

Reviewing files that changed from the base of the PR and between 91d2f76 and 8ec2d05.

⛔ Files ignored due to path filters (6)
  • screenshot-tests/src/screenshotTestDebug/reference/org/meshtastic/screenshots/core/AlertScreenshotTestsKt/ScreenshotNfcWriteFailedAlert_Dark_d19fbf1f_0.png is excluded by !**/*.png, !**/*.png
  • screenshot-tests/src/screenshotTestDebug/reference/org/meshtastic/screenshots/core/AlertScreenshotTestsKt/ScreenshotNfcWriteFailedAlert_Light_b29dc7a7_0.png is excluded by !**/*.png, !**/*.png
  • screenshot-tests/src/screenshotTestDebug/reference/org/meshtastic/screenshots/core/AlertScreenshotTestsKt/ScreenshotNfcWriteSuccessAlert_Dark_d19fbf1f_0.png is excluded by !**/*.png, !**/*.png
  • screenshot-tests/src/screenshotTestDebug/reference/org/meshtastic/screenshots/core/AlertScreenshotTestsKt/ScreenshotNfcWriteSuccessAlert_Light_b29dc7a7_0.png is excluded by !**/*.png, !**/*.png
  • screenshot-tests/src/screenshotTestDebug/reference/org/meshtastic/screenshots/core/AlertScreenshotTestsKt/ScreenshotSharedContactImportAlert_Dark_d19fbf1f_0.png is excluded by !**/*.png, !**/*.png
  • screenshot-tests/src/screenshotTestDebug/reference/org/meshtastic/screenshots/core/AlertScreenshotTestsKt/ScreenshotSharedContactImportAlert_Light_b29dc7a7_0.png is excluded by !**/*.png, !**/*.png
📒 Files selected for processing (9)
  • .skills/compose-ui/strings-index.txt
  • core/resources/src/commonMain/composeResources/values/strings.xml
  • core/service/src/commonMain/kotlin/org/meshtastic/core/service/MessagingControllerImpl.kt
  • core/service/src/commonTest/kotlin/org/meshtastic/core/service/RadioControllerImplTest.kt
  • core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/AlertDialogs.kt
  • core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/QrDialog.kt
  • core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/share/SharedContactDialog.kt
  • core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/util/AlertPreviews.kt
  • screenshot-tests/src/screenshotTest/kotlin/org/meshtastic/screenshots/core/AlertScreenshotTests.kt

@jamesarich
jamesarich enabled auto-merge July 21, 2026 00:36
@github-actions github-actions Bot added the enhancement New feature or request label Jul 21, 2026
@jamesarich
jamesarich added this pull request to the merge queue Jul 21, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks Jul 21, 2026
@jamesarich
jamesarich added this pull request to the merge queue Jul 21, 2026
@thebentern
thebentern removed this pull request from the merge queue due to a manual request Jul 21, 2026
thebentern and others added 2 commits July 21, 2026 06:28
Implements the Android side of the cross-platform NFC alignment audit
(meshtastic/design#126):

- importContact now honors the manually_verified flag encoded by the
  sharer instead of forcing it to true, matching iOS (cross-platform
  policy from the design-repo NFC alignment audit).
- The NFC write result dialog colors its message with
  SemanticColors.Success (Green 600) on success and colorScheme.error
  on failure (§7); MeshtasticDialog gained an optional messageColor.
- New write_nfc_subtext explains what writing a tag does before the
  write starts (§6).
- The shared-contact import dialog shows the NodeChip identity badge
  for both known and unknown contacts (§1).
- Tests: importContact passthrough (false->false, true->true) with
  the sent AdminMessage payload asserted; screenshot goldens for the
  colored result dialogs and the import dialog (light + dark).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
core/resources/.../composeResources is Compose Multiplatform Resources,
not an Android res/values dir, so AAPT's apostrophe-escaping rules do
not apply and Compose Resources does not unescape \'. The escape was
rendering literally as "Couldn\'t write to tag" in the dialog.

Use a plain apostrophe, matching the ~25 strings already doing so in the
same file (e.g. cant_change_no_radio, "Couldn't change channel").
Screenshot goldens for the failure dialog re-recorded.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@thebentern
thebentern force-pushed the feat/nfc-tag-alignment branch 2 times, most recently from 4bc1658 to 896d582 Compare July 21, 2026 11:28
@thebentern
thebentern enabled auto-merge July 21, 2026 11:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ALIGNMENT]: NFC tag feature-set — Design Standards v1.4 conformance polish

1 participant