fix: add missing StateFlow import, merge duplicate KDoc blocks, and fix rebase conflicts
- Add missing 'import kotlinx.coroutines.flow.StateFlow' in SearchBarViewModel.kt - Merge duplicate KDoc blocks on nameShowWithFallback in ElectrumXClient.kt - Move NamecoinLookupException to ElectrumXServer.kt (avoid redeclaration) - Remove duplicate NameShowResult/ElectrumxServer from ElectrumXClient.kt - Fix ElectrumxClient -> ElectrumXClient renames in NamecoinNameService - Extract namecoinElectrumxClient in AppModules.kt for NamecoinNameService.init() - Update package paths from nip05.namecoin to nip05DnsIdentifiers.namecoin
This commit is contained in:
@@ -147,12 +147,14 @@ class AppModules(
|
|||||||
// Custom fetcher that considers tor settings and avoids forwarding.
|
// Custom fetcher that considers tor settings and avoids forwarding.
|
||||||
val nip05Fetcher = OkHttpNip05Fetcher(roleBasedHttpClientBuilder::okHttpClientForNip05)
|
val nip05Fetcher = OkHttpNip05Fetcher(roleBasedHttpClientBuilder::okHttpClientForNip05)
|
||||||
|
|
||||||
|
val namecoinElectrumxClient =
|
||||||
|
ElectrumXClient(
|
||||||
|
socketFactory = { roleBasedHttpClientBuilder.socketFactoryForNip05() },
|
||||||
|
)
|
||||||
|
|
||||||
val namecoinResolver =
|
val namecoinResolver =
|
||||||
NamecoinNameResolver(
|
NamecoinNameResolver(
|
||||||
electrumxClient =
|
electrumxClient = namecoinElectrumxClient,
|
||||||
ElectrumXClient(
|
|
||||||
socketFactory = { roleBasedHttpClientBuilder.socketFactoryForNip05() },
|
|
||||||
),
|
|
||||||
serverListProvider = {
|
serverListProvider = {
|
||||||
if (roleBasedHttpClientBuilder.shouldUseTorForNIP05("https://electrumx.example.com")) {
|
if (roleBasedHttpClientBuilder.shouldUseTorForNIP05("https://electrumx.example.com")) {
|
||||||
TOR_ELECTRUMX_SERVERS
|
TOR_ELECTRUMX_SERVERS
|
||||||
|
|||||||
+3
-2
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.service.namecoin
|
package com.vitorpamplona.amethyst.service.namecoin
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.DEFAULT_ELECTRUMX_SERVERS
|
||||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.ElectrumXClient
|
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.ElectrumXClient
|
||||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.ElectrumxServer
|
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.ElectrumxServer
|
||||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinLookupCache
|
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinLookupCache
|
||||||
@@ -50,7 +51,7 @@ class NamecoinNameService(
|
|||||||
private val resolver =
|
private val resolver =
|
||||||
NamecoinNameResolver(
|
NamecoinNameResolver(
|
||||||
electrumxClient = electrumxClient,
|
electrumxClient = electrumxClient,
|
||||||
serverListProvider = { customServers.ifEmpty { ElectrumxClient.DEFAULT_SERVERS } },
|
serverListProvider = { customServers.ifEmpty { DEFAULT_ELECTRUMX_SERVERS } },
|
||||||
)
|
)
|
||||||
private val cache = NamecoinLookupCache()
|
private val cache = NamecoinLookupCache()
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ class NamecoinNameService(
|
|||||||
"NamecoinNameService not initialized. Call init() first.",
|
"NamecoinNameService not initialized. Call init() first.",
|
||||||
)
|
)
|
||||||
|
|
||||||
fun init(electrumxClient: ElectrumxClient): NamecoinNameService =
|
fun init(electrumxClient: ElectrumXClient): NamecoinNameService =
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
instance?.let { return it }
|
instance?.let { return it }
|
||||||
NamecoinNameService(electrumxClient).also { instance = it }
|
NamecoinNameService(electrumxClient).also { instance = it }
|
||||||
|
|||||||
+17
-7
@@ -34,10 +34,9 @@ import com.vitorpamplona.amethyst.commons.ui.feeds.InvalidatableContent
|
|||||||
import com.vitorpamplona.amethyst.model.Account
|
import com.vitorpamplona.amethyst.model.Account
|
||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.service.namecoin.NamecoinNameService
|
|
||||||
import com.vitorpamplona.quartz.nip05.namecoin.NamecoinLookupException
|
|
||||||
import com.vitorpamplona.amethyst.service.relayClient.searchCommand.SearchQueryState
|
import com.vitorpamplona.amethyst.service.relayClient.searchCommand.SearchQueryState
|
||||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||||
|
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinLookupException
|
||||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinNameResolver
|
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinNameResolver
|
||||||
import com.vitorpamplona.quartz.nip10Notes.content.findHashtags
|
import com.vitorpamplona.quartz.nip10Notes.content.findHashtags
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -45,6 +44,7 @@ import kotlinx.coroutines.FlowPreview
|
|||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
|
import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.debounce
|
import kotlinx.coroutines.flow.debounce
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
@@ -83,10 +83,21 @@ class SearchBarViewModel(
|
|||||||
*/
|
*/
|
||||||
sealed class NamecoinSearchState {
|
sealed class NamecoinSearchState {
|
||||||
data object Idle : NamecoinSearchState()
|
data object Idle : NamecoinSearchState()
|
||||||
|
|
||||||
data object Loading : NamecoinSearchState()
|
data object Loading : NamecoinSearchState()
|
||||||
data class Resolved(val user: User) : NamecoinSearchState()
|
|
||||||
data class NotFound(val name: String) : NamecoinSearchState()
|
data class Resolved(
|
||||||
data class Expired(val name: String) : NamecoinSearchState()
|
val user: User,
|
||||||
|
) : NamecoinSearchState()
|
||||||
|
|
||||||
|
data class NotFound(
|
||||||
|
val name: String,
|
||||||
|
) : NamecoinSearchState()
|
||||||
|
|
||||||
|
data class Expired(
|
||||||
|
val name: String,
|
||||||
|
) : NamecoinSearchState()
|
||||||
|
|
||||||
data object ServersUnreachable : NamecoinSearchState()
|
data object ServersUnreachable : NamecoinSearchState()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,8 +143,7 @@ class SearchBarViewModel(
|
|||||||
is NamecoinSearchState.Resolved -> state.user
|
is NamecoinSearchState.Resolved -> state.user
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}.stateIn(viewModelScope, WhileSubscribed(5000), null)
|
||||||
.stateIn(viewModelScope, WhileSubscribed(5000), null)
|
|
||||||
|
|
||||||
val searchResultsUsers =
|
val searchResultsUsers =
|
||||||
combine(
|
combine(
|
||||||
|
|||||||
+2
-4
@@ -238,16 +238,14 @@ private fun ReactionRowItemCard(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onGloballyPositioned { coordinates ->
|
.onGloballyPositioned { coordinates ->
|
||||||
onMeasured(coordinates.size.height.toFloat())
|
onMeasured(coordinates.size.height.toFloat())
|
||||||
}
|
}.graphicsLayer {
|
||||||
.graphicsLayer {
|
|
||||||
translationY = dragOffsetY
|
translationY = dragOffsetY
|
||||||
shadowElevation = elevation
|
shadowElevation = elevation
|
||||||
if (isDragging) {
|
if (isDragging) {
|
||||||
scaleX = 1.02f
|
scaleX = 1.02f
|
||||||
scaleY = 1.02f
|
scaleY = 1.02f
|
||||||
}
|
}
|
||||||
}
|
}.padding(vertical = 8.dp),
|
||||||
.padding(vertical = 8.dp),
|
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
|||||||
+24
@@ -48,6 +48,30 @@ data class ElectrumxServer(
|
|||||||
val trustAllCerts: Boolean = false,
|
val trustAllCerts: Boolean = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specific exception types for Namecoin resolution failures.
|
||||||
|
* Allows callers to distinguish "name doesn't exist" from "servers unreachable".
|
||||||
|
*/
|
||||||
|
sealed class NamecoinLookupException(
|
||||||
|
message: String,
|
||||||
|
cause: Throwable? = null,
|
||||||
|
) : Exception(message, cause) {
|
||||||
|
/** The name was queried successfully but does not exist on the blockchain. */
|
||||||
|
class NameNotFound(
|
||||||
|
val name: String,
|
||||||
|
) : NamecoinLookupException("Name not found: $name")
|
||||||
|
|
||||||
|
/** The name has expired (>36000 blocks since last update). */
|
||||||
|
class NameExpired(
|
||||||
|
val name: String,
|
||||||
|
) : NamecoinLookupException("Name expired: $name")
|
||||||
|
|
||||||
|
/** All ElectrumX servers were unreachable or returned errors. */
|
||||||
|
class ServersUnreachable(
|
||||||
|
val lastError: Throwable? = null,
|
||||||
|
) : NamecoinLookupException("All ElectrumX servers unreachable", lastError)
|
||||||
|
}
|
||||||
|
|
||||||
/** Well-known public Namecoin ElectrumX servers (clearnet). */
|
/** Well-known public Namecoin ElectrumX servers (clearnet). */
|
||||||
val DEFAULT_ELECTRUMX_SERVERS =
|
val DEFAULT_ELECTRUMX_SERVERS =
|
||||||
listOf(
|
listOf(
|
||||||
|
|||||||
-46
@@ -52,48 +52,6 @@ import javax.net.ssl.SSLSocketFactory
|
|||||||
import javax.net.ssl.TrustManager
|
import javax.net.ssl.TrustManager
|
||||||
import javax.net.ssl.X509TrustManager
|
import javax.net.ssl.X509TrustManager
|
||||||
|
|
||||||
/**
|
|
||||||
* Result of an ElectrumX name_show query.
|
|
||||||
*
|
|
||||||
* Maps to the JSON fields returned by Namecoin Core / Electrum-NMC:
|
|
||||||
* { "name": "d/example", "value": "{...}", "txid": "abc...", "height": 12345, ... }
|
|
||||||
*/
|
|
||||||
@Serializable
|
|
||||||
data class NameShowResult(
|
|
||||||
val name: String,
|
|
||||||
val value: String,
|
|
||||||
val txid: String? = null,
|
|
||||||
val height: Int? = null,
|
|
||||||
val expiresIn: Int? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specific exception types for Namecoin resolution failures.
|
|
||||||
* Allows callers to distinguish "name doesn't exist" from "servers unreachable".
|
|
||||||
*/
|
|
||||||
sealed class NamecoinLookupException(message: String, cause: Throwable? = null) : Exception(message, cause) {
|
|
||||||
/** The name was queried successfully but does not exist on the blockchain. */
|
|
||||||
class NameNotFound(val name: String) : NamecoinLookupException("Name not found: $name")
|
|
||||||
|
|
||||||
/** The name has expired (>36000 blocks since last update). */
|
|
||||||
class NameExpired(val name: String) : NamecoinLookupException("Name expired: $name")
|
|
||||||
|
|
||||||
/** All ElectrumX servers were unreachable or returned errors. */
|
|
||||||
class ServersUnreachable(val lastError: Throwable? = null) :
|
|
||||||
NamecoinLookupException("All ElectrumX servers unreachable", lastError)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a single ElectrumX server endpoint.
|
|
||||||
*/
|
|
||||||
data class ElectrumxServer(
|
|
||||||
val host: String,
|
|
||||||
val port: Int,
|
|
||||||
val useSsl: Boolean = true,
|
|
||||||
/** If true, accept any certificate (self-signed, expired, etc.) */
|
|
||||||
val trustAllCerts: Boolean = false,
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lightweight, query-only ElectrumX client for Namecoin name resolution.
|
* Lightweight, query-only ElectrumX client for Namecoin name resolution.
|
||||||
*
|
*
|
||||||
@@ -184,10 +142,6 @@ class ElectrumXClient(
|
|||||||
*
|
*
|
||||||
* @param identifier Full Namecoin name, e.g. "d/example"
|
* @param identifier Full Namecoin name, e.g. "d/example"
|
||||||
* @param servers Ordered server list to try; defaults to [DEFAULT_ELECTRUMX_SERVERS]
|
* @param servers Ordered server list to try; defaults to [DEFAULT_ELECTRUMX_SERVERS]
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Try each server in order until one succeeds.
|
|
||||||
*
|
|
||||||
* @throws NamecoinLookupException.NameNotFound if the name definitively doesn't exist
|
* @throws NamecoinLookupException.NameNotFound if the name definitively doesn't exist
|
||||||
* @throws NamecoinLookupException.NameExpired if the name has expired
|
* @throws NamecoinLookupException.NameExpired if the name has expired
|
||||||
* @throws NamecoinLookupException.ServersUnreachable if all servers failed with connection errors
|
* @throws NamecoinLookupException.ServersUnreachable if all servers failed with connection errors
|
||||||
|
|||||||
Reference in New Issue
Block a user