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
@@ -14,6 +14,8 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.*
import kotlinx.coroutines.Job
import com.bitchat.android.ui.debug.DebugSettingsManager
import com.bitchat.android.ui.debug.DebugScanResult
/**
* Manages GATT client operations, scanning, and client-side connections
@@ -44,6 +46,21 @@ class BluetoothGattClientManager(
private val bluetoothAdapter: BluetoothAdapter? = bluetoothManager.adapter
private val bleScanner: BluetoothLeScanner? = bluetoothAdapter?.bluetoothLeScanner
/**
* Public: Connect to a device by MAC address (for debug UI)
*/
fun connectToAddress(deviceAddress: String): Boolean {
val device = bluetoothAdapter?.getRemoteDevice(deviceAddress)
return if (device != null) {
val rssi = connectionTracker.getBestRSSI(deviceAddress) ?: -50
connectToDevice(device, rssi)
true
} else {
Log.w(TAG, "connectToAddress: No device for $deviceAddress")
false
}
}
// Scan management
private var scanCallback: ScanCallback? = null
@@ -63,6 +80,18 @@ class BluetoothGattClientManager(
* Start client manager
*/
fun start(): Boolean {
// Respect debug setting
try {
if (!com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().gattClientEnabled.value) {
Log.i(TAG, "Client start skipped: GATT Client disabled in debug settings")
return false
}
} catch (_: Exception) { }
if (isActive) {
Log.d(TAG, "GATT client already active; start is a no-op")
return true
}
if (!permissionManager.hasBluetoothPermissions()) {
Log.e(TAG, "Missing Bluetooth permissions")
return false
@@ -98,9 +127,25 @@ class BluetoothGattClientManager(
* Stop client manager
*/
fun stop() {
if (!isActive) {
// Idempotent stop
stopScanning()
stopRSSIMonitoring()
Log.i(TAG, "GATT client manager stopped (already inactive)")
return
}
isActive = false
connectionScope.launch {
// Disconnect all client connections decisively
try {
val conns = connectionTracker.getConnectedDevices().values.filter { it.isClient && it.gatt != null }
conns.forEach { dc ->
try { dc.gatt?.disconnect() } catch (_: Exception) { }
}
} catch (_: Exception) { }
stopScanning()
stopRSSIMonitoring()
Log.i(TAG, "GATT client manager stopped")
@@ -111,7 +156,8 @@ class BluetoothGattClientManager(
* Handle scan state changes from power manager
*/
fun onScanStateChanged(shouldScan: Boolean) {
if (shouldScan) {
val enabled = try { com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().gattClientEnabled.value } catch (_: Exception) { true }
if (shouldScan && enabled) {
startScanning()
} else {
stopScanning()
@@ -158,7 +204,9 @@ class BluetoothGattClientManager(
*/
@Suppress("DEPRECATION")
private fun startScanning() {
if (!permissionManager.hasBluetoothPermissions() || bleScanner == null || !isActive) return
// Respect debug setting
val enabled = try { com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().gattClientEnabled.value } catch (_: Exception) { true }
if (!permissionManager.hasBluetoothPermissions() || bleScanner == null || !isActive || !enabled) return
// Rate limit scan starts to prevent "scanning too frequently" errors
val currentTime = System.currentTimeMillis()
@@ -282,10 +330,34 @@ class BluetoothGattClientManager(
// Store RSSI from scan results for later use (especially for server connections)
connectionTracker.updateScanRSSI(deviceAddress, rssi)
// Publish scan result to debug UI buffer
try {
DebugSettingsManager.getInstance().addScanResult(
DebugScanResult(
deviceName = device.name,
deviceAddress = deviceAddress,
rssi = rssi,
peerID = null // peerID unknown at scan time
)
)
} catch (_: Exception) { }
// Power-aware RSSI filtering
if (rssi < powerManager.getRSSIThreshold()) {
Log.d(TAG, "Skipping device $deviceAddress due to weak signal: $rssi < ${powerManager.getRSSIThreshold()}")
// Even if we skip connecting, still publish scan result to debug UI
try {
val pid: String? = null // We don't know peerID until packet exchange
DebugSettingsManager.getInstance().addScanResult(
DebugScanResult(
deviceName = device.name,
deviceAddress = deviceAddress,
rssi = rssi,
peerID = pid
)
)
} catch (_: Exception) { }
return
}
@@ -474,7 +546,9 @@ class BluetoothGattClientManager(
* Restart scanning for power mode changes
*/
fun restartScanning() {
if (!isActive) return
// Respect debug setting
val enabled = try { com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().gattClientEnabled.value } catch (_: Exception) { true }
if (!isActive || !enabled) return
connectionScope.launch {
stopScanning()
@@ -489,4 +563,4 @@ class BluetoothGattClientManager(
}
}
}
}
}