Conversation
Aligns chat input placeholder text with the terminology used throughout the MeshCore ecosystem. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add MeshCoreOpenReactionParser with v3 (r:xxxx:yy) and v1
(r:{millis}_{nameHash}_{textHash}:{emoji}) parsing
- Add fetchChannelMessageCandidates and fetchDMMessageCandidates
to PersistenceStoreProtocol for MCO candidate lookup
- Wire MCO v3 and v1 handlers into channel and DM reaction pipelines
- Update isReactionText to recognize both MCO formats
- Sort messages by createdAt (local receive time) over sender timestamp to handle skewed clocks - Add reorderSameSenderClusters() to re-sort rapid same-sender bursts by sender timestamp - Re-run cluster reordering after page merges to fix clusters split across boundaries - Add MessageDTO.senderDate; date now returns createdAt - Use createdAt for timestamp gap calculation in DisplayFlags - Add indexes on createdAt in Message SwiftData model
- Relocates reorderSameSenderClusters and isSameSender from PersistenceStore to MessageDTO where the logic belongs - Makes sameSenderReorderWindow private (implementation detail) - Fixes isSameSender asymmetry: guard both messages are the same type (DM or channel) before clustering - Updates all call sites and test references
- Show static "GPS Source: Phone GPS" row when device lacks built-in GPS - Alert and revert toggle when enabling auto-update with denied location permission - Alert and revert picker when switching to Phone GPS with denied location permission - Use UIApplication.openSettingsURLString instead of undocumented "app-settings:"
- Rewrote deleteChannelConversation to wait for BLE confirmation instead of optimistic removal, eliminating the reappearance bug on tab switch - Made deleteChannel throw so errors propagate to the call site - Added retry/dismiss alert on failure using alert(_:isPresented:presenting:) - Added "Try Again" button to ChannelInfoSheet error section
…return - Extract duplicated split/stack navigation reset into clearNavigationIfActive(_:), removing 3 identical inline blocks - Fix deleteChannel guard returning silently when services are nil — now throws ChannelDeleteError.servicesUnavailable so the caller correctly shows the failure alert
- Inject parent horizontalSizeClass into MessageActionsSheet environment so the sheet sees the real window size class, not the compact override SwiftUI applies inside sheets on iPad - Remove isRegularWidth: Bool parameter; sheet reads horizontalSizeClass naturally from environment - ChatView and ChannelChatView inject their size class via .environment(\.horizontalSizeClass, ...)
…mands - Change suggestedTimeoutMs multiplier from 1.2x to 2.0x in performStatusRequest, performTelemetryRequest, performMMARequest, performACLRequest, and performNeighboursRequest to account for full round-trip (outbound + response) - CLI commands now capture MessageSentInfo from sendCommand instead of discarding it, and derive a firmware-aware timeout using 2x suggestedTimeoutMs with the caller-supplied timeout as a floor - Add diagnostic logging to performStatusRequest and performTelemetryRequest to capture messageSent arrival, timeout values, and elapsed time
- preserve MeshCore advert policy values for gps and prefs modes - restore location adverts for phone-backed nodes without gps
- Add getMessage(timeout:) override to MeshCoreSession for per-call budgets - Introduce RemoteOperationTimeoutPolicy with capped login, CLI, and binary timeouts - Wrap login and CLI flows with withTaskCancellationHandler for clean cancellation - Move repeater status/neighbors/telemetry timeout ownership to service layer with deadline-based retry budget - Replace Date() deadlines in CLI poll loops with ContinuousClock for monotonicity - Cancel authenticationTask on dismiss in NodeAuthenticationSheet - Remove UI-side timeout tasks from RepeaterStatusViewModel - Use localized string for login timeout errors
- turn off device GPS before saving or clearing a manual location - keep location settings, sharing behavior, and verification in sync with device state
…writes, clean debug comments
…w structs - Remove 3 per-render extractFirstURL calls from view bodies; forward detectedURL from MessageDisplayItem via MessageDisplayState - Cache NSRegularExpression for mention pattern in LinkPreviewService - Add cachedURLs dictionary to ChatViewModel; buildDisplayItems uses cached results and defers async detection for new messages - Hoist MessageBubbleConfiguration.channel(...) out of per-cell closure - Extract messagesView/emptyMessagesView into ChannelMessagesContent and ChannelEmptyMessagesView structs
- Batch-fetch message previews in two actor calls instead of N sequential hops (one per contact/channel) via new fetchLastMessages/fetchLastChannelMessages - Hoist TimelineView(.everyMinute) to list level so one timer fires instead of one per visible row - Extract ConversationSelectionRow/ConversationNavigationRow as View structs for better SwiftUI identity tracking in ForEach
- Replace bare UInt8 bitmask with AutoAddConfig struct bundling bitmask + maxHops - Update PacketBuilder to serialize maxHops as second byte - Update PacketParser to parse optional maxHops byte (backward-compatible) - Update MeshCoreSession get/set signatures to use AutoAddConfig - Add tests for maxHops serialization and parsing
- Add autoAddMaxHops to Device/DeviceDTO with v1.14+ capability check - Thread AutoAddConfig through ConnectionManager and SettingsService - Add max hop distance picker to NodesSettingsSection - Add localization strings for max hops options across all languages
- updateAutoAddConfig now saves to the data store after updating in-memory state, matching the pattern used by updateClientRepeat and updatePathHashMode
- Add translations for nodes.maxHops.* keys across de, es, fr, nl, pl, ru, uk, zh-Hans
- Add advert.zerohop and discover.neighbors to repeaterCommands - Add path.hash.mode, loop.detect, bootloader.ver to getSetParams - Add value completion for set path.hash.mode (0/1/2) and set loop.detect (off/minimal/moderate/strict) - Add 8 tests covering new commands, params, and value completions
- Replace raw Data params in LinkPreviewCard with pre-decoded UIImage - Add decodedPreviewImages/Icons state to ChatViewModel - Decode hero and icon images via Task.detached when previews load - Add decodeLegacyPreviewImages() for messages with embedded preview data
- Pre-compile NSRegularExpression for mentions and hashtags as static lets - Eliminate duplicate NSDataDetector scan by passing URL ranges from URL pass to hashtag pass - Extract formatting logic to a static buildFormattedText method so it can be called outside the SwiftUI view hierarchy - Cache AttributedString per message UUID in ChatViewModel (keyed by UUID, cleared on conversation switch and message deletion) - Wire pre-computed text through MessageDisplayState into BubbleContent - Replace text.distance O(n) URL-containment check with direct index comparison - Add explicit isOutgoing parameter to MessageText, removing the fragile baseColor == .white proxy - Pre-compile leading mention regex in buildReplyText
- Remove per-cell @AppStorage subscriptions from BubbleContent (200-600us each) - Read once in ChatView/ChannelChatView, pass through as let properties - Add showIncomingPath/showIncomingHopCount to MessageDisplayState - Follows established showInlineImages/autoPlayGIFs pattern
- Merge decodedPreviewImages/decodedPreviewIcons into decodedPreviewAssets to reduce Observable notifications from 2-3 to 1 per preview decode - Fix decodeLegacyPreviewImages guard: check data availability instead of cache presence, preventing wasteful no-op tasks on repeat calls - Parallelize hero/icon decode in legacy path with async let
- Adds computed property to eliminate repeated inline !isPublicChannel && !name.hasPrefix("#") checks
- Show lock.fill (blue) for encrypted chats, lock.open.fill (orange) for unencrypted - DMs always encrypted, private channels encrypted, public/hashtag/rooms unencrypted - Icon sits inside text field trailing edge with reserved padding - VoiceOver reads encryption status via accessibilityValue on the text field - Localized encryption labels across all 9 languages
- Add isDeviceConnectedToOtherApp check in pairNewDevice() after ASK picker returns - Catch BLEError.deviceConnectedToOtherApp in DeviceScanView to trigger existing alert
- Added PairingError.deviceConnectedToOtherApp(deviceID:) case - Added retryConnection button in DeviceScanView for other-app conflicts - Added [OtherAppCheck] diagnostic logging and systemConnectedPeripheralIDs() - Added localized strings for retry connection and connecting states
ASK pairing severs the other app's BLE connection. The other app auto-reconnects seconds later, so a single check immediately after ASK returns always misses it. Replace with a 6-check polling loop at 400ms intervals (~2s max).
- Add connectingDeviceID to track the active connect(to:) target - Replace blanket .connecting early-return with device-aware guard: same device is a no-op, different device cancels and falls through - Guard connectWithRetry loop and catch against supersession - Expand handleConnectionLoss early-return to cover both connectingDeviceID and reconnectionCoordinator.reconnectingDeviceID - Clear connectingDeviceID in cleanupConnection(), disconnect(reason:), and setTestState
fix(chats): rename "Private Message" placeholder to "Direct Message"
…cles - Expose reconnectGeneration via private(set) for cross-type visibility - Capture expected generation at rebuildSession entry point - Add generation equality checks after each await to bail out if a newer reconnect cycle has started, stopping the stale session to free resources
simulatorConnect() never set connectingDeviceID, so concurrent checkBLEConnectionHealth() → connect(to:) treated the in-progress connection as a different device and called cleanupResources(), niling out session before connectionState reached .ready.
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.
No description provided.