Skip to content

Align message delivery status wording#2054

Merged
garthvh merged 8 commits into
meshtastic:mainfrom
RCGV1:codex/message-status-alignment
Jul 16, 2026
Merged

Align message delivery status wording#2054
garthvh merged 8 commits into
meshtastic:mainfrom
RCGV1:codex/message-status-alignment

Conversation

@RCGV1

@RCGV1 RCGV1 commented Jul 6, 2026

Copy link
Copy Markdown
Member

Summary

  • Aligns outgoing message delivery status labels with the cross-platform design issue wording.
  • Distinguishes channel mesh delivery, direct relayed-but-unconfirmed delivery, direct recipient delivery, sending, retryable warnings, and permanent failures.
  • Keeps retry affordances tied to retryable failure states and updates routing-error wording for the firmware-backed statuses.
  • Updates user docs and regenerated in-app docs output for the message status language.

Evidence

  • Docs/help status screenshot: docs/assets/screenshots/ackErrors.png
  • Bundled docs screenshot copy: Meshtastic/Resources/docs/assets/screenshots/ackErrors.png

iOS message status help

Validation

  • git diff --check passed.
  • git diff --cached --check passed before commit.
  • bash scripts/build-docs.sh --output Meshtastic/Resources/docs passed; bundle was 7.9 MB / 10 MB hard limit.
  • bash scripts/copy-snapshots.sh --output Meshtastic/Resources/docs/assets/screenshots copied 98 doc-referenced screenshots; the helper cleanup removed one unrelated orphan locally, which was restored before commit.
  • Focused XcodeBuildMCP test_sim passed: 53 tests, 0 failures.
    • Filters: MeshtasticTests/RoutingErrorTests, MeshtasticTests/RoutingErrorDetailedTests, MeshtasticTests/MessageAckStatusRefreshTests, MeshtasticTests/AckErrorsSnapshotTests.
    • Result bundle: /Users/benjaminfaershtein/Library/Developer/XcodeBuildMCP/workspaces/Meshtastic-Apple-Fork-3-a9b3dcc49c40/result-bundles/test_sim_2026-07-07T18-29-52-872Z_pid78002_f6419b45.xcresult
  • Local swiftlint command is unavailable in this environment; the GitHub SwiftLint check is expected to cover it.
  • Full test suite was not run locally.

Links

Closes #2051

Summary by CodeRabbit

  • New Features
    • Added a unified message delivery status model and label (icon, color, status text/detail) across sending, mesh delivery, direct-recipient delivery, and relayed-not-confirmed outcomes.
    • Updated retry UI to use the unified status (including when “Try Again” is available).
  • Bug Fixes
    • Refined routing/PKI failure wording and improved retryable vs non-retryable behavior, including a new PKI-related failure case.
  • Documentation
    • Rewrote “Message Status” help in user docs to match the new icon/color/status text and retry semantics.
  • Tests
    • Expanded delivery-status and retry-behavior assertions with exact user-facing wording.

@coderabbitai

coderabbitai Bot commented Jul 6, 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: dcd8990b-a811-46ef-b6e6-0a7fce4097bf

📥 Commits

Reviewing files that changed from the base of the PR and between e169b28 and 508c5a3.

📒 Files selected for processing (4)
  • Meshtastic/Views/Messages/ChannelMessageList.swift
  • Meshtastic/Views/Messages/ChannelMessageRow.swift
  • Meshtastic/Views/Messages/RetryButton.swift
  • MeshtasticTests/RoutingAndMiscTests.swift
💤 Files with no reviewable changes (1)
  • MeshtasticTests/RoutingAndMiscTests.swift
🚧 Files skipped from review as they are similar to previous changes (2)
  • Meshtastic/Views/Messages/RetryButton.swift
  • Meshtastic/Views/Messages/ChannelMessageRow.swift

📝 Walkthrough

Walkthrough

This PR standardizes iOS message delivery statuses. It adds a public-key routing error, centralizes ACK and retry presentation, updates message rows and retry handling, and refreshes help content, tests, and documentation.

Changes

Message delivery status standardization

Layer / File(s) Summary
RoutingError semantics
Meshtastic/Enums/RoutingError.swift, MeshtasticTests/*
Adds pkiSendFailPublicKey, revises localized wording and retryability, extends protobuf mapping, and updates enum tests.
Delivery status model
Meshtastic/Extensions/SwiftData/*, Meshtastic.xcodeproj/project.pbxproj, MeshtasticTests/MessageAckStatusRefreshTests.swift
Adds shared status resolution and rendering, registers the new source file, and tests delivery wording and retry behavior.
Message UI and retry flow
Meshtastic/Views/Messages/*
Uses delivery status for rows, details, retry eligibility, alerts, resend behavior, and channel reloads.
Delivery status help
Meshtastic/Views/Helpers/Help/AckErrors.swift
Updates status examples, routing-error presentation, retry icons, and color guidance.
Message status documentation
Meshtastic/Resources/docs/*, docs/user/messages.md
Rewrites status tables and metadata for delivery, retryable, and permanent failure states.

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

Sequence Diagram(s)

sequenceDiagram
  participant MessageRow
  participant MessageEntity
  participant RoutingError
  participant MessageDeliveryStatus
  participant RetryButton
  MessageRow->>MessageEntity: deliveryStatus(isDirectMessage:)
  MessageEntity->>RoutingError: parse ackError
  RoutingError-->>MessageEntity: display, description, canRetry
  MessageEntity->>MessageDeliveryStatus: build status
  MessageRow->>RetryButton: show when status.canRetry
Loading

Possibly related issues

  • meshtastic/device-ui#334: Covers the same canonical delivery wording and retryability states.
  • meshtastic/web#1245: Addresses cross-client delivery-status wording and retry presentation.
  • meshtastic/firmware#10904: Defines matching delivery, relay, and retryable/permanent failure states.

Possibly related PRs

Suggested reviewers: garthvh

Poem

I hop through gray, orange, red,
Clearer words where jargon fled.
Delivered, relayed, or retry—
Each message tells us why. 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title concisely reflects the main change: aligning message delivery status wording.
Description check ✅ Passed The description covers the change, motivation, testing, evidence, and links, and mostly follows the template.
Linked Issues check ✅ Passed The changes match #2051 by standardizing delivery-status wording, preserving retry only for retryable states, and avoiding raw technical labels.
Out of Scope Changes check ✅ Passed The docs, screenshots, and project wiring are directly related to the delivery-status update and not out of scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
MeshtasticTests/RoutingAndMiscTests.swift (1)

49-51: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Stale/weak assertion left over from the .none.display rename.

This PR renames RoutingError.none.display to "Delivered to recipient", but display_noneIsAcknowledged still passes via .contains("Acknowledged") || .count > 0 — a condition that's true regardless of the actual string. EnumTests.swift already has the correct assertion for this (== "Delivered to recipient"); consider tightening or removing this duplicate/misleading test.

🧹 Proposed fix
-	`@Test` func display_noneIsAcknowledged() {
-		`#expect`(RoutingError.none.display.contains("Acknowledged") || RoutingError.none.display.count > 0)
-	}
+	`@Test` func display_noneIsDeliveredToRecipient() {
+		`#expect`(RoutingError.none.display == "Delivered to recipient")
+	}
🤖 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/RoutingAndMiscTests.swift` around lines 49 - 51, The
display_noneIsAcknowledged test in RoutingAndMiscTests is stale and too weak
because it always passes, so update it to assert the exact new
RoutingError.none.display value or remove it as redundant. Use the
RoutingError.none.display symbol and align the expectation with the existing
EnumTests.swift check for "Delivered to recipient" so the test verifies the
rename precisely.
🧹 Nitpick comments (3)
Meshtastic/Extensions/SwiftData/MessageEntityExtension.swift (1)

14-81: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Relocate MessageDeliveryStatus/MessageDeliveryStatusLabel out of MessageEntityExtension.swift.

These are standalone types, not MessageEntity extensions, and don't match this file's name. As per coding guidelines, "Make file names match the primary type they define" and "Group extensions by functionality in separate files, such as AccessoryManager+ToRadio.swift." Consider moving these into a dedicated MessageDeliveryStatus.swift.

🤖 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 `@Meshtastic/Extensions/SwiftData/MessageEntityExtension.swift` around lines 14
- 81, The issue is that MessageDeliveryStatus and MessageDeliveryStatusLabel are
standalone types living in a file named like an extension file, which violates
the file/type organization guidelines. Move these types out of
MessageEntityExtension.swift into a dedicated MessageDeliveryStatus.swift (or
similarly named file), and leave MessageEntityExtension.swift for actual
MessageEntity-related extensions only.

Source: Coding guidelines

Meshtastic/Views/Messages/ChannelMessageRow.swift (1)

143-145: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Compute deliveryStatus once per row instead of twice.

message.deliveryStatus(isDirectMessage: false) is invoked separately for the retry gate (Line 143) and the label (Line 153). Since it's pure but non-trivial (RoutingError lookup + several localized strings), hoist it into a single let for clarity and to avoid duplicate work on every row render.

♻️ Proposed consolidation
 VStack(alignment: isCurrentUser ? .trailing : .leading) {
 	let isDetectionSensorMessage = message.portNum == Int32(PortNum.detectionSensorApp.rawValue)
+	let deliveryStatus = message.deliveryStatus(isDirectMessage: false)
 	...
 	HStack {
 		MessageText(...) { ... } onTapback: { ... }
-		if isCurrentUser && message.deliveryStatus(isDirectMessage: false).canRetry {
+		if isCurrentUser && deliveryStatus.canRetry {
 			RetryButton(message: message, destination: .channel(channel))
 		}
 	}
 	...
 	HStack {
 		if isCurrentUser && !isDetectionSensorMessage {
-			MessageDeliveryStatusLabel(status: message.deliveryStatus(isDirectMessage: false))
+			MessageDeliveryStatusLabel(status: deliveryStatus)
 		}
 	}
 }

Also applies to: 150-154

🤖 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 `@Meshtastic/Views/Messages/ChannelMessageRow.swift` around lines 143 - 145,
The row in ChannelMessageRow is calling message.deliveryStatus(isDirectMessage:
false) more than once for the same render path, including the retry check and
the status label. Hoist that result into a single local let inside the relevant
row-building logic, then reuse the cached value for both the canRetry gate and
the label in ChannelMessageRow so the delivery status is computed once per row.
Meshtastic/Views/Messages/UserMessageRow.swift (1)

146-151: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Same duplicate deliveryStatus computation as ChannelMessageRow.swift.

message.deliveryStatus(isDirectMessage: true) is called once for the retry gate (Line 151) and again for the label (Line 161). Hoist into a single let at the top of rowContent (or right before this HStack) and reuse.

♻️ Proposed consolidation
 VStack(alignment: isCurrentUser ? .trailing : .leading) {
+	let deliveryStatus = message.deliveryStatus(isDirectMessage: true)
 	...
 	HStack {
 		MessageText(...) { ... } onTapback: { ... }
-		if isCurrentUser && message.deliveryStatus(isDirectMessage: true).canRetry {
+		if isCurrentUser && deliveryStatus.canRetry {
 			RetryButton(message: message, destination: .user(user))
 		}
 	}
 	...
 	HStack {
 		if isCurrentUser {
-			MessageDeliveryStatusLabel(status: message.deliveryStatus(isDirectMessage: true))
+			MessageDeliveryStatusLabel(status: deliveryStatus)
 		}
 	}
 }

Also applies to: 158-163

🤖 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 `@Meshtastic/Views/Messages/UserMessageRow.swift` around lines 146 - 151, The
row currently recomputes message.deliveryStatus(isDirectMessage: true) in
UserMessageRow.rowContent for both the retry check and the status label, so
hoist that value into a single local let near the start of rowContent (or just
before the HStack) and reuse it for both the canRetry gate and the label
rendering. Update the existing delivery-status references in UserMessageRow to
use the cached value, matching the consolidation already intended in
ChannelMessageRow.
🤖 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/MessageContextMenuItems.swift`:
- Around line 118-132: The MessageContextMenuItems branch logic is redundant and
applies fixedSize inconsistently. Consolidate the repeated
deliveryStatus(isDirectMessage:) lookup and
Text(status.text)/Text(status.detail) rendering into a single path, then apply
.fixedSize(horizontal: false, vertical: true) to both Text views consistently
for all current-user message states. Use the existing isCurrentUser,
message.receivedACK, message.ackError, and tapBackDestination.isDirectMessage
symbols to keep the behavior identical while preventing truncation in the Menu.

---

Outside diff comments:
In `@MeshtasticTests/RoutingAndMiscTests.swift`:
- Around line 49-51: The display_noneIsAcknowledged test in RoutingAndMiscTests
is stale and too weak because it always passes, so update it to assert the exact
new RoutingError.none.display value or remove it as redundant. Use the
RoutingError.none.display symbol and align the expectation with the existing
EnumTests.swift check for "Delivered to recipient" so the test verifies the
rename precisely.

---

Nitpick comments:
In `@Meshtastic/Extensions/SwiftData/MessageEntityExtension.swift`:
- Around line 14-81: The issue is that MessageDeliveryStatus and
MessageDeliveryStatusLabel are standalone types living in a file named like an
extension file, which violates the file/type organization guidelines. Move these
types out of MessageEntityExtension.swift into a dedicated
MessageDeliveryStatus.swift (or similarly named file), and leave
MessageEntityExtension.swift for actual MessageEntity-related extensions only.

In `@Meshtastic/Views/Messages/ChannelMessageRow.swift`:
- Around line 143-145: The row in ChannelMessageRow is calling
message.deliveryStatus(isDirectMessage: false) more than once for the same
render path, including the retry check and the status label. Hoist that result
into a single local let inside the relevant row-building logic, then reuse the
cached value for both the canRetry gate and the label in ChannelMessageRow so
the delivery status is computed once per row.

In `@Meshtastic/Views/Messages/UserMessageRow.swift`:
- Around line 146-151: The row currently recomputes
message.deliveryStatus(isDirectMessage: true) in UserMessageRow.rowContent for
both the retry check and the status label, so hoist that value into a single
local let near the start of rowContent (or just before the HStack) and reuse it
for both the canRetry gate and the label rendering. Update the existing
delivery-status references in UserMessageRow to use the cached value, matching
the consolidation already intended in ChannelMessageRow.
🪄 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: f5e3c1b0-66d5-4955-a569-0be97262082f

📥 Commits

Reviewing files that changed from the base of the PR and between 4148979 and e232172.

⛔ Files ignored due to path filters (1)
  • MeshtasticTests/__Snapshots__/SwiftUIViewSnapshotTests/messageDeliveryStatusStates.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • Meshtastic/Enums/RoutingError.swift
  • Meshtastic/Extensions/SwiftData/MessageEntityExtension.swift
  • Meshtastic/Views/Helpers/Help/AckErrors.swift
  • Meshtastic/Views/Messages/ChannelMessageRow.swift
  • Meshtastic/Views/Messages/MessageContextMenuItems.swift
  • Meshtastic/Views/Messages/UserMessageRow.swift
  • MeshtasticTests/EnumTests.swift
  • MeshtasticTests/MessageAckStatusRefreshTests.swift
  • MeshtasticTests/RoutingAndMiscTests.swift
  • MeshtasticTests/SwiftUIViewSnapshotTests.swift

Comment thread Meshtastic/Views/Messages/MessageContextMenuItems.swift Outdated
@RCGV1

RCGV1 commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

Latest follow-up pushed: 4bd2651

Issue links:

Evidence paths at this head:

  • MeshtasticTests/Snapshots/SwiftUIViewSnapshotTests/messageDeliveryStatusStates.png
  • docs/assets/screenshots/ackErrors.png
  • Meshtastic/Resources/docs/assets/screenshots/ackErrors.png

Validation:

  • git diff --check: passed
  • git diff --cached --check before commit: passed
  • bash scripts/build-docs.sh --output Meshtastic/Resources/docs: passed, 8.0 MB / 10 MB hard limit with existing 8 MB soft warning
  • bash scripts/copy-snapshots.sh --output Meshtastic/Resources/docs/assets/screenshots: copied 98 doc-referenced screenshots; unrelated cleanup deletion restored before commit
  • XcodeBuildMCP test_sim focused run: passed 54 tests, 0 failures (RoutingErrorTests, RoutingErrorDetailedTests, MessageAckStatusRefreshTests, AckErrorsSnapshotTests, MessageDeliveryStatusSnapshotTests)

Local swiftlint is unavailable here; relying on the GitHub SwiftLint check for that coverage. Full local suite was not run.

@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

🧹 Nitpick comments (1)
docs/user/messages.md (1)

115-131: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

New status table drops the icon column used elsewhere in this doc.

Every other table in this file (Channel Index, Channel Security, Contacts, Encryption) uses an Icon | Meaning pattern per the coding guidelines. This new table uses plain Status | Description text with no icons, which is inconsistent with the rest of the page and with the guideline requiring ![icon](...) references and an Icon column when documenting icon-backed states. Since the cohort description mentions AckErrors now shows "retry-aware icons," consider mirroring those icons here for consistency.
As per coding guidelines, "In markdown tables, use ![icon](...) for icon references and include at least | Icon | Description | columns."

🤖 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 `@docs/user/messages.md` around lines 115 - 131, The new status table is
inconsistent with the rest of the document because it omits the icon column used
for icon-backed states. Update the table in the messages doc so it follows the
same Icon/Description pattern as the other sections, using the relevant icon
references for each status and matching the coding guideline format. Keep the
content aligned with the existing status names by adjusting the table structure
and entries in the status table itself.

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.

Inline comments:
In `@docs/user/messages.md`:
- Around line 113-131: Update the message-bubble error table in the docs so it
matches the UI color semantics: the retryable RoutingError statuses should be
explicitly marked as orange, or remove the “red unless noted” phrasing if you
are not annotating colors. Use the existing status rows in the messages table to
add the color note for entries like Failed to deliver to mesh, No radio
interface, Duty cycle limit, Rate limited, No app response, Could not send
encrypted message, Recipient needs your key, Recipient key unavailable, and
Admin session expired.

---

Nitpick comments:
In `@docs/user/messages.md`:
- Around line 115-131: The new status table is inconsistent with the rest of the
document because it omits the icon column used for icon-backed states. Update
the table in the messages doc so it follows the same Icon/Description pattern as
the other sections, using the relevant icon references for each status and
matching the coding guideline format. Keep the content aligned with the existing
status names by adjusting the table structure and entries in the status table
itself.
🪄 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: c840e67a-7a75-450f-8d8e-4500535a0ce3

📥 Commits

Reviewing files that changed from the base of the PR and between bc3de8c and 4bd2651.

📒 Files selected for processing (9)
  • Meshtastic/Enums/RoutingError.swift
  • Meshtastic/Resources/docs/index.json
  • Meshtastic/Resources/docs/markdown/user/messages.md
  • Meshtastic/Resources/docs/markdown/user/settings.md
  • Meshtastic/Resources/docs/user/messages.html
  • Meshtastic/Resources/docs/user/settings.html
  • MeshtasticTests/EnumTests.swift
  • MeshtasticTests/RoutingAndMiscTests.swift
  • docs/user/messages.md
✅ Files skipped from review due to trivial changes (2)
  • Meshtastic/Resources/docs/user/settings.html
  • Meshtastic/Resources/docs/markdown/user/settings.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • MeshtasticTests/EnumTests.swift
  • MeshtasticTests/RoutingAndMiscTests.swift
  • Meshtastic/Enums/RoutingError.swift

Comment thread docs/user/messages.md Outdated
@RCGV1
RCGV1 marked this pull request as draft July 7, 2026 15:45
@RCGV1

RCGV1 commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

Follow-up pushed: 496645b

Changes:

  • Addressed CodeRabbit docs feedback by replacing the message status docs table with Icon / Color / Status / Description columns.
  • Marked retryable vs permanent statuses explicitly in the docs.
  • Collapsed NO_ROUTE, GOT_NAK, and TIMEOUT display text to the design issue's source-backed generic delivery failure wording: Failed to deliver to mesh.
  • Removed the previously generated Mesh Beacon settings docs drift from this PR.
  • Refreshed docs/assets/screenshots/ackErrors.png and Meshtastic/Resources/docs/assets/screenshots/ackErrors.png.

Validation:

  • git diff --check: passed
  • git diff --cached --check before commit: passed
  • bash scripts/build-docs.sh --output Meshtastic/Resources/docs: passed, 7.9 MB / 10 MB hard limit
  • bash scripts/copy-snapshots.sh --output Meshtastic/Resources/docs/assets/screenshots: copied 98 doc-referenced screenshots; unrelated cleanup deletion restored before commit
  • XcodeBuildMCP test_sim focused run: passed 53 tests, 0 failures (RoutingErrorTests, RoutingErrorDetailedTests, MessageAckStatusRefreshTests, AckErrorsSnapshotTests)

Remaining local note: Meshtastic.xcworkspace/xcshareddata/swiftpm/Package.resolved is still an unrelated unstaged local change and was not committed.

@RCGV1
RCGV1 marked this pull request as ready for review July 7, 2026 18:38
@RCGV1

RCGV1 commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Reviews resumed.

RCGV1 commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

Follow-up pushed: e169b28

Changes:

  • The retry affordance now opens the delivery status detail text before retrying.
  • Retry still deletes the failed original message and sends a fresh message, preserving the existing retry behavior.
  • Expanded routing-error detail text now matches the source-backed wording from the design issue and message-status docs.

Validation:

  • git diff --check: passed
  • git diff --cached --check before commit: passed
  • Focused simulator test run passed: 53 tests, 0 failures
    • MeshtasticTests/RoutingErrorTests
    • MeshtasticTests/RoutingErrorDetailedTests
    • MeshtasticTests/MessageAckStatusRefreshTests
  • swiftlint is not installed in this local environment; GitHub CI should cover it.

Real-device screenshot evidence:

Delivered to mesh status

Relayed not confirmed status

@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

🧹 Nitpick comments (1)
MeshtasticTests/RoutingAndMiscTests.swift (1)

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

Remove redundant test.

The test description_noChannelUsesSourceBackedMeaning redundantly asserts RoutingError.noChannel.description, which is already validated identically inside the expected array of the description_usesActionableDesignIssueWording test immediately below it.

♻️ Proposed refactor
-	`@Test` func description_noChannelUsesSourceBackedMeaning() {
-		`#expect`(RoutingError.noChannel.description == "The sender or recipient could not use a matching channel/key for this message.")
-	}
-
🤖 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/RoutingAndMiscTests.swift` around lines 84 - 87, Remove the
redundant description_noChannelUsesSourceBackedMeaning test, leaving the
identical RoutingError.noChannel.description assertion covered by the expected
array in description_usesActionableDesignIssueWording.
🤖 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/RetryButton.swift`:
- Around line 54-60: Implement the missing channel refresh inside the MainActor
Task in the .channel branch: bind or retrieve the associated channel entity and
trigger its objectWillChange (or refresh the relevant context) after sending, so
the view updates immediately. Preserve the existing user-destination behavior
and channel-specific flow.

---

Nitpick comments:
In `@MeshtasticTests/RoutingAndMiscTests.swift`:
- Around line 84-87: Remove the redundant
description_noChannelUsesSourceBackedMeaning test, leaving the identical
RoutingError.noChannel.description assertion covered by the expected array in
description_usesActionableDesignIssueWording.
🪄 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: 5666e595-bf45-4114-9746-01d620fff6cf

📥 Commits

Reviewing files that changed from the base of the PR and between 496645b and e169b28.

📒 Files selected for processing (5)
  • Meshtastic/Enums/RoutingError.swift
  • Meshtastic/Views/Messages/ChannelMessageRow.swift
  • Meshtastic/Views/Messages/RetryButton.swift
  • Meshtastic/Views/Messages/UserMessageRow.swift
  • MeshtasticTests/RoutingAndMiscTests.swift
🚧 Files skipped from review as they are similar to previous changes (2)
  • Meshtastic/Views/Messages/UserMessageRow.swift
  • Meshtastic/Views/Messages/ChannelMessageRow.swift

Comment thread Meshtastic/Views/Messages/RetryButton.swift
@RCGV1

RCGV1 commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

Follow-up pushed: 508c5a38

Addressed review feedback:

  • Channel message retries now reload the channel list after a successful resend, so deleting the failed message and sending the replacement updates the visible timeline immediately.
  • Removed the redundant no-channel detail test; the same wording remains covered by the shared routing detail assertions.

Validation:

  • git diff --check
  • git diff --cached --check
  • xcodebuild test -workspace Meshtastic.xcworkspace -scheme Meshtastic -destination id=DE3343B3-1E9D-4C2D-9AFE-B50AC465BEBA -derivedDataPath /tmp/meshtastic-ios-status-detail-tests -only-testing:MeshtasticTests/RoutingErrorTests -only-testing:MeshtasticTests/RoutingErrorDetailedTests -only-testing:MeshtasticTests/MessageAckStatusRefreshTests

Focused simulator result: 52 tests passed.

@garthvh garthvh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Wording verified against the merged Android counterpart (meshtastic/Meshtastic-Android#6121) earlier in this alignment effort. The routing-error semantics were sourced from firmware review per the meshtastic/design#43 thread. One known cross-platform naming inconsistency to track separately: Android's no_channel string says 'No channel selected' while iOS says 'Channel/key mismatch'.

@garthvh
garthvh merged commit e886046 into meshtastic:main Jul 16, 2026
4 checks passed
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.

[Alignment]: Standardize message status wording and presentation

2 participants