mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 11:05:20 +00:00
Plumtree sync (#393)
* wip plumtree * sync works * fix logging * ttl to 0 * fix send packet to one peer * spec * wip GCS instead of bloom * remove bloom filter remainders * clean * prune old announcements * remove announcements from sync after LEAVE * sync after 1 second * pruning * track own announcement and prune messages without announcements * fix pruning * getGcsMaxFilterBytes default value 400 bytes * parameters
This commit is contained in:
@@ -153,7 +153,7 @@ class GeohashViewModel(
|
||||
isRelay = false
|
||||
)
|
||||
fun startGeohashDM(pubkeyHex: String, onStartPrivateChat: (String) -> Unit) {
|
||||
val convKey = "nostr_${'$'}{pubkeyHex.take(16)}"
|
||||
val convKey = "nostr_${pubkeyHex.take(16)}"
|
||||
repo.putNostrKeyMapping(convKey, pubkeyHex)
|
||||
// Record the conversation's geohash using the currently selected location channel (if any)
|
||||
val current = state.selectedLocationChannel.value
|
||||
@@ -163,7 +163,7 @@ class GeohashViewModel(
|
||||
com.bitchat.android.nostr.GeohashConversationRegistry.set(convKey, gh)
|
||||
}
|
||||
onStartPrivateChat(convKey)
|
||||
Log.d(TAG, "🗨️ Started geohash DM with ${'$'}pubkeyHex -> ${'$'}convKey (geohash=${'$'}gh)")
|
||||
Log.d(TAG, "🗨️ Started geohash DM with ${pubkeyHex} -> ${convKey} (geohash=${gh})")
|
||||
}
|
||||
|
||||
messageManager.addMessage(sysMsg)
|
||||
|
||||
@@ -16,6 +16,10 @@ object DebugPreferenceManager {
|
||||
private const val KEY_MAX_CONN_OVERALL = "max_connections_overall"
|
||||
private const val KEY_MAX_CONN_SERVER = "max_connections_server"
|
||||
private const val KEY_MAX_CONN_CLIENT = "max_connections_client"
|
||||
private const val KEY_SEEN_PACKET_CAP = "seen_packet_capacity"
|
||||
// GCS keys (no migration/back-compat)
|
||||
private const val KEY_GCS_MAX_BYTES = "gcs_max_filter_bytes"
|
||||
private const val KEY_GCS_FPR = "gcs_filter_fpr_percent"
|
||||
|
||||
private lateinit var prefs: SharedPreferences
|
||||
|
||||
@@ -74,4 +78,26 @@ object DebugPreferenceManager {
|
||||
fun setMaxConnectionsClient(value: Int) {
|
||||
if (ready()) prefs.edit().putInt(KEY_MAX_CONN_CLIENT, value).apply()
|
||||
}
|
||||
|
||||
// Sync/GCS settings
|
||||
fun getSeenPacketCapacity(default: Int = 500): Int =
|
||||
if (ready()) prefs.getInt(KEY_SEEN_PACKET_CAP, default) else default
|
||||
|
||||
fun setSeenPacketCapacity(value: Int) {
|
||||
if (ready()) prefs.edit().putInt(KEY_SEEN_PACKET_CAP, value).apply()
|
||||
}
|
||||
|
||||
fun getGcsMaxFilterBytes(default: Int = 400): Int =
|
||||
if (ready()) prefs.getInt(KEY_GCS_MAX_BYTES, default) else default
|
||||
|
||||
fun setGcsMaxFilterBytes(value: Int) {
|
||||
if (ready()) prefs.edit().putInt(KEY_GCS_MAX_BYTES, value).apply()
|
||||
}
|
||||
|
||||
fun getGcsFprPercent(default: Double = 1.0): Double =
|
||||
if (ready()) java.lang.Double.longBitsToDouble(prefs.getLong(KEY_GCS_FPR, java.lang.Double.doubleToRawLongBits(default))) else default
|
||||
|
||||
fun setGcsFprPercent(value: Double) {
|
||||
if (ready()) prefs.edit().putLong(KEY_GCS_FPR, java.lang.Double.doubleToRawLongBits(value)).apply()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,6 +201,37 @@ class DebugSettingsManager private constructor() {
|
||||
fun updateRelayStats(stats: PacketRelayStats) {
|
||||
_relayStats.value = stats
|
||||
}
|
||||
|
||||
// Sync/GCS settings (UI-configurable)
|
||||
private val _seenPacketCapacity = MutableStateFlow(DebugPreferenceManager.getSeenPacketCapacity(500))
|
||||
val seenPacketCapacity: StateFlow<Int> = _seenPacketCapacity.asStateFlow()
|
||||
|
||||
private val _gcsMaxBytes = MutableStateFlow(DebugPreferenceManager.getGcsMaxFilterBytes(400))
|
||||
val gcsMaxBytes: StateFlow<Int> = _gcsMaxBytes.asStateFlow()
|
||||
|
||||
private val _gcsFprPercent = MutableStateFlow(DebugPreferenceManager.getGcsFprPercent(1.0))
|
||||
val gcsFprPercent: StateFlow<Double> = _gcsFprPercent.asStateFlow()
|
||||
|
||||
fun setSeenPacketCapacity(value: Int) {
|
||||
val clamped = value.coerceIn(10, 1000)
|
||||
DebugPreferenceManager.setSeenPacketCapacity(clamped)
|
||||
_seenPacketCapacity.value = clamped
|
||||
addDebugMessage(DebugMessage.SystemMessage("🧩 max packets per sync set to $clamped"))
|
||||
}
|
||||
|
||||
fun setGcsMaxBytes(value: Int) {
|
||||
val clamped = value.coerceIn(128, 1024)
|
||||
DebugPreferenceManager.setGcsMaxFilterBytes(clamped)
|
||||
_gcsMaxBytes.value = clamped
|
||||
addDebugMessage(DebugMessage.SystemMessage("🌸 max GCS filter size set to $clamped bytes"))
|
||||
}
|
||||
|
||||
fun setGcsFprPercent(value: Double) {
|
||||
val clamped = value.coerceIn(0.1, 5.0)
|
||||
DebugPreferenceManager.setGcsFprPercent(clamped)
|
||||
_gcsFprPercent.value = clamped
|
||||
addDebugMessage(DebugMessage.SystemMessage("🎯 GCS FPR set to ${String.format("%.2f", clamped)}%"))
|
||||
}
|
||||
|
||||
// MARK: - Debug Message Creation Helpers
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ fun DebugSettingsSheet(
|
||||
val scanResults by manager.scanResults.collectAsState()
|
||||
val connectedDevices by manager.connectedDevices.collectAsState()
|
||||
val relayStats by manager.relayStats.collectAsState()
|
||||
val seenCapacity by manager.seenPacketCapacity.collectAsState()
|
||||
val gcsMaxBytes by manager.gcsMaxBytes.collectAsState()
|
||||
val gcsFpr by manager.gcsFprPercent.collectAsState()
|
||||
|
||||
// Push live connected devices from mesh service whenever sheet is visible
|
||||
LaunchedEffect(isPresented) {
|
||||
@@ -284,6 +287,27 @@ fun DebugSettingsSheet(
|
||||
}
|
||||
}
|
||||
|
||||
// Connected devices
|
||||
item {
|
||||
Surface(shape = RoundedCornerShape(12.dp), color = colorScheme.surfaceVariant.copy(alpha = 0.2f)) {
|
||||
Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
Icon(Icons.Filled.SettingsEthernet, contentDescription = null, tint = Color(0xFF9C27B0))
|
||||
Text("sync settings", fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
|
||||
}
|
||||
Text("max packets per sync: $seenCapacity", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
|
||||
Slider(value = seenCapacity.toFloat(), onValueChange = { manager.setSeenPacketCapacity(it.toInt()) }, valueRange = 10f..1000f, steps = 99)
|
||||
Text("max GCS filter size: $gcsMaxBytes bytes (128–1024)", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
|
||||
Slider(value = gcsMaxBytes.toFloat(), onValueChange = { manager.setGcsMaxBytes(it.toInt()) }, valueRange = 128f..1024f, steps = 0)
|
||||
Text("target FPR: ${String.format("%.2f", gcsFpr)}%", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
|
||||
Slider(value = gcsFpr.toFloat(), onValueChange = { manager.setGcsFprPercent(it.toDouble()) }, valueRange = 0.1f..5.0f, steps = 49)
|
||||
val p = remember(gcsFpr) { com.bitchat.android.sync.GCSFilter.deriveP(gcsFpr / 100.0) }
|
||||
val nmax = remember(gcsFpr, gcsMaxBytes) { com.bitchat.android.sync.GCSFilter.estimateMaxElementsForSize(gcsMaxBytes, p) }
|
||||
Text("derived P: $p • est. max elements: $nmax", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Connected devices
|
||||
item {
|
||||
Surface(shape = RoundedCornerShape(12.dp), color = colorScheme.surfaceVariant.copy(alpha = 0.2f)) {
|
||||
|
||||
Reference in New Issue
Block a user