fix(MessageBubble): clamp future-dated timestamps to now#66
Draft
torlando-agent[bot] wants to merge 1 commit into
Draft
fix(MessageBubble): clamp future-dated timestamps to now#66torlando-agent[bot] wants to merge 1 commit into
torlando-agent[bot] wants to merge 1 commit into
Conversation
A peer with a fast clock (or our own clock corrected backward by NTP between pack-time and view-time) can stamp a wire timestamp ahead of local time. Rendering it through RelativeDateTimeFormatter then yields strings like "in 5 min" on a message that has already arrived. Clamp the timestamp passed to the formatter to min(timestamp, now) so future wire timestamps render as the formatter's "now" string instead. Refs #60 Co-Authored-By: Claude claude-opus-4-7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the iOS half of the approved plan for #60.
Summary
LXMF wire format puts a single timestamp on each message: the sender's
time.time()at pack time (set inLXMessage.swift:171-179, matchingRNS/LXMF/LXMessage.py:362). Columba-iOS treats that field as the canonical timestamp for both display and ordering — seeMessageBubble.swift:329, 384for display, andLXMFDatabase.swift:447, 213for the SQLORDER BY timestamp DESCthat drives the chat ScrollView. Result: any clock skew between two devices (or any clock drift on the local device) leaks straight into the UI as out-of-order messages and "in 5 min" relative-time strings. Both observed symptoms collapse to that one cause.The fix has two halves: (1) sort the chat scroll by local arrival time (
created_at, already populated on every save inMessageRecord.swift:182-184), so a peer with a stale or fast clock can't reorder my own thread; (2) clamp displayed relative time so a future-dated wire timestamp renders as "Just now" instead of "in 5 min".This PR is half (2) — the iOS clamp. Half (1) lives in LXMF-swift and ships as a separate PR per the plan's split.
Changes
Sources/ColumbaApp/Views/Messaging/MessageBubble.swift— clampMessage.formattedTimetomin(timestamp, Date())before handing toRelativeDateTimeFormatter. The bubble's absolute-time formatter atMessageDetailView.swift:527is intentionally left alone — that view shows raw protocol-level metadata.Tests/ColumbaAppTests/MessageFormattedTimeTests.swift— new test file with two cases: future-dated timestamps render as the formatter's "now" string; past-dated timestamps still render the formatter's relative-past string.Columba.xcodeproj/project.pbxproj— wire the new test file into theColumbaAppTeststarget (PBXBuildFile / PBXFileReference / group / sources phase).Test plan
test_formattedTime_clampsFutureTimestampToNow— constructs a 600 s future-datedMessage, assertsformattedTime == formatter.localizedString(for: now, relativeTo: now). Captures whatever the formatter actually emits rather than hard-coding "Just now" so locale variation doesn't break it.test_formattedTime_pastTimestampsRenderRelativePast— regression guard that the clamp doesn't affect past timestamps.xcodebuild test -only-testing:ColumbaAppTests— 67 passed, 0 failed.xcodebuild buildclean (warnings present in the build log are pre-existing Swift 6 sendability warnings unrelated to this change).Implementer notes
created_at. This iOS PR alone covers the "in 5 min" symptom only; the out-of-order-messages symptom needs the LXMF-swift PR. Commit message usesRefs #60(notCloses) for that reason.Package.swiftversion bump for LXMF-swift in this PR — the LXMF-swift change isn't released yet, so bumping the pin would break SPM resolution. The bump should land in the LXMF-swift PR's follow-up or a coordination PR once the LXMF-swift release is tagged.🤖 Generated with Claude Code