Fix blank message row and API misuse warnings

- Fix blank row appearing when peer disconnects by ensuring display names are never empty
- Add validation to prevent system messages with empty content from being displayed
- Fix API MISUSE warnings by adding connection state checks before writing to peripherals
- Improve write queue processing with additional safety checks
- Update activity tracking when processing queued writes

These fixes address UI glitches and improve Bluetooth reliability.
This commit is contained in:
jack
2025-07-23 21:02:51 +02:00
parent a33ba1678b
commit 391c80ef14
2 changed files with 38 additions and 14 deletions
+25 -9
View File
@@ -201,17 +201,26 @@ class BluetoothMeshService: NSObject {
private func writeToPeripheral(_ data: Data, peripheral: CBPeripheral, characteristic: CBCharacteristic, peerID: String? = nil) { private func writeToPeripheral(_ data: Data, peripheral: CBPeripheral, characteristic: CBCharacteristic, peerID: String? = nil) {
let peripheralID = peripheral.identifier.uuidString let peripheralID = peripheral.identifier.uuidString
if peripheral.state == .connected { // Double check the peripheral state to avoid API misuse
// Direct write if connected guard peripheral.state == .connected else {
let writeType: CBCharacteristicWriteType = data.count > 512 ? .withResponse : .withoutResponse
peripheral.writeValue(data, for: characteristic, type: writeType)
// Update activity tracking
updatePeripheralActivity(peripheralID)
} else {
// Queue write for disconnected peripheral // Queue write for disconnected peripheral
queueWrite(data: data, peripheralID: peripheralID, peerID: peerID) queueWrite(data: data, peripheralID: peripheralID, peerID: peerID)
return
} }
// Verify characteristic is valid and writable
guard characteristic.properties.contains(.write) || characteristic.properties.contains(.writeWithoutResponse) else {
SecureLogger.log("Characteristic does not support writing for peripheral \(peripheralID)",
category: SecureLogger.session, level: .warning)
return
}
// Direct write if connected
let writeType: CBCharacteristicWriteType = data.count > 512 ? .withResponse : .withoutResponse
peripheral.writeValue(data, for: characteristic, type: writeType)
// Update activity tracking
updatePeripheralActivity(peripheralID)
} }
private func queueWrite(data: Data, peripheralID: String, peerID: String?) { private func queueWrite(data: Data, peripheralID: String, peerID: String?) {
@@ -263,10 +272,17 @@ class BluetoothMeshService: NSObject {
// Process queued writes with small delay between them // Process queued writes with small delay between them
for (index, queuedWrite) in queue.enumerated() { for (index, queuedWrite) in queue.enumerated() {
DispatchQueue.main.asyncAfter(deadline: .now() + Double(index) * 0.01) { [weak self] in DispatchQueue.main.asyncAfter(deadline: .now() + Double(index) * 0.01) { [weak self] in
guard peripheral.state == .connected else { return } guard let self = self,
peripheral.state == .connected,
characteristic.properties.contains(.write) || characteristic.properties.contains(.writeWithoutResponse) else {
return
}
let writeType: CBCharacteristicWriteType = queuedWrite.data.count > 512 ? .withResponse : .withoutResponse let writeType: CBCharacteristicWriteType = queuedWrite.data.count > 512 ? .withResponse : .withoutResponse
peripheral.writeValue(queuedWrite.data, for: characteristic, type: writeType) peripheral.writeValue(queuedWrite.data, for: characteristic, type: writeType)
// Update activity tracking
self.updatePeripheralActivity(peripheralID)
} }
} }
} }
+13 -5
View File
@@ -1953,9 +1953,11 @@ extension ChatViewModel: BitchatDelegate {
} }
} }
} else { } else {
// System message - always add // System message - check for empty content before adding
messages.append(finalMessage) if !finalMessage.content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
messages.sort { $0.timestamp < $1.timestamp } messages.append(finalMessage)
messages.sort { $0.timestamp < $1.timestamp }
}
} }
} }
@@ -2067,9 +2069,12 @@ extension ChatViewModel: BitchatDelegate {
// Resolve nickname using helper // Resolve nickname using helper
let displayName = resolveNickname(for: peerID) let displayName = resolveNickname(for: peerID)
// Ensure we have a valid display name
let finalDisplayName = displayName.isEmpty ? "peer" : displayName
let systemMessage = BitchatMessage( let systemMessage = BitchatMessage(
sender: "system", sender: "system",
content: "\(displayName) connected", content: "\(finalDisplayName) connected",
timestamp: Date(), timestamp: Date(),
isRelay: false, isRelay: false,
originalSender: nil originalSender: nil
@@ -2098,9 +2103,12 @@ extension ChatViewModel: BitchatDelegate {
// Resolve nickname using helper // Resolve nickname using helper
let displayName = resolveNickname(for: peerID) let displayName = resolveNickname(for: peerID)
// Ensure we have a valid display name
let finalDisplayName = displayName.isEmpty ? "peer" : displayName
let systemMessage = BitchatMessage( let systemMessage = BitchatMessage(
sender: "system", sender: "system",
content: "\(displayName) disconnected", content: "\(finalDisplayName) disconnected",
timestamp: Date(), timestamp: Date(),
isRelay: false, isRelay: false,
originalSender: nil originalSender: nil