mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 03:25:19 +00:00
* 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>
231 lines
6.8 KiB
Swift
231 lines
6.8 KiB
Swift
//
|
|
// MockBLEService.swift
|
|
// bitchatTests
|
|
//
|
|
// This is free and unencumbered software released into the public domain.
|
|
// For more information, see <https://unlicense.org>
|
|
//
|
|
|
|
import Foundation
|
|
import CoreBluetooth
|
|
@testable import bitchat
|
|
|
|
// Mock implementation that mimics BLEService behavior
|
|
class MockBLEService: NSObject {
|
|
|
|
// MARK: - Properties matching BLEService
|
|
|
|
weak var delegate: BitchatDelegate?
|
|
var myPeerID: String = "MOCK1234"
|
|
var myNickname: String = "MockUser"
|
|
|
|
// Test-specific properties
|
|
var sentMessages: [(message: BitchatMessage, packet: BitchatPacket)] = []
|
|
var sentPackets: [BitchatPacket] = []
|
|
var connectedPeers: Set<String> = []
|
|
var messageDeliveryHandler: ((BitchatMessage) -> Void)?
|
|
var packetDeliveryHandler: ((BitchatPacket) -> Void)?
|
|
|
|
// Compatibility properties for old tests
|
|
var mockNickname: String {
|
|
get { return myNickname }
|
|
set { myNickname = newValue }
|
|
}
|
|
|
|
var nickname: String {
|
|
return myNickname
|
|
}
|
|
|
|
var peerID: String {
|
|
return myPeerID
|
|
}
|
|
|
|
// MARK: - Initialization
|
|
|
|
override init() {
|
|
super.init()
|
|
}
|
|
|
|
// MARK: - Methods matching BLEService
|
|
|
|
func setNickname(_ nickname: String) {
|
|
self.myNickname = nickname
|
|
}
|
|
|
|
func startServices() {
|
|
// Mock implementation - do nothing
|
|
}
|
|
|
|
func stopServices() {
|
|
// Mock implementation - do nothing
|
|
}
|
|
|
|
func isPeerConnected(_ peerID: String) -> Bool {
|
|
return connectedPeers.contains(peerID)
|
|
}
|
|
|
|
func getPeerNicknames() -> [String: String] {
|
|
var nicknames: [String: String] = [:]
|
|
for peer in connectedPeers {
|
|
nicknames[peer] = "MockPeer_\(peer)"
|
|
}
|
|
return nicknames
|
|
}
|
|
|
|
func getPeers() -> [String: String] {
|
|
return getPeerNicknames()
|
|
}
|
|
|
|
func sendMessage(_ content: String, mentions: [String] = [], to recipientID: String? = nil, messageID: String? = nil, timestamp: Date? = nil) {
|
|
let message = BitchatMessage(
|
|
id: messageID ?? UUID().uuidString,
|
|
sender: myNickname,
|
|
content: content,
|
|
timestamp: timestamp ?? Date(),
|
|
isRelay: false,
|
|
originalSender: nil,
|
|
isPrivate: recipientID != nil,
|
|
recipientNickname: nil,
|
|
senderPeerID: myPeerID,
|
|
mentions: mentions.isEmpty ? nil : mentions
|
|
)
|
|
|
|
if let payload = message.toBinaryPayload() {
|
|
let packet = BitchatPacket(
|
|
type: 0x01,
|
|
senderID: myPeerID.data(using: .utf8)!,
|
|
recipientID: recipientID?.data(using: .utf8),
|
|
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
|
payload: payload,
|
|
signature: nil,
|
|
ttl: 3
|
|
)
|
|
|
|
sentMessages.append((message, packet))
|
|
sentPackets.append(packet)
|
|
|
|
// Simulate local echo
|
|
DispatchQueue.main.async { [weak self] in
|
|
self?.delegate?.didReceiveMessage(message)
|
|
}
|
|
|
|
// Call delivery handler if set
|
|
messageDeliveryHandler?(message)
|
|
}
|
|
}
|
|
|
|
func sendPrivateMessage(_ content: String, to recipientPeerID: String, recipientNickname: String, messageID: String) {
|
|
let message = BitchatMessage(
|
|
id: messageID,
|
|
sender: myNickname,
|
|
content: content,
|
|
timestamp: Date(),
|
|
isRelay: false,
|
|
originalSender: nil,
|
|
isPrivate: true,
|
|
recipientNickname: recipientNickname,
|
|
senderPeerID: myPeerID,
|
|
mentions: nil
|
|
)
|
|
|
|
if let payload = message.toBinaryPayload() {
|
|
let packet = BitchatPacket(
|
|
type: 0x01,
|
|
senderID: myPeerID.data(using: .utf8)!,
|
|
recipientID: recipientPeerID.data(using: .utf8)!,
|
|
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
|
payload: payload,
|
|
signature: nil,
|
|
ttl: 3
|
|
)
|
|
|
|
sentMessages.append((message, packet))
|
|
sentPackets.append(packet)
|
|
|
|
// Simulate local echo
|
|
DispatchQueue.main.async { [weak self] in
|
|
self?.delegate?.didReceiveMessage(message)
|
|
}
|
|
|
|
// Call delivery handler if set
|
|
messageDeliveryHandler?(message)
|
|
}
|
|
}
|
|
|
|
func sendFavoriteNotification(to peerID: String, isFavorite: Bool) {
|
|
// Mock implementation
|
|
}
|
|
|
|
func sendReadReceipt(_ receipt: ReadReceipt, to peerID: String) {
|
|
// Mock implementation
|
|
}
|
|
|
|
func sendBroadcastAnnounce() {
|
|
// Mock implementation
|
|
}
|
|
|
|
func getPeerFingerprint(_ peerID: String) -> String? {
|
|
return nil
|
|
}
|
|
|
|
func getNoiseSessionState(for peerID: String) -> LazyHandshakeState {
|
|
return .none
|
|
}
|
|
|
|
func triggerHandshake(with peerID: String) {
|
|
// Mock implementation
|
|
}
|
|
|
|
func emergencyDisconnectAll() {
|
|
connectedPeers.removeAll()
|
|
delegate?.didUpdatePeerList([])
|
|
}
|
|
|
|
func getNoiseService() -> NoiseEncryptionService {
|
|
return NoiseEncryptionService()
|
|
}
|
|
|
|
func getFingerprint(for peerID: String) -> String? {
|
|
return nil
|
|
}
|
|
|
|
// MARK: - Test Helper Methods
|
|
|
|
func simulateConnectedPeer(_ peerID: String) {
|
|
connectedPeers.insert(peerID)
|
|
delegate?.didConnectToPeer(peerID)
|
|
delegate?.didUpdatePeerList(Array(connectedPeers))
|
|
}
|
|
|
|
func simulateDisconnectedPeer(_ peerID: String) {
|
|
connectedPeers.remove(peerID)
|
|
delegate?.didDisconnectFromPeer(peerID)
|
|
delegate?.didUpdatePeerList(Array(connectedPeers))
|
|
}
|
|
|
|
func simulateIncomingMessage(_ message: BitchatMessage) {
|
|
delegate?.didReceiveMessage(message)
|
|
}
|
|
|
|
func simulateIncomingPacket(_ packet: BitchatPacket) {
|
|
// Process through the actual handling logic
|
|
if let message = BitchatMessage.fromBinaryPayload(packet.payload) {
|
|
delegate?.didReceiveMessage(message)
|
|
}
|
|
packetDeliveryHandler?(packet)
|
|
}
|
|
|
|
func getConnectedPeers() -> [String] {
|
|
return Array(connectedPeers)
|
|
}
|
|
|
|
// MARK: - Compatibility methods for old tests
|
|
|
|
func sendPrivateMessage(_ content: String, to recipientPeerID: String, recipientNickname: String, messageID: String? = nil) {
|
|
sendPrivateMessage(content, to: recipientPeerID, recipientNickname: recipientNickname, messageID: messageID ?? UUID().uuidString)
|
|
}
|
|
}
|
|
|
|
// Backward compatibility for older tests
|
|
typealias MockSimplifiedBluetoothService = MockBLEService
|