mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 05:05:20 +00:00
Debug button (#377)
* feat(debug): add DebugSettingsManager + DebugSettingsSheet scaffold and AboutSheet entry; groundwork for verbose logging, GATT controls, relay stats, device/scan views * fix(debug): wire debug sheet launch via onShowDebug in AboutSheet from ChatScreen; add public start/stop server/client methods} * fix(about): remove misplaced debug item block inside PoW section; keep debug launcher managed by ChatScreen only * feat(debug): wire DebugSettingsSheet role switches to explicit startServer/stopServer and startClient/stopClient; expose role controls + disconnectAll on BluetoothConnectionManager; fix syntax error; build passes * feat(debug): add connect/disconnect helpers; wire DebugSettingsSheet connect/disconnect actions to BluetoothConnectionManager * feat(debug): add debug settings button at bottom of AboutSheet; wire onShowDebug callback to open DebugSettingsSheet from ChatScreen * feat(debug): wire verbose logging into chat view via DebugSettingsManager; add rolling relay stats; push connected devices and scan results; ensure GATT role stop closes connections; log incoming packets and relay events; add UI polling for devices; build passes * chore(debug-branch): remove unrelated files that were mistakenly added in first commit; keep only intended debug settings changes * fix(chat): prevent mesh→geohash leak Root cause: - DebugSettingsManager→chat bridge appended system logs to the global timeline regardless of active channel - MeshDelegateHandler added public mesh messages to UI unconditionally Fixes: - Only inject debug system messages when selected location channel is Mesh - Only add public mesh messages to UI when Mesh is selected (still send notifications) Build: ./gradlew assembleDebug } * fix(timeline): restore message persistence across channel switches Root cause: - NostrGeohashService.switchLocationChannel() called messageManager.clearMessages() which wiped ALL messages (mesh + debug + geohash) from main timeline - Geohash events were adding to main timeline, causing cross-contamination Fixes: - Remove messageManager.clearMessages() from channel switching - ChatScreen displayMessages now routes to separate storage: - Mesh: messages (main timeline, includes debug logs when Mesh selected) - Geohash: viewModel.getGeohashMessages(geohash) from separate history - Private: privateChats[peerID] - Channels: channelMessages[channel] - Geohash events no longer add to main timeline, only to geohash history - Mesh messages always stored to preserve history when switching away Result: Each chat type has persistent separate storage, no message loss * Debug/relay logs: use MessageType names; include device route in verbose packet logs. * Verbose device-peer assignment and connection/disconnection logs with peerId, deviceId, nickname; packet relay log uses MessageType names.} * Debug logs API: include nickname and deviceId for incoming/relay; update callers.} * Fix compile: import MessageType; correct debug manager API usage and remove stray insertion; build.} * Respect relay toggle; helper to log relay with deviceId.} * PacketRelayManager: add relay toggle and unified logging helper; clean file header comments; build fixes.} * changes * Geohash local echo: do not add to mesh timeline; rely on geohash history and ChatScreen display for location channels. * persisting * persist debug settings * gitignore * gatt server / client controls * debugger * max connection settings and graph * more graph * better logging * refactor logging
This commit is contained in:
@@ -7,6 +7,8 @@ import android.bluetooth.BluetoothGattServer
|
||||
import android.util.Log
|
||||
import com.bitchat.android.protocol.SpecialRecipients
|
||||
import com.bitchat.android.model.RoutedPacket
|
||||
import com.bitchat.android.protocol.MessageType
|
||||
import com.bitchat.android.util.toHexString
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
@@ -44,6 +46,47 @@ class BluetoothPacketBroadcaster(
|
||||
private const val TAG = "BluetoothPacketBroadcaster"
|
||||
private const val CLEANUP_DELAY = 500L
|
||||
}
|
||||
|
||||
// Optional nickname resolver injected by higher layer (peerID -> nickname?)
|
||||
private var nicknameResolver: ((String) -> String?)? = null
|
||||
|
||||
fun setNicknameResolver(resolver: (String) -> String?) {
|
||||
nicknameResolver = resolver
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug logging helper - can be easily removed/disabled for production
|
||||
*/
|
||||
private fun logPacketRelay(
|
||||
typeName: String,
|
||||
senderPeerID: String,
|
||||
senderNick: String?,
|
||||
incomingPeer: String?,
|
||||
incomingAddr: String?,
|
||||
toPeer: String?,
|
||||
toDeviceAddress: String,
|
||||
ttl: UByte
|
||||
) {
|
||||
try {
|
||||
val fromNick = incomingPeer?.let { nicknameResolver?.invoke(it) }
|
||||
val toNick = toPeer?.let { nicknameResolver?.invoke(it) }
|
||||
|
||||
com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().logPacketRelayDetailed(
|
||||
packetType = typeName,
|
||||
senderPeerID = senderPeerID,
|
||||
senderNickname = senderNick,
|
||||
fromPeerID = incomingPeer,
|
||||
fromNickname = fromNick,
|
||||
fromDeviceAddress = incomingAddr,
|
||||
toPeerID = toPeer,
|
||||
toNickname = toNick,
|
||||
toDeviceAddress = toDeviceAddress,
|
||||
ttl = ttl
|
||||
)
|
||||
} catch (_: Exception) {
|
||||
// Silently ignore debug logging failures
|
||||
}
|
||||
}
|
||||
|
||||
// Data class to hold broadcast request information
|
||||
private data class BroadcastRequest(
|
||||
@@ -127,6 +170,11 @@ class BluetoothPacketBroadcaster(
|
||||
) {
|
||||
val packet = routed.packet
|
||||
val data = packet.toBinaryData() ?: return
|
||||
val typeName = MessageType.fromValue(packet.type)?.name ?: packet.type.toString()
|
||||
val senderPeerID = routed.peerID ?: packet.senderID.toHexString()
|
||||
val incomingAddr = routed.relayAddress
|
||||
val incomingPeer = incomingAddr?.let { connectionTracker.addressPeerMap[it] }
|
||||
val senderNick = senderPeerID.let { pid -> nicknameResolver?.invoke(pid) }
|
||||
|
||||
if (packet.recipientID != SpecialRecipients.BROADCAST) {
|
||||
val recipientID = packet.recipientID?.let {
|
||||
@@ -140,8 +188,11 @@ class BluetoothPacketBroadcaster(
|
||||
// If found, send directly
|
||||
if (targetDevice != null) {
|
||||
Log.d(TAG, "Send packet type ${packet.type} directly to target device for recipient $recipientID: ${targetDevice.address}")
|
||||
if (notifyDevice(targetDevice, data, gattServer, characteristic))
|
||||
if (notifyDevice(targetDevice, data, gattServer, characteristic)) {
|
||||
val toPeer = connectionTracker.addressPeerMap[targetDevice.address]
|
||||
logPacketRelay(typeName, senderPeerID, senderNick, incomingPeer, incomingAddr, toPeer, targetDevice.address, packet.ttl)
|
||||
return // Sent, no need to continue
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find the recipient in client connections (connectedDevices)
|
||||
@@ -151,8 +202,11 @@ class BluetoothPacketBroadcaster(
|
||||
// If found, send directly
|
||||
if (targetDeviceConn != null) {
|
||||
Log.d(TAG, "Send packet type ${packet.type} directly to target client connection for recipient $recipientID: ${targetDeviceConn.device.address}")
|
||||
if (writeToDeviceConn(targetDeviceConn, data))
|
||||
if (writeToDeviceConn(targetDeviceConn, data)) {
|
||||
val toPeer = connectionTracker.addressPeerMap[targetDeviceConn.device.address]
|
||||
logPacketRelay(typeName, senderPeerID, senderNick, incomingPeer, incomingAddr, toPeer, targetDeviceConn.device.address, packet.ttl)
|
||||
return // Sent, no need to continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +228,11 @@ class BluetoothPacketBroadcaster(
|
||||
Log.d(TAG, "Skipping broadcast to client back to sender: ${device.address}")
|
||||
return@forEach
|
||||
}
|
||||
notifyDevice(device, data, gattServer, characteristic)
|
||||
val sent = notifyDevice(device, data, gattServer, characteristic)
|
||||
if (sent) {
|
||||
val toPeer = connectionTracker.addressPeerMap[device.address]
|
||||
logPacketRelay(typeName, senderPeerID, senderNick, incomingPeer, incomingAddr, toPeer, device.address, packet.ttl)
|
||||
}
|
||||
}
|
||||
|
||||
// Send to client connections (GATT servers we are connected to)
|
||||
@@ -188,7 +246,11 @@ class BluetoothPacketBroadcaster(
|
||||
Log.d(TAG, "Skipping roadcast to server back to sender: ${deviceConn.device.address}")
|
||||
return@forEach
|
||||
}
|
||||
writeToDeviceConn(deviceConn, data)
|
||||
val sent = writeToDeviceConn(deviceConn, data)
|
||||
if (sent) {
|
||||
val toPeer = connectionTracker.addressPeerMap[deviceConn.device.address]
|
||||
logPacketRelay(typeName, senderPeerID, senderNick, incomingPeer, incomingAddr, toPeer, deviceConn.device.address, packet.ttl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -268,4 +330,4 @@ class BluetoothPacketBroadcaster(
|
||||
|
||||
Log.d(TAG, "BluetoothPacketBroadcaster shutdown complete")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user