Update Quartz to 1.08.0 and refactor NostrClient usage

Migrates `NostrClient` method calls and listeners to align with the updated Quartz library API.

Key changes:
- Update `quartz` version to `1.08.0` and `richtextUi` to `a02a03a3e9`.
- Replace `IRelayClientListener` with `RelayConnectionListener` across all service and UI components.
- Rename `client.subscribe(listener)` to `client.addConnectionListener(listener)` and `client.unsubscribe(listener)` to `client.removeConnectionListener(listener)`.
- Replace `client.openReqSubscription` with `client.subscribe` and `client.close` with `client.unsubscribe`.
- Rename `client.send` to `client.publish` and `client.sendAndWaitForResponse` to `client.publishAndConfirm`.
This commit is contained in:
greenart7c3
2026-04-08 14:17:41 -03:00
parent 158609bc84
commit 884f7c5613
10 changed files with 40 additions and 40 deletions
@@ -52,7 +52,7 @@ import com.greenart7c3.nostrsigner.service.crashreports.UnexpectedCrashSaver
import com.greenart7c3.nostrsigner.ui.ToastManager
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.sendAndWaitForResponse
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.publishAndConfirm
import com.vitorpamplona.quartz.nip01Core.relay.client.auth.RelayAuthenticator
import com.vitorpamplona.quartz.nip01Core.relay.client.stats.RelayStats
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
@@ -116,7 +116,7 @@ class Amber :
// logs and stat counts.
val listener = NostrClientLoggerListener(this, stats, applicationIOScope).also {
client.subscribe(it)
client.addConnectionListener(it)
}
// Authenticates with relays.
@@ -587,7 +587,7 @@ class Amber :
// This will automatically connect to these relays even if they are not in the list
// once the events have been saved, it will disconnect from them unless there are other
// filters with them
return client.sendAndWaitForResponse(event, relays)
return client.publishAndConfirm(event, relays)
}
companion object {
@@ -10,7 +10,7 @@ import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.database.LogEntity
import com.greenart7c3.nostrsigner.service.NotificationUtils.sendErrorNotification
import com.greenart7c3.nostrsigner.ui.ToastManager
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.OkMessage
@@ -50,7 +50,7 @@ class NostrClientLoggerListener(
val context: Context,
val stats: AmberRelayStats,
val scope: CoroutineScope,
) : IRelayClientListener {
) : RelayConnectionListener {
private var reconnectJob: Job? = null
private var reconnectDelay = 5_000L
private var lastDisconnectTime = 0L
@@ -24,7 +24,7 @@ import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.jackson.JacksonMapper
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.sendAndWaitForResponse
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.publishAndConfirm
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerRequest
@@ -157,7 +157,7 @@ object BunkerRequestUtils {
Log.d(Amber.TAG, "Sending response to relays ${relays.map { relay -> relay.url }} type ${bunkerRequest.request.method}")
val success = retryWithBackoff {
val result = Amber.instance.client.sendAndWaitForResponse(
val result = Amber.instance.client.publishAndConfirm(
event = signedEvent,
relayList = relays.toSet(),
timeoutInSeconds = 5,
@@ -26,7 +26,7 @@ import com.greenart7c3.nostrsigner.Amber
import com.greenart7c3.nostrsigner.BuildFlavorChecker
import com.greenart7c3.nostrsigner.LocalPreferences
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.EventMessage
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
@@ -39,13 +39,13 @@ import java.util.UUID
class NotificationSubscription(
val client: NostrClient,
val appContext: Context,
) : IRelayClientListener {
) : RelayConnectionListener {
private val eventNotificationConsumer = EventNotificationConsumer(appContext)
private val subIds = mutableMapOf<String, String>()
init {
// listens until the app crashes.
client.subscribe(this)
client.addConnectionListener(this)
}
override fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) {
@@ -87,7 +87,7 @@ class NotificationSubscription(
subIds[subKey] = UUID.randomUUID().toString()
}
val connRelays = conn.relays.ifEmpty { Amber.instance.getSavedRelays(account) }
client.openReqSubscription(
client.subscribe(
subIds[subKey]!!,
connRelays.associateWith {
listOf(
@@ -108,7 +108,7 @@ class NotificationSubscription(
subIds[account.hexKey] = UUID.randomUUID().toString()
}
val relays = Amber.instance.getSavedRelays(account)
client.openReqSubscription(
client.subscribe(
subIds[account.hexKey]!!,
relays.associateWith {
listOf(
@@ -29,7 +29,7 @@ import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.crypto.verify
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.EoseMessage
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.EventMessage
@@ -51,14 +51,14 @@ class ProfileSubscription(
val client: NostrClient,
val appContext: Context,
val scope: CoroutineScope,
) : IRelayClientListener {
) : RelayConnectionListener {
private val subIds = mutableMapOf<String, String>()
private val relaysPerSubId = mutableMapOf<String, MutableSet<NormalizedRelayUrl>>()
private val timeoutJobs = mutableMapOf<String, Job>()
init {
// listens until the app crashes.
client.subscribe(this)
client.addConnectionListener(this)
}
override fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) {
@@ -70,7 +70,7 @@ class ProfileSubscription(
if (relays.isEmpty()) {
timeoutJobs.remove(subId)?.cancel()
Amber.instance.intentionalDisconnectTime = System.currentTimeMillis()
client.close(subId)
client.unsubscribe(subId)
relaysPerSubId.remove(subId)
}
}
@@ -135,12 +135,12 @@ class ProfileSubscription(
val subId = subIds[it.hexKey]!!
val profileFilter = createProfileFilter(it)
relaysPerSubId[subId] = profileFilter.keys.toMutableSet()
client.openReqSubscription(subId, profileFilter)
client.subscribe(subId, profileFilter)
timeoutJobs[subId] = scope.launch {
delay(EOSE_TIMEOUT_MS)
if (relaysPerSubId.containsKey(subId)) {
Amber.instance.intentionalDisconnectTime = System.currentTimeMillis()
client.close(subId)
client.unsubscribe(subId)
relaysPerSubId.remove(subId)
timeoutJobs.remove(subId)
}
@@ -156,7 +156,7 @@ class ProfileSubscription(
Amber.instance.intentionalDisconnectTime = System.currentTimeMillis()
subIds.values.forEach {
timeoutJobs.remove(it)?.cancel()
client.close(it)
client.unsubscribe(it)
}
relaysPerSubId.clear()
}
@@ -12,7 +12,7 @@ import com.greenart7c3.nostrsigner.okhttp.HttpClientManager
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.crypto.verify
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.EoseMessage
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.EventMessage
@@ -47,7 +47,7 @@ enum class DownloadState {
class ZapstoreUpdater(
private val client: NostrClient,
private val scope: CoroutineScope,
) : IRelayClientListener {
) : RelayConnectionListener {
val latestRelease = MutableStateFlow<ZapstoreRelease?>(null)
val isChecking = MutableStateFlow(false)
val downloadState = MutableStateFlow(DownloadState.IDLE)
@@ -61,7 +61,7 @@ class ZapstoreUpdater(
private var timeoutJob: Job? = null
init {
client.subscribe(this)
client.addConnectionListener(this)
}
override fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) {
@@ -91,7 +91,7 @@ class ZapstoreUpdater(
limit = 10,
)
client.openReqSubscription(releaseSubId, mapOf(relay to listOf(releaseFilter)))
client.subscribe(releaseSubId, mapOf(relay to listOf(releaseFilter)))
timeoutJob = scope.launch {
delay(EOSE_TIMEOUT_MS)
@@ -151,7 +151,7 @@ class ZapstoreUpdater(
val fileFilter = Filter(
ids = pendingFileEventIds.toList(),
)
client.openReqSubscription(fileSubId, mapOf(relay to listOf(fileFilter)))
client.subscribe(fileSubId, mapOf(relay to listOf(fileFilter)))
}
private fun processFileEvent(event: Event) {
@@ -197,8 +197,8 @@ class ZapstoreUpdater(
timeoutJob?.cancel()
timeoutJob = null
Amber.instance.intentionalDisconnectTime = System.currentTimeMillis()
client.close(releaseSubId)
client.close(fileSubId)
client.unsubscribe(releaseSubId)
client.unsubscribe(fileSubId)
isChecking.value = false
pendingFileEventIds.clear()
latestRelease.value?.let { release ->
@@ -163,7 +163,7 @@ fun CrashReportScreen(
}
val signedEvents = account.createMessageNIP17(template)
signedEvents.wraps.forEach { wrap ->
client.send(
client.publish(
event = wrap,
relayList = setOf(
NormalizedRelayUrl(url = "wss://inbox.nostr.wine"),
@@ -73,8 +73,8 @@ import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.sendAndWaitForResponse
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.publishAndConfirm
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.EventMessage
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
@@ -380,7 +380,7 @@ fun onAddRelay(
var canSendRequest = false
val listener = object : IRelayClientListener {
val listener = object : RelayConnectionListener {
override fun onSent(relay: IRelayClient, cmdStr: String, cmd: Command, success: Boolean) {
if (!success) {
AmberListenerSingleton.latestErrorMessages.add("Failed to send event. Try again.")
@@ -426,13 +426,13 @@ fun onAddRelay(
}
}
client.subscribe(listener)
client.addConnectionListener(listener)
if (!client.isActive()) {
client.connect()
}
client.openReqSubscription(
client.subscribe(
ncSub,
mapOf(addedWSS to filters),
)
@@ -454,8 +454,8 @@ fun onAddRelay(
},
onReject = {},
)
client.close(ncSub)
client.unsubscribe(listener)
client.unsubscribe(ncSub)
client.removeConnectionListener(listener)
client.disconnect()
textFieldRelay.value = TextFieldValue("")
isLoading.value = false
@@ -465,7 +465,7 @@ fun onAddRelay(
var success = false
var errorCount = 0
while (!success && errorCount < 3) {
success = client.sendAndWaitForResponse(signedEvent, setOf(addedWSS))
success = client.publishAndConfirm(signedEvent, setOf(addedWSS))
if (!success) {
errorCount++
delay(1000)
@@ -490,9 +490,9 @@ fun onAddRelay(
filterResult = true
}
client.close(ncSub)
client.unsubscribe(ncSub)
client.disconnect()
client.unsubscribe(listener)
client.removeConnectionListener(listener)
if (success && filterResult) {
relays2.add(addedWSS)
@@ -272,7 +272,7 @@ fun ReportMissingEventKindButton(account: Account, kind: Int) {
}
val signedEvents = account.createMessageNIP17(template)
signedEvents.wraps.forEach { wrap ->
client.send(
client.publish(
event = wrap,
relayList = setOf(
NormalizedRelayUrl(url = "wss://inbox.nostr.wine"),
+2 -2
View File
@@ -11,9 +11,9 @@ junitVersion = "1.3.0"
lifecycle_version = "2.10.0"
material3 = "1.4.0"
nav_version = "2.9.7"
quartz = "1.06.3"
quartz = "1.08.0"
compose_ui = "1.10.6"
richtextUi = "f92ef49c9d"
richtextUi = "a02a03a3e9"
roomKtx = "2.8.4"
securityCryptoKtx = "1.1.0"
zxingAndroidEmbedded = "4.3.0"