[codex] Refactor BLE outbound scheduling and Noise queues (#1306)

* Refactor BLE transport event handling

* Make image output paths unique

* Keep queued Nostr read receipts alive

* Refine BLE ingress fanout

* Rediscover BLE service after invalidation

* Extract BLE notification retry buffer

* Extract BLE inbound write buffer

* Extract BLE fragment assembly buffer

* Tidy secure log handling from device run

* Extract BLE outbound fragment scheduler

* Harden app CI media tests

* Redact BLE message content from logs

* Extract BLE Noise session queues

* Fix BLE read receipt UI updates

* Allow self-authored RSR ingress replies

* Harden read receipt queue test timing

* Extract BLE outbound policy and incoming file storage

* Avoid duplicate BLE link snapshots during send

* Canonicalize Nostr relay URLs

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
jack
2026-05-31 14:16:11 +02:00
committed by GitHub
co-authored by jack
parent df36b19afe
commit 9e84f5e822
19 changed files with 1084 additions and 629 deletions
+51
View File
@@ -516,6 +516,57 @@ struct ChatViewModelNoisePayloadTests {
#expect(delivered)
}
@Test @MainActor
func didReceiveNoisePayload_readReceiptUpdatesBeforePeerNicknameIsKnown() async {
let (viewModel, _) = makeTestableViewModel()
let peerID = PeerID(str: "0000000000000005")
let message = BitchatMessage(
id: "pm-read-before-name",
sender: viewModel.nickname,
content: "Waiting on read receipt",
timestamp: Date(),
isRelay: false,
originalSender: nil,
isPrivate: true,
recipientNickname: "Peer",
senderPeerID: viewModel.meshService.myPeerID,
mentions: nil,
deliveryStatus: .sent
)
viewModel.privateChats[peerID] = [message]
viewModel.didReceiveNoisePayload(
from: peerID,
type: .readReceipt,
payload: Data("pm-read-before-name".utf8),
timestamp: Date()
)
let privateChatUpdated = await TestHelpers.waitUntil({
guard let status = viewModel.privateChats[peerID]?.first?.deliveryStatus else { return false }
if case .read = status {
return true
}
return false
}, timeout: TestConstants.defaultTimeout)
let conversationStoreUpdated = await TestHelpers.waitUntil({
let messages = viewModel.conversationStore.directMessages(
for: peerID,
identityResolver: viewModel.identityResolver
)
guard let status = messages.first?.deliveryStatus else { return false }
if case .read = status {
return true
}
return false
}, timeout: TestConstants.defaultTimeout)
#expect(privateChatUpdated)
#expect(conversationStoreUpdated)
}
}
// MARK: - Formatting Tests