mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-24 22:45:20 +00:00
* Pause Nostr geohash firehose in background to cut mobile data The Bluetooth mesh uses no mobile data, but the Nostr relay layer ran unbounded in the background: the live geohash channel subscription kept streaming across 5 relays, the presence heartbeat broadcast every ~60s, and a participant-refresh timer polled every 30s. Combined with reconnect/re-subscribe replay on public relays, this could burn gigabytes while idle. GeohashViewModel now tears down the high-volume subscriptions when the app is backgrounded (onStop) and restores them on foreground (onStart): - drop the live channel message stream (currentGeohashSubId) - drop sampling subscriptions - cancel the presence heartbeat and participant-refresh timer Gift-wrap DM subscriptions are intentionally kept alive in the background since they are filtered to our pubkey (lightweight) so DMs still arrive. The selected channel is tracked in activeChannelGeohash so the stream can be rebuilt on foreground without losing the user's selection. The channel subscription logic is extracted into subscribeChannelStream() / subscribeChannelDM() helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * separate the heartbeat firehose from message delivery * correct comment --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
48 lines
2.1 KiB
Kotlin
48 lines
2.1 KiB
Kotlin
package com.bitchat.android.nostr
|
|
|
|
import android.app.Application
|
|
import android.util.Log
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.launch
|
|
|
|
/**
|
|
* NostrSubscriptionManager
|
|
* - Encapsulates subscription lifecycle with NostrRelayManager
|
|
*/
|
|
class NostrSubscriptionManager(
|
|
private val application: Application,
|
|
private val scope: CoroutineScope
|
|
) {
|
|
companion object { private const val TAG = "NostrSubscriptionManager" }
|
|
|
|
private val relayManager get() = NostrRelayManager.getInstance(application)
|
|
|
|
fun connect() = scope.launch { runCatching { relayManager.connect() }.onFailure { Log.e(TAG, "connect failed: ${it.message}") } }
|
|
fun disconnect() = scope.launch { runCatching { relayManager.disconnect() }.onFailure { Log.e(TAG, "disconnect failed: ${it.message}") } }
|
|
|
|
fun subscribeGiftWraps(pubkey: String, sinceMs: Long, id: String, handler: (NostrEvent) -> Unit) {
|
|
scope.launch {
|
|
val filter = NostrFilter.giftWrapsFor(pubkey, sinceMs)
|
|
relayManager.subscribe(filter, id, handler)
|
|
}
|
|
}
|
|
|
|
/** Subscribe to geohash chat messages only (kind 20000) — low-volume, kept alive in background. */
|
|
fun subscribeGeohashMessages(geohash: String, sinceMs: Long, limit: Int, id: String, handler: (NostrEvent) -> Unit) {
|
|
scope.launch {
|
|
val filter = NostrFilter.geohashMessages(geohash, sinceMs, limit)
|
|
relayManager.subscribeForGeohash(geohash, filter, id, handler, includeDefaults = false, nRelays = 5)
|
|
}
|
|
}
|
|
|
|
/** Subscribe to geohash presence heartbeats only (kind 20001) — high-volume, paused in background. */
|
|
fun subscribeGeohashPresence(geohash: String, sinceMs: Long, limit: Int, id: String, handler: (NostrEvent) -> Unit) {
|
|
scope.launch {
|
|
val filter = NostrFilter.geohashPresence(geohash, sinceMs, limit)
|
|
relayManager.subscribeForGeohash(geohash, filter, id, handler, includeDefaults = false, nRelays = 5)
|
|
}
|
|
}
|
|
|
|
fun unsubscribe(id: String) { scope.launch { runCatching { relayManager.unsubscribe(id) } } }
|
|
}
|