diff --git a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt index 74ab15c6..57722b11 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt @@ -404,8 +404,9 @@ class ChatViewModel( state.getNicknameValue() ) } else { - // Default: route via mesh + // Default: route via mesh + Wi‑Fi Aware meshService.sendMessage(messageContent, mentions, channel) + try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.sendMessage(messageContent, mentions, channel) } catch (_: Exception) {} } }) return @@ -475,19 +476,23 @@ class ChatViewModel( state.getNicknameValue(), meshService.myPeerID, onEncryptedPayload = { encryptedData -> - // This would need proper mesh service integration + // Send encrypted payload announcement over both transports for reachability meshService.sendMessage(content, mentions, currentChannelValue) + try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.sendMessage(content, mentions, currentChannelValue) } catch (_: Exception) {} }, onFallback = { meshService.sendMessage(content, mentions, currentChannelValue) + try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.sendMessage(content, mentions, currentChannelValue) } catch (_: Exception) {} } ) } else { meshService.sendMessage(content, mentions, currentChannelValue) + try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.sendMessage(content, mentions, currentChannelValue) } catch (_: Exception) {} } } else { messageManager.addMessage(message) meshService.sendMessage(content, mentions, null) + try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.sendMessage(content, mentions, null) } catch (_: Exception) {} } } } @@ -610,16 +615,23 @@ class ChatViewModel( val fingerprints = privateChatManager.getAllPeerFingerprints() state.setPeerFingerprints(fingerprints) - val nicknames = meshService.getPeerNicknames() - state.setPeerNicknames(nicknames) + // Merge nicknames from BLE and Wi‑Fi Aware to display names for all peers + val bleNick = meshService.getPeerNicknames() + val awareNick = try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.getPeerNicknames() } catch (_: Exception) { null } + val mergedNick = if (awareNick != null) bleNick + awareNick.filterKeys { it !in bleNick || bleNick[it].isNullOrBlank() } else bleNick + state.setPeerNicknames(mergedNick) val rssiValues = meshService.getPeerRSSI() - state.setPeerRSSI(rssiValues) + val awareRssi = try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.getPeerRSSI() } catch (_: Exception) { null } + val mergedRssi = if (awareRssi != null) rssiValues + awareRssi.filterKeys { it !in rssiValues } else rssiValues + state.setPeerRSSI(mergedRssi) // Update directness per peer (driven by PeerManager state) try { val directMap = state.getConnectedPeersValue().associateWith { pid -> - meshService.getPeerInfo(pid)?.isDirectConnection == true + val ble = meshService.getPeerInfo(pid)?.isDirectConnection == true + val aware = try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.getPeerInfo(pid)?.isDirectConnection == true } catch (_: Exception) { false } + ble || aware } state.setPeerDirect(directMap) } catch (_: Exception) { } diff --git a/app/src/main/java/com/bitchat/android/ui/MeshDelegateHandler.kt b/app/src/main/java/com/bitchat/android/ui/MeshDelegateHandler.kt index d6a9e746..f64a8cc2 100644 --- a/app/src/main/java/com/bitchat/android/ui/MeshDelegateHandler.kt +++ b/app/src/main/java/com/bitchat/android/ui/MeshDelegateHandler.kt @@ -85,7 +85,10 @@ class MeshDelegateHandler( override fun didUpdatePeerList(peers: List) { coroutineScope.launch { - state.setConnectedPeers(peers) + // Merge peers from multiple transports to avoid flapping + val current = state.getConnectedPeersValue().toMutableSet() + current.addAll(peers) + state.setConnectedPeers(current.toList()) state.setIsConnected(peers.isNotEmpty()) notificationManager.showActiveUserNotification(peers) // Flush router outbox for any peers that just connected (and their noiseHex aliases) diff --git a/app/src/main/java/com/bitchat/android/wifi-aware/WifiAwareMeshServiceLatest.kt b/app/src/main/java/com/bitchat/android/wifi-aware/WifiAwareMeshServiceLatest.kt index 7c3a728e..87c1d616 100644 --- a/app/src/main/java/com/bitchat/android/wifi-aware/WifiAwareMeshServiceLatest.kt +++ b/app/src/main/java/com/bitchat/android/wifi-aware/WifiAwareMeshServiceLatest.kt @@ -156,16 +156,26 @@ class WifiAwareMeshService(private val context: Context) { * Broadcasts raw bytes to currently connected peer. */ private fun broadcastRaw(bytes: ByteArray) { - peerSockets.values.forEach { sock -> - try { sock.getOutputStream().write(bytes) } catch (_: IOException) {} + var sent = 0 + peerSockets.forEach { (pid, sock) -> + try { + sock.getOutputStream().write(bytes) + sent++ + } catch (e: IOException) { + Log.e(TAG, "TX: write failed to ${pid.take(8)}…: ${e.message}") + } } + Log.i(TAG, "TX: broadcast via Wi‑Fi Aware to $sent peers (bytes=${bytes.size})") } /** * Broadcasts routed packet to currently connected peers. */ private fun broadcastPacket(routed: RoutedPacket) { - routed.packet.toBinaryData()?.let { broadcastRaw(it) } + routed.packet.toBinaryData()?.let { + Log.d(TAG, "TX: packet type=${routed.packet.type} broadcast (ttl=${routed.packet.ttl})") + broadcastRaw(it) + } } /** @@ -173,7 +183,13 @@ class WifiAwareMeshService(private val context: Context) { */ private fun sendPacketToPeer(peerID: String, packet: BitchatPacket) { val sock = peerSockets[peerID] ?: return - try { sock.getOutputStream().write(packet.toBinaryData() ?: return) } catch (_: IOException) {} + try { + val data = packet.toBinaryData() ?: return + sock.getOutputStream().write(data) + Log.d(TAG, "TX: packet type=${packet.type} → ${peerID.take(8)}… (bytes=${data.size})") + } catch (e: IOException) { + Log.e(TAG, "TX: write to ${peerID.take(8)}… failed: ${e.message}") + } } /** @@ -577,6 +593,7 @@ class WifiAwareMeshService(private val context: Context) { // Kick off Noise handshake for this logical peer if (myPeerID < peerId) { messageHandler.delegate?.initiateNoiseHandshake(peerId) + Log.d(TAG, "SERVER: initiating Noise handshake to ${peerId.take(8)}…") } } catch (ioe: IOException) { Log.e(TAG, "SERVER: accept failed for ${peerId.take(8)}…", ioe) @@ -690,8 +707,9 @@ class WifiAwareMeshService(private val context: Context) { listenerExec.execute { listenToPeer(sock, peerId) } handleServerKeepAlive(sock, peerId, peerHandle) // Kick off Noise handshake for this logical peer - if (myPeerID < peerId) { + if (myPeerID > peerId) { messageHandler.delegate?.initiateNoiseHandshake(peerId) + Log.d(TAG, "CLIENT: initiating Noise handshake to ${peerId.take(8)}…") } } catch (ioe: IOException) { Log.e(TAG, "CLIENT: socket connect failed to ${peerId.take(8)}…", ioe) @@ -771,6 +789,7 @@ class WifiAwareMeshService(private val context: Context) { peerSockets[routedPeerId] = socket } + Log.d(TAG, "RX: packet type=${pkt.type} from ${senderPeerHex.take(8)}… (bytes=${raw.size})") packetProcessor.processPacket(RoutedPacket(pkt, routedPeerId)) }