chore: optimize the battery usage #16
@@ -38,6 +38,7 @@ import rust.nostr.sdk.PublicKey
|
|||||||
import rust.nostr.sdk.RelayCapabilities
|
import rust.nostr.sdk.RelayCapabilities
|
||||||
import rust.nostr.sdk.RelayMessageEnum
|
import rust.nostr.sdk.RelayMessageEnum
|
||||||
import rust.nostr.sdk.RelayMetadata
|
import rust.nostr.sdk.RelayMetadata
|
||||||
|
import rust.nostr.sdk.RelayStatus
|
||||||
import rust.nostr.sdk.RelayUrl
|
import rust.nostr.sdk.RelayUrl
|
||||||
import rust.nostr.sdk.ReqExitPolicy
|
import rust.nostr.sdk.ReqExitPolicy
|
||||||
import rust.nostr.sdk.ReqTarget
|
import rust.nostr.sdk.ReqTarget
|
||||||
@@ -59,6 +60,18 @@ import kotlin.time.Duration.Companion.milliseconds
|
|||||||
|
|
||||||
object NostrManager {
|
object NostrManager {
|
||||||
val instance = Nostr()
|
val instance = Nostr()
|
||||||
|
|
||||||
|
val BOOTSTRAP_RELAYS = listOf(
|
||||||
|
"wss://relay.primal.net",
|
||||||
|
"wss://user.kindpag.es",
|
||||||
|
"wss://purplepag.es"
|
||||||
|
)
|
||||||
|
|
||||||
|
val INDEXER_RELAY = listOf(
|
||||||
|
"wss://indexer.coracle.social",
|
||||||
|
)
|
||||||
|
|
||||||
|
val ALL_RELAYS = BOOTSTRAP_RELAYS + INDEXER_RELAY
|
||||||
}
|
}
|
||||||
|
|
||||||
class Nostr {
|
class Nostr {
|
||||||
@@ -75,7 +88,6 @@ class Nostr {
|
|||||||
|
|
||||||
private val isInitialized = MutableStateFlow(false)
|
private val isInitialized = MutableStateFlow(false)
|
||||||
|
|
||||||
// Add these to the Nostr class
|
|
||||||
private val _newEvents = MutableSharedFlow<UnsignedEvent>(extraBufferCapacity = 100)
|
private val _newEvents = MutableSharedFlow<UnsignedEvent>(extraBufferCapacity = 100)
|
||||||
val newEvents = _newEvents.asSharedFlow()
|
val newEvents = _newEvents.asSharedFlow()
|
||||||
|
|
||||||
@@ -144,24 +156,43 @@ class Nostr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun connectBootstrapRelays() {
|
suspend fun connectBootstrapRelays() {
|
||||||
// Bootstrap relays
|
NostrManager.BOOTSTRAP_RELAYS.forEach { url ->
|
||||||
client?.addRelay(RelayUrl.parse("wss://relay.primal.net"))
|
client?.addRelay(RelayUrl.parse(url))
|
||||||
client?.addRelay(RelayUrl.parse("wss://user.kindpag.es"))
|
}
|
||||||
client?.addRelay(RelayUrl.parse("wss://purplepag.es"))
|
NostrManager.INDEXER_RELAY.forEach { url ->
|
||||||
|
client?.addRelay(
|
||||||
|
url = RelayUrl.parse(url),
|
||||||
|
capabilities = RelayCapabilities.gossip()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// Connect to all bootstrap relays
|
||||||
|
client?.connect()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun reconnect() {
|
||||||
// Indexer relay for NIP-65 discovery
|
NostrManager.ALL_RELAYS.forEach { url ->
|
||||||
client?.addRelay(
|
try {
|
||||||
url = RelayUrl.parse("wss://indexer.coracle.social"),
|
client?.relay(RelayUrl.parse(url)).let { relay ->
|
||||||
capabilities = RelayCapabilities.gossip()
|
if (relay != null) {
|
||||||
)
|
if (relay.status() != RelayStatus.CONNECTED) {
|
||||||
|
relay.connect()
|
||||||
// Connect to all bootstrap relays and wait for all connections to be established
|
}
|
||||||
client?.connect(Duration.parse("2s"))
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println("Failed to reconnect relay: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun disconnect() {
|
suspend fun disconnect() {
|
||||||
client?.shutdown()
|
NostrManager.ALL_RELAYS.forEach { url ->
|
||||||
|
try {
|
||||||
|
client?.disconnectRelay(RelayUrl.parse(url))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println("Failed to disconnect relay: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun exit() {
|
suspend fun exit() {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
||||||
import io.ktor.serialization.kotlinx.json.json
|
import io.ktor.serialization.kotlinx.json.json
|
||||||
|
import kotlinx.coroutines.NonCancellable
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
@@ -15,6 +16,7 @@ import kotlinx.coroutines.flow.asStateFlow
|
|||||||
import kotlinx.coroutines.flow.receiveAsFlow
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import rust.nostr.sdk.AsyncNostrSigner
|
import rust.nostr.sdk.AsyncNostrSigner
|
||||||
@@ -85,6 +87,9 @@ class NostrViewModel(
|
|||||||
// Check local stored secret (secret key or bunker)
|
// Check local stored secret (secret key or bunker)
|
||||||
login()
|
login()
|
||||||
|
|
||||||
|
// Automatically reconnect bootstrap relays
|
||||||
|
reconnect()
|
||||||
|
|
||||||
// Observe the signer state and verify the relay list
|
// Observe the signer state and verify the relay list
|
||||||
observeSignerAndCheckRelays()
|
observeSignerAndCheckRelays()
|
||||||
|
|
||||||
@@ -100,7 +105,13 @@ class NostrViewModel(
|
|||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
// TODO: optimize relay connection
|
|
||||||
|
// Disconnect to all bootstrap relays
|
||||||
|
viewModelScope.launch {
|
||||||
|
withContext(NonCancellable) {
|
||||||
|
nostr.disconnect()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showError(message: String) {
|
private fun showError(message: String) {
|
||||||
@@ -116,6 +127,13 @@ class NostrViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun reconnect() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
nostr.waitUntilInitialized()
|
||||||
|
nostr.reconnect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun runObserver() {
|
private fun runObserver() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
// Observe new messages
|
// Observe new messages
|
||||||
|
|||||||
Reference in New Issue
Block a user