Skip to content

fix: accept interoperable QR URL hosts#2116

Open
RCGV1 wants to merge 5 commits into
meshtastic:mainfrom
RCGV1:codex/qr-interoperability
Open

fix: accept interoperable QR URL hosts#2116
RCGV1 wants to merge 5 commits into
meshtastic:mainfrom
RCGV1:codex/qr-interoperability

Conversation

@RCGV1

@RCGV1 RCGV1 commented Jul 19, 2026

Copy link
Copy Markdown
Member

Summary

  • Accept canonical and www Meshtastic hosts for channel QR links.
  • Route contact QR links structurally instead of relying on a raw URL substring.
  • Cover Android channel replace, channel add, and shared-contact payload vectors in Apple tests.

Root cause

Android accepts both meshtastic.org and www.meshtastic.org for channel and contact links. Apple only accepted the bare host for channels and routed contacts with a literal meshtastic.org/v/# substring, so valid links using the alternate host were not imported.

Evidence

  • The shared channel vector exercises replace with LoRa preserved and add with LoRa removed.
  • The shared-contact vector CAE= decodes to node 1.
  • Focused simulator verification passed:
    xcodebuild test -quiet -project Meshtastic.xcodeproj -scheme Meshtastic -only-testing:MeshtasticTests/MeshtasticChannelURLTests -only-testing:MeshtasticTests/ShareContactQRTests

No UI layout changes: this is URL routing and protocol regression coverage.

Summary by CodeRabbit

  • Bug Fixes
    • Improved recognition of Meshtastic contact and channel links (including www.meshtastic.org), and tightened in-app importing to the supported URL formats only.
    • Updated URL routing across app launch, shared content, and message interactions so supported contact links consistently use the in-app import flow.
  • Documentation
    • Refined “Link Appearance” guidance to clearly distinguish in-app import URLs (exact contact/channel formats) from system-browser links (including Meshtastic docs).
  • Tests
    • Expanded coverage for Android-compatible link/QR payload handling and add-versus-replace parsing behavior.

@coderabbitai

coderabbitai Bot commented Jul 19, 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e4deadab-fbf1-4e22-8b9c-95b06f71558a

📥 Commits

Reviewing files that changed from the base of the PR and between 31c99e4 and 64cd386.

📒 Files selected for processing (1)
  • MeshtasticTests/MeshtasticChannelURLTests.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • MeshtasticTests/MeshtasticChannelURLTests.swift

📝 Walkthrough

Walkthrough

Contact and channel URL handling now uses structured host, path, and fragment validation. Contact routing supports canonical and www domains across app entry points, while channel parsing and tests cover Android-compatible URL forms.

Changes

URL handling

Layer / File(s) Summary
Contact URL recognition and routing
Meshtastic/Helpers/ContactURLHandler.swift, Meshtastic/AppIntents/AddContactIntent.swift, Meshtastic/MeshtasticApp.swift, Meshtastic/Views/Messages/MessageText.swift, MeshtasticTests/EntityTests.swift
Contact URLs are validated by host, path, and fragment, then routed consistently through intents, app URL handlers, and message links. Tests cover canonical and www forms, documentation URL exclusion, and Android contact payload decoding.
Android-compatible channel URLs
Meshtastic/Helpers/MeshtasticChannelURL.swift, MeshtasticTests/MeshtasticChannelURLTests.swift
Channel URL validation accepts both Meshtastic domains, with tests covering add and replace modes, channel counts, and configuration results.
Link behavior documentation and metadata
docs/user/messages.md, Meshtastic/Resources/docs/markdown/user/messages.md, Meshtastic/Resources/docs/user/messages.html, Meshtastic/Resources/docs/index.json
Documentation distinguishes in-app Meshtastic imports from system-browser documentation links, and the messages index metadata is updated.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant EntryPoint
  participant ContactURLHandler
  participant AccessoryManager
  EntryPoint->>ContactURLHandler: Validate contact URL
  ContactURLHandler-->>EntryPoint: Return supported URL result
  EntryPoint->>ContactURLHandler: Handle contact URL
  ContactURLHandler->>AccessoryManager: Import contact
Loading

Possibly related PRs

Poem

I’m a rabbit with links in my ear,
Canonical and www now both appear.
Contacts hop through paths made true,
Channels add or replace anew.
Android payloads join the cheer!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: accepting both Meshtastic hosts for QR URL handling.
Description check ✅ Passed The description covers the change, motivation, and testing, though it does not follow the template headings exactly.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@Meshtastic/Views/Messages/MessageText.swift`:
- Around line 197-200: Update docs/user/messages.md to document that
message-text contact links handled by ContactURLHandler, including
www.meshtastic.org links, are intercepted instead of opening in the default
browser. Keep the documentation aligned with the behavior in MessageText.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 19a68736-0b65-4ed9-a2a3-6c726d16e6fc

📥 Commits

Reviewing files that changed from the base of the PR and between e531f15 and 94d2dfb.

📒 Files selected for processing (7)
  • Meshtastic/AppIntents/AddContactIntent.swift
  • Meshtastic/Helpers/ContactURLHandler.swift
  • Meshtastic/Helpers/MeshtasticChannelURL.swift
  • Meshtastic/MeshtasticApp.swift
  • Meshtastic/Views/Messages/MessageText.swift
  • MeshtasticTests/EntityTests.swift
  • MeshtasticTests/MeshtasticChannelURLTests.swift

Comment thread Meshtastic/Views/Messages/MessageText.swift

@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.

Actionable comments posted: 2

🤖 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.

Inline comments:
In `@docs/user/messages.md`:
- Line 148: Regenerate the bundled documentation for the updated
docs/user/messages.md content by running the repository’s build-docs.sh command
with Meshtastic/Resources/docs as output, then run copy-snapshots.sh with
Meshtastic/Resources/docs/assets/screenshots and include all generated changes.
- Line 148: Update the message-bubble link documentation to replace both
references to Safari with “the system browser,” reflecting
MessageText.handleURL’s .systemAction behavior. Keep the exceptions for
Meshtastic channel and contact links opening the in-app import flow, and retain
Meshtastic documentation links as system-browser links.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 248eba44-2758-4c62-9ecb-4ab3aa9eb231

📥 Commits

Reviewing files that changed from the base of the PR and between 94d2dfb and 8700ffe.

📒 Files selected for processing (2)
  • MeshtasticTests/EntityTests.swift
  • docs/user/messages.md

Comment thread docs/user/messages.md Outdated

@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 (1)
MeshtasticTests/MeshtasticChannelURLTests.swift (1)

41-52: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Leverage parameterized testing.

Instead of using a for loop inside the test function, you can utilize Swift Testing's built-in parameterized testing feature. This approach is more idiomatic and provides individual, granular test results for each channel count in the test runner.

♻️ Proposed refactor
-	`@Test` func allSupportedChannelCountsPreserveSettingsForReplaceAndAdd() throws {
-		for channelCount in 1 ... 8 {
-			let channelSet = makeChannelSet(channelCount: channelCount)
-			let replace = try MeshtasticChannelURL.parse(MeshtasticChannelURL.urlString(for: channelSet))
-			let add = try MeshtasticChannelURL.parse(MeshtasticChannelURL.urlString(for: channelSet, addChannels: true))
-
-			`#expect`(replace.channelSet.settings == channelSet.settings, "\(channelCount)-channel replace settings")
-			`#expect`(replace.channelSet.loraConfig == channelSet.loraConfig, "\(channelCount)-channel replace LoRa config")
-			`#expect`(add.channelSet.settings == channelSet.settings, "\(channelCount)-channel add settings")
-			`#expect`(!add.channelSet.hasLoraConfig, "\(channelCount)-channel add must not retune")
-		}
-	}
+	`@Test`(arguments: 1 ... 8)
+	func allSupportedChannelCountsPreserveSettingsForReplaceAndAdd(channelCount: Int) throws {
+		let channelSet = makeChannelSet(channelCount: channelCount)
+		let replace = try MeshtasticChannelURL.parse(MeshtasticChannelURL.urlString(for: channelSet))
+		let add = try MeshtasticChannelURL.parse(MeshtasticChannelURL.urlString(for: channelSet, addChannels: true))
+
+		`#expect`(replace.channelSet.settings == channelSet.settings, "\(channelCount)-channel replace settings")
+		`#expect`(replace.channelSet.loraConfig == channelSet.loraConfig, "\(channelCount)-channel replace LoRa config")
+		`#expect`(add.channelSet.settings == channelSet.settings, "\(channelCount)-channel add settings")
+		`#expect`(!add.channelSet.hasLoraConfig, "\(channelCount)-channel add must not retune")
+	}
🤖 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 `@MeshtasticTests/MeshtasticChannelURLTests.swift` around lines 41 - 52,
Refactor allSupportedChannelCountsPreserveSettingsForReplaceAndAdd to use Swift
Testing parameterized testing with channel counts 1 through 8 instead of looping
inside the test. Keep the existing replace/add parsing and expectations
unchanged so each channel count produces an individual test result.
🤖 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 `@MeshtasticTests/MeshtasticChannelURLTests.swift`:
- Around line 41-52: Refactor
allSupportedChannelCountsPreserveSettingsForReplaceAndAdd to use Swift Testing
parameterized testing with channel counts 1 through 8 instead of looping inside
the test. Keep the existing replace/add parsing and expectations unchanged so
each channel count produces an individual test result.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 699ee49b-0b08-4304-80d6-1fa415c52da1

📥 Commits

Reviewing files that changed from the base of the PR and between 8700ffe and 31c99e4.

📒 Files selected for processing (5)
  • Meshtastic/Resources/docs/index.json
  • Meshtastic/Resources/docs/markdown/user/messages.md
  • Meshtastic/Resources/docs/user/messages.html
  • MeshtasticTests/MeshtasticChannelURLTests.swift
  • docs/user/messages.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/user/messages.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant