mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 22:05:21 +00:00
Fix crash from duplicate peer IDs in Dictionary initialization
- Added deduplication logic in ChatViewModel to handle duplicate peer IDs gracefully - Enhanced PeerManager to prevent duplicate peers by tracking both nicknames and IDs - Added final safety check to ensure no duplicates in peers array - This fixes crash when Dictionary(uniqueKeysWithValues:) encounters duplicate keys
This commit is contained in:
@@ -143,6 +143,7 @@ class PeerManager: ObservableObject {
|
|||||||
// Build peer list
|
// Build peer list
|
||||||
var allPeers: [BitchatPeer] = []
|
var allPeers: [BitchatPeer] = []
|
||||||
var connectedNicknames: Set<String> = []
|
var connectedNicknames: Set<String> = []
|
||||||
|
var addedPeerIDs: Set<String> = []
|
||||||
|
|
||||||
// Add connected mesh peers (only if actually connected or relay connected)
|
// Add connected mesh peers (only if actually connected or relay connected)
|
||||||
for (peerID, nickname) in meshPeers {
|
for (peerID, nickname) in meshPeers {
|
||||||
@@ -180,6 +181,9 @@ class PeerManager: ObservableObject {
|
|||||||
connectedNicknames.insert(nickname)
|
connectedNicknames.insert(nickname)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track that we've added this peer ID
|
||||||
|
addedPeerIDs.insert(peerID)
|
||||||
|
|
||||||
var peer = BitchatPeer(
|
var peer = BitchatPeer(
|
||||||
id: peerID,
|
id: peerID,
|
||||||
noisePublicKey: noiseKey,
|
noisePublicKey: noiseKey,
|
||||||
@@ -221,6 +225,13 @@ class PeerManager: ObservableObject {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip if we already added a peer with this ID (prevents duplicates)
|
||||||
|
if addedPeerIDs.contains(favoriteID) {
|
||||||
|
SecureLogger.log(" - Skipping '\(favorite.peerNickname)' - peer ID already added",
|
||||||
|
category: SecureLogger.session, level: .debug)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Only add peers that WE favorite (not just ones who favorite us)
|
// Only add peers that WE favorite (not just ones who favorite us)
|
||||||
if !favorite.isFavorite {
|
if !favorite.isFavorite {
|
||||||
SecureLogger.log(" - Skipping '\(favorite.peerNickname)' - we don't favorite them (they favorite us: \(favorite.theyFavoritedUs))",
|
SecureLogger.log(" - Skipping '\(favorite.peerNickname)' - we don't favorite them (they favorite us: \(favorite.theyFavoritedUs))",
|
||||||
@@ -241,6 +252,7 @@ class PeerManager: ObservableObject {
|
|||||||
// Set favorite status
|
// Set favorite status
|
||||||
peer.favoriteStatus = favorite
|
peer.favoriteStatus = favorite
|
||||||
peer.nostrPublicKey = favorite.peerNostrPublicKey
|
peer.nostrPublicKey = favorite.peerNostrPublicKey
|
||||||
|
addedPeerIDs.insert(favoriteID) // Track that we've added this ID
|
||||||
allPeers.append(peer)
|
allPeers.append(peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +299,20 @@ class PeerManager: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.peers = allPeers
|
// Final safety check: ensure no duplicate IDs
|
||||||
|
var finalPeers: [BitchatPeer] = []
|
||||||
|
var seenIDs: Set<String> = []
|
||||||
|
for peer in allPeers {
|
||||||
|
if !seenIDs.contains(peer.id) {
|
||||||
|
seenIDs.insert(peer.id)
|
||||||
|
finalPeers.append(peer)
|
||||||
|
} else {
|
||||||
|
SecureLogger.log("⚠️ Removing duplicate peer ID in final check: \(peer.id) (\(peer.displayName))",
|
||||||
|
category: SecureLogger.session, level: .warning)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.peers = finalPeers
|
||||||
self.favorites = favorites
|
self.favorites = favorites
|
||||||
self.mutualFavorites = mutualFavorites
|
self.mutualFavorites = mutualFavorites
|
||||||
|
|
||||||
|
|||||||
@@ -220,7 +220,18 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
// Update peers directly
|
// Update peers directly
|
||||||
self?.allPeers = peers
|
self?.allPeers = peers
|
||||||
// Update peer index for O(1) lookups
|
// Update peer index for O(1) lookups
|
||||||
self?.peerIndex = Dictionary(uniqueKeysWithValues: peers.map { ($0.id, $0) })
|
// Deduplicate peers by ID to prevent crash from duplicate keys
|
||||||
|
var uniquePeers: [String: PeerData] = [:]
|
||||||
|
for peer in peers {
|
||||||
|
// Keep the first occurrence of each peer ID
|
||||||
|
if uniquePeers[peer.id] == nil {
|
||||||
|
uniquePeers[peer.id] = peer
|
||||||
|
} else {
|
||||||
|
SecureLogger.log("⚠️ Duplicate peer ID detected: \(peer.id) (\(peer.displayName))",
|
||||||
|
category: SecureLogger.session, level: .warning)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self?.peerIndex = uniquePeers
|
||||||
// Schedule UI update if peers changed
|
// Schedule UI update if peers changed
|
||||||
if peers.count > 0 || self?.allPeers.count ?? 0 > 0 {
|
if peers.count > 0 || self?.allPeers.count ?? 0 > 0 {
|
||||||
// UI will update automatically
|
// UI will update automatically
|
||||||
|
|||||||
Reference in New Issue
Block a user