Refactor/ble nostr boundaries (#449)

* Refactor: move Nostr embedding and TLVs out of BLE; add NostrEmbeddedBitChat, Packets, PeerIDUtils; centralize MessageDeduplicator; update ChatViewModel to use new helpers; remove AI_CONTEXT.md and CLAUDE.md

* Rename class to BLEService with compatibility alias; move mention parsing out of BLE; emit low-level BLE events to delegate; unify hex helpers; accept 64-hex in isPeerConnected; add PeerIDResolver

* Project: rename file to BLEService.swift and update Xcode project; keep typealias SimplifiedBluetoothService = BLEService for compatibility

* Remove SimplifiedBluetoothService alias; update app code to use BLEService explicitly

* Tests: rename MockSimplifiedBluetoothService to MockBLEService; update typealiases and Xcode project

* Docs: update comments to refer to BLEService (tests, protocol, noise service)

* Tests: rename SimplifiedBluetoothServiceTests to BLEServiceTests; update project references and class names

* Introduce Transport protocol; BLEService conforms; document delegate-only event pattern in BLEService; keep publishers internal for UnifiedPeerService

* Adopt Transport end-to-end: add TransportPeerSnapshot + publishers; BLEService maps to Transport snapshots; UnifiedPeerService consumes Transport; ChatViewModel holds Transport

* Fix Transport integration: replace getPeerFingerprint with getFingerprint(for:); update PrivateChatManager and CommandProcessor to use Transport; add BLEService.getFingerprint(for:); update PeerManager to use Transport

* Refactor transport and BLE/Nostr layers; unify UI events; fix MainActor isolation

- Rename SimplifiedBluetoothService to BLEService and slim responsibilities
- Introduce Transport protocol and peerEventsDelegate for UI updates
- Add NostrTransport and MessageRouter to route PM/read/favorite via BLE or Nostr
- Centralize TLVs, PeerID utils, and MessageDeduplicator outside BLE
- Update UnifiedPeerService and ChatViewModel to use Transport and delegate events
- Fix MainActor isolation: route delegate calls via Task on MainActor; update notifyUI helper
- Adjust related files and tests accordingly

* BLEService: remove internal publishers; switch to delegate-only events

- Drop legacy messages/peers/fullPeers publishers
- Provide lightweight peerSnapshotSubject only to satisfy Transport
- Rework publishFullPeerData to build snapshots from internal state and notify delegate + subject
- Remove all peersPublisher.send call sites
- Keep UnifiedPeerService on delegate updates exclusively

* Remove inlined Nostr send helpers from ChatViewModel; route via MessageRouter

- Replace direct Nostr sends (PM, ACKs, favorites) with MessageRouter
- Add router method for delivery ACKs and implement NostrTransport.sendDeliveryAck
- Simplify ChatViewModel favorite notification path to use router
- Keep Nostr receive handling intact; reduce duplication

* Fix ReadReceipt initializer usage in ChatViewModel (readerID + readerNickname)

* Fix unused variable warning: replace shadowed 'nostrPubkey' bind with boolean check in ChatViewModel

* Fix queued PM format: use TLV for pending messages after Noise handshake

- Pending messages (including first-time favorite notifications) now use the same TLV encoding as normal sends
- Ensures ChatViewModel can decode on first send, even if handshake completes after queuing

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
jack
2025-08-17 15:17:04 +02:00
committed by GitHub
co-authored by jack
parent 3ebfa85e90
commit 6fbf7eee25
25 changed files with 873 additions and 1647 deletions
+5 -5
View File
@@ -18,9 +18,9 @@ class PrivateChatManager: ObservableObject {
private var selectedPeerFingerprint: String? = nil
var sentReadReceipts: Set<String> = [] // Made accessible for ChatViewModel
weak var meshService: SimplifiedBluetoothService?
weak var meshService: Transport?
init(meshService: SimplifiedBluetoothService? = nil) {
init(meshService: Transport? = nil) {
self.meshService = meshService
}
@@ -29,7 +29,7 @@ class PrivateChatManager: ObservableObject {
selectedPeer = peerID
// Store fingerprint for persistence across reconnections
if let fingerprint = meshService?.getPeerFingerprint(peerID) {
if let fingerprint = meshService?.getFingerprint(for: peerID) {
selectedPeerFingerprint = fingerprint
}
@@ -130,7 +130,7 @@ class PrivateChatManager: ObservableObject {
// Find peer with matching fingerprint
for (peerID, _) in peers {
if meshService?.getPeerFingerprint(peerID) == fingerprint {
if meshService?.getFingerprint(for: peerID) == fingerprint {
selectedPeer = peerID
break
}
@@ -186,4 +186,4 @@ class PrivateChatManager: ObservableObject {
// Send through mesh service's read receipt method
meshService?.sendReadReceipt(receipt, to: senderPeerID)
}
}
}