From bdbc0a6cfe47d4a29b5fe3e9ab7861b6565ebc62 Mon Sep 17 00:00:00 2001 From: jack Date: Thu, 24 Jul 2025 15:11:45 +0200 Subject: [PATCH] Fix duplicate disconnect messages when Mac app closes - Added gracefullyLeftPeers tracking to prevent duplicate disconnect messages - Show disconnect message immediately when leave announcement is received - Skip duplicate message when physical disconnect happens after graceful leave - Fixed API misuse by adding peripheral.state checks before readRSSI() calls - Added debug logging to track graceful leave flow --- bitchat/Services/BluetoothMeshService.swift | 24 +++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/bitchat/Services/BluetoothMeshService.swift b/bitchat/Services/BluetoothMeshService.swift index 34616c70..60cc164f 100644 --- a/bitchat/Services/BluetoothMeshService.swift +++ b/bitchat/Services/BluetoothMeshService.swift @@ -2495,18 +2495,13 @@ class BluetoothMeshService: NSObject { // Mark as gracefully left to prevent duplicate disconnect message self.gracefullyLeftPeers.insert(senderID) - // Remove after a delay to handle race conditions with physical disconnect - DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { [weak self] in - self?.gracefullyLeftPeers.remove(senderID) - } - - SecureLogger.log("📴 Peer left network: \(senderID) (\(nickname))", category: SecureLogger.session, level: .info) + SecureLogger.log("📴 Peer left network: \(senderID) (\(nickname)) - marked as gracefully left", category: SecureLogger.session, level: .info) } } announcedPeers.remove(senderID) - // Show leave message + // Show disconnect message immediately when peer leaves DispatchQueue.main.async { self.delegate?.didDisconnectFromPeer(senderID) } @@ -3376,8 +3371,18 @@ extension BluetoothMeshService: CBCentralManagerDelegate { // Reset handshake state to prevent stuck handshakes handshakeCoordinator.resetHandshakeState(for: peerID) - // Notify delegate immediately about disconnect (unless peer gracefully left) - if !gracefullyLeftPeers.contains(peerID) { + // Check if peer gracefully left and notify delegate + let shouldNotifyDisconnect = collectionsQueue.sync { + let isGracefullyLeft = self.gracefullyLeftPeers.contains(peerID) + if isGracefullyLeft { + SecureLogger.log("Physical disconnect for \(peerID) - was gracefully left, NOT notifying delegate", category: SecureLogger.session, level: .info) + } else { + SecureLogger.log("Physical disconnect for \(peerID) - was NOT gracefully left, will notify delegate", category: SecureLogger.session, level: .info) + } + return !isGracefullyLeft + } + + if shouldNotifyDisconnect { DispatchQueue.main.async { self.delegate?.didDisconnectFromPeer(peerID) } @@ -3442,6 +3447,7 @@ extension BluetoothMeshService: CBCentralManagerDelegate { } else { // Peer gracefully left, just clean up the tracking self.gracefullyLeftPeers.remove(peerID) + SecureLogger.log("Cleaning up gracefullyLeftPeers for \(peerID)", category: SecureLogger.session, level: .debug) } }