Fix peer nickname display once and for all

- Only show peers in UI who have announced (have nicknames)
- Filter out peers without nicknames from getAllConnectedPeerIDs()
- Send announces proactively when app starts, not just on connection
- Send announces immediately when nickname changes via saveNickname()
- Send announces when Bluetooth services become available
- Send announces multiple times (0.5s, 1s, 2s) for reliability
- Add sendBroadcastAnnounce() method for proactive announcing

This ensures peers always see proper nicknames, never 'person-xxx'
This commit is contained in:
jack
2025-07-03 23:38:17 +02:00
parent 7e8c5d0153
commit 34e51b3d9a
2 changed files with 75 additions and 32 deletions
+72 -32
View File
@@ -127,7 +127,33 @@ class BluetoothMeshService: NSObject {
startAdvertising() startAdvertising()
} }
// Don't send announcement here - wait for connections // Send initial announces after services are ready
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
self?.sendBroadcastAnnounce()
}
}
func sendBroadcastAnnounce() {
guard let vm = delegate as? ChatViewModel else { return }
let announcePacket = BitchatPacket(
type: MessageType.announce.rawValue,
ttl: 1,
senderID: myPeerID,
payload: Data(vm.nickname.utf8)
)
print("[ANNOUNCE] Sending proactive broadcast announce with nickname: \(vm.nickname)")
broadcastPacket(announcePacket)
// Send multiple times for reliability
for delay in [0.5, 1.0, 2.0] {
DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
guard let self = self else { return }
self.broadcastPacket(announcePacket)
print("[ANNOUNCE] Re-sending broadcast announce (delay: \(delay)s)")
}
}
} }
func startAdvertising() { func startAdvertising() {
@@ -336,12 +362,15 @@ class BluetoothMeshService: NSObject {
} }
private func getAllConnectedPeerIDs() -> [String] { private func getAllConnectedPeerIDs() -> [String] {
// Return all active peers, even if they haven't announced yet // Only return peers who have announced (have nicknames)
let uniquePeers = Set(activePeers.filter { peerID in let announcedPeers = Set(activePeers.filter { peerID in
peerID != "unknown" && peerID != myPeerID && peerID.count <= 8 // Filter out temp IDs peerID != "unknown" &&
peerID != myPeerID &&
peerID.count <= 8 && // Filter out temp IDs
peerNicknames[peerID] != nil // Only include peers who have announced
}) })
print("[DEBUG] Active peers: \(activePeers), myPeerID: \(myPeerID), filtered: \(uniquePeers)") print("[DEBUG] Active peers: \(activePeers), announced: \(announcedPeers), nicknames: \(peerNicknames.keys)")
return Array(uniquePeers).sorted() return Array(announcedPeers).sorted()
} }
private func broadcastPacket(_ packet: BitchatPacket) { private func broadcastPacket(_ packet: BitchatPacket) {
@@ -839,7 +868,10 @@ extension BluetoothMeshService: CBCentralManagerDelegate {
if central.state == .poweredOn { if central.state == .poweredOn {
startScanning() startScanning()
// Scanning will connect to peers and announce then // Send announces when central manager is ready
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
self?.sendBroadcastAnnounce()
}
} }
} }
@@ -945,22 +977,25 @@ extension BluetoothMeshService: CBPeripheralDelegate {
} }
// Send announce packet immediately after key exchange // Send announce packet immediately after key exchange
// Send both broadcast and targeted announce for reliability // Send multiple times for reliability
if let vm = self.delegate as? ChatViewModel { if let vm = self.delegate as? ChatViewModel {
// First, send broadcast announce // Send announces multiple times with delays
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in for delay in [0.1, 0.5, 1.0] {
guard let self = self else { return } DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
let announcePacket = BitchatPacket( guard let self = self else { return }
type: MessageType.announce.rawValue, let announcePacket = BitchatPacket(
ttl: 1, type: MessageType.announce.rawValue,
senderID: self.myPeerID, ttl: 1,
payload: Data(vm.nickname.utf8) senderID: self.myPeerID,
) payload: Data(vm.nickname.utf8)
self.broadcastPacket(announcePacket) )
self.broadcastPacket(announcePacket)
print("[KEY_EXCHANGE] Sent announce broadcast (delay: \(delay)s)")
}
} }
// Also send targeted announce to this specific peripheral // Also send targeted announce to this specific peripheral
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self, weak peripheral] in DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self, weak peripheral] in
guard let self = self, guard let self = self,
let peripheral = peripheral, let peripheral = peripheral,
let characteristic = peripheral.services?.first(where: { $0.uuid == BluetoothMeshService.serviceUUID })?.characteristics?.first(where: { $0.uuid == BluetoothMeshService.characteristicUUID }) else { return } let characteristic = peripheral.services?.first(where: { $0.uuid == BluetoothMeshService.serviceUUID })?.characteristics?.first(where: { $0.uuid == BluetoothMeshService.characteristicUUID }) else { return }
@@ -1056,7 +1091,10 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
setupPeripheral() setupPeripheral()
startAdvertising() startAdvertising()
// Scanning will connect to peers and announce then // Send announces when peripheral manager is ready
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
self?.sendBroadcastAnnounce()
}
default: default:
break break
} }
@@ -1097,19 +1135,21 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
} }
// Send announce immediately after key exchange // Send announce immediately after key exchange
// Broadcast announce to ensure all peers get it // Send multiple times for reliability
if let vm = self.delegate as? ChatViewModel { if let vm = self.delegate as? ChatViewModel {
DispatchQueue.main.async { [weak self] in for delay in [0.1, 0.5, 1.0] {
guard let self = self else { return } DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
let announcePacket = BitchatPacket( guard let self = self else { return }
type: MessageType.announce.rawValue, let announcePacket = BitchatPacket(
ttl: 1, type: MessageType.announce.rawValue,
senderID: self.myPeerID, ttl: 1,
payload: Data(vm.nickname.utf8) senderID: self.myPeerID,
) payload: Data(vm.nickname.utf8)
if let data = announcePacket.toBinaryData() { )
peripheral.updateValue(data, for: self.characteristic, onSubscribedCentrals: nil) if let data = announcePacket.toBinaryData() {
print("[ANNOUNCE] Sent broadcast announce as peripheral") peripheral.updateValue(data, for: self.characteristic, onSubscribedCentrals: nil)
print("[ANNOUNCE] Sent broadcast announce as peripheral (delay: \(delay)s)")
}
} }
} }
} }
+3
View File
@@ -61,6 +61,9 @@ class ChatViewModel: ObservableObject {
func saveNickname() { func saveNickname() {
userDefaults.set(nickname, forKey: nicknameKey) userDefaults.set(nickname, forKey: nicknameKey)
userDefaults.synchronize() // Force immediate save userDefaults.synchronize() // Force immediate save
// Send announce with new nickname to all peers
meshService.sendBroadcastAnnounce()
} }
private func loadFavorites() { private func loadFavorites() {