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:
callebtc
2025-09-05 15:40:39 +02:00
committed by GitHub
parent 91f3f270d4
commit f47819a31e
19 changed files with 1318 additions and 79 deletions
@@ -1,4 +1,5 @@
package com.bitchat.android.mesh
import com.bitchat.android.protocol.MessageType
import android.util.Log
import com.bitchat.android.model.RoutedPacket
@@ -14,11 +15,18 @@ import kotlin.random.Random
* All packets that aren't specifically addressed to us get processed here.
*/
class PacketRelayManager(private val myPeerID: String) {
private val debugManager by lazy { try { com.bitchat.android.ui.debug.DebugSettingsManager.getInstance() } catch (e: Exception) { null } }
companion object {
private const val TAG = "PacketRelayManager"
}
private fun isRelayEnabled(): Boolean = try {
com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().packetRelayEnabled.value
} catch (_: Exception) { true }
// Logging moved to BluetoothPacketBroadcaster per actual transmission target
// Delegate for callbacks
var delegate: PacketRelayManagerDelegate? = null
@@ -33,7 +41,7 @@ class PacketRelayManager(private val myPeerID: String) {
val packet = routed.packet
val peerID = routed.peerID ?: "unknown"
Log.d(TAG, "Evaluating relay for packet type ${packet.type} from $peerID (TTL: ${packet.ttl})")
Log.d(TAG, "Evaluating relay for packet type ${'$'}{packet.type} from ${'$'}peerID (TTL: ${'$'}{packet.ttl})")
// Double-check this packet isn't addressed to us
if (isPacketAddressedToMe(packet)) {
@@ -55,15 +63,15 @@ class PacketRelayManager(private val myPeerID: String) {
// Decrement TTL by 1
val relayPacket = packet.copy(ttl = (packet.ttl - 1u).toUByte())
Log.d(TAG, "Decremented TTL from ${packet.ttl} to ${relayPacket.ttl}")
Log.d(TAG, "Decremented TTL from ${'$'}{packet.ttl} to ${'$'}{relayPacket.ttl}")
// Apply relay logic based on packet type
val shouldRelay = shouldRelayPacket(relayPacket, peerID)
// Apply relay logic based on packet type and debug switch
val shouldRelay = isRelayEnabled() && shouldRelayPacket(relayPacket, peerID)
if (shouldRelay) {
relayPacket(RoutedPacket(relayPacket, peerID, routed.relayAddress))
} else {
Log.d(TAG, "Relay decision: NOT relaying packet type ${packet.type}")
Log.d(TAG, "Relay decision: NOT relaying packet type ${'$'}{packet.type}")
}
}
@@ -95,7 +103,7 @@ class PacketRelayManager(private val myPeerID: String) {
private fun shouldRelayPacket(packet: BitchatPacket, fromPeerID: String): Boolean {
// Always relay if TTL is high enough (indicates important message)
if (packet.ttl >= 4u) {
Log.d(TAG, "High TTL (${packet.ttl}), relaying")
Log.d(TAG, "High TTL (${ '$' }{packet.ttl}), relaying")
return true
}
@@ -104,7 +112,7 @@ class PacketRelayManager(private val myPeerID: String) {
// Small networks always relay to ensure connectivity
if (networkSize <= 3) {
Log.d(TAG, "Small network ($networkSize peers), relaying")
Log.d(TAG, "Small network (${ '$' }networkSize peers), relaying")
return true
}
@@ -118,7 +126,7 @@ class PacketRelayManager(private val myPeerID: String) {
}
val shouldRelay = Random.nextDouble() < relayProb
Log.d(TAG, "Network size: $networkSize, Relay probability: $relayProb, Decision: $shouldRelay")
Log.d(TAG, "Network size: ${'$'}networkSize, Relay probability: ${'$'}relayProb, Decision: ${'$'}shouldRelay")
return shouldRelay
}
@@ -151,11 +159,11 @@ class PacketRelayManager(private val myPeerID: String) {
if (shouldRelay) {
val delay = Random.nextLong(50, 500) // Random delay like iOS
Log.d(TAG, "Relaying message after ${delay}ms delay")
Log.d(TAG, "Relaying message after ${'$'}delay ms delay")
delay(delay)
relayPacket(routed.copy(packet = relayPacket))
} else {
Log.d(TAG, "Relay decision: NOT relaying message (network size: $networkSize, prob: $relayProb)")
Log.d(TAG, "Relay decision: NOT relaying message (network size: ${'$'}networkSize, prob: ${'$'}relayProb)")
}
}
@@ -163,7 +171,7 @@ class PacketRelayManager(private val myPeerID: String) {
* Actually broadcast the packet for relay
*/
private fun relayPacket(routed: RoutedPacket) {
Log.d(TAG, "🔄 Relaying packet type ${routed.packet.type} with TTL ${routed.packet.ttl}")
Log.d(TAG, "🔄 Relaying packet type ${'$'}{routed.packet.type} with TTL ${'$'}{routed.packet.ttl}")
delegate?.broadcastPacket(routed)
}
@@ -173,9 +181,9 @@ class PacketRelayManager(private val myPeerID: String) {
fun getDebugInfo(): String {
return buildString {
appendLine("=== Packet Relay Manager Debug Info ===")
appendLine("Relay Scope Active: ${relayScope.isActive}")
appendLine("My Peer ID: $myPeerID")
appendLine("Network Size: ${delegate?.getNetworkSize() ?: "unknown"}")
appendLine("Relay Scope Active: ${'$'}{relayScope.isActive}")
appendLine("My Peer ID: ${'$'}myPeerID")
appendLine("Network Size: ${'$'}{delegate?.getNetworkSize() ?: \"unknown\"}")
}
}