From 645bcf8f449a4278b167c9ec893cc4178b729810 Mon Sep 17 00:00:00 2001 From: M Date: Mon, 30 Mar 2026 08:17:09 +1100 Subject: [PATCH] refactor: lazy-load Namecoin services on Desktop (not kept in memory from start) Move Namecoin service initialization from App-level (eager, on every startup) to inside the LoggedIn branch (only created when user logs in and screens that use Namecoin are reachable). Matches the Android lazy pattern in AppModules. Also deduplicate NamecoinSettings: Android module now uses a typealias to the commons module version, matching the original PR intent. --- .../service/namecoin/NamecoinSettings.kt | 79 +------------------ .../vitorpamplona/amethyst/desktop/Main.kt | 9 --- 2 files changed, 1 insertion(+), 87 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/namecoin/NamecoinSettings.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/namecoin/NamecoinSettings.kt index 1a859848c..accf61510 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/namecoin/NamecoinSettings.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/namecoin/NamecoinSettings.kt @@ -20,81 +20,4 @@ */ package com.vitorpamplona.amethyst.service.namecoin -import androidx.compose.runtime.Stable -import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.ElectrumxServer -import kotlinx.serialization.Serializable - -/** - * Immutable data class representing the current Namecoin resolution config. - * - * When custom servers are configured, they are used EXCLUSIVELY and the - * hardcoded defaults are ignored. This gives privacy-conscious users full - * control over which ElectrumX servers observe their name lookups. - */ -@Serializable -@Stable -data class NamecoinSettings( - /** Whether Namecoin resolution is enabled at all. */ - val enabled: Boolean = true, - /** - * Custom ElectrumX servers. When non-empty, these replace the defaults. - * - * Each entry is `host:port` (TLS) or `host:port:tcp` (plaintext). - */ - val customServers: List = emptyList(), -) { - /** True when the user has configured at least one custom server. */ - val hasCustomServers: Boolean get() = customServers.isNotEmpty() - - /** - * Convert to [ElectrumxServer] instances used by the resolver. - * Returns `null` when no valid custom servers are configured (use defaults). - */ - fun toElectrumxServers(): List? { - if (customServers.isEmpty()) return null - return customServers - .mapNotNull { parseServerString(it) } - .ifEmpty { null } - } - - companion object { - val DEFAULT = NamecoinSettings() - - /** - * Parse `host:port` or `host:port:tcp` into an [ElectrumxServer]. - * - * TLS is the default protocol. Append `:tcp` for plaintext - * (useful for `.onion` addresses and local servers). - * - * `.onion` addresses automatically get `usePinnedTrustStore = true` - * since certificate verification is meaningless over Tor. - */ - fun parseServerString(s: String): ElectrumxServer? { - val parts = s.trim().split(":") - if (parts.size < 2) return null - val host = parts[0].trim() - val port = parts[1].trim().toIntOrNull() ?: return null - if (host.isEmpty() || port <= 0 || port > 65535) return null - val useSsl = parts.getOrNull(2)?.trim()?.lowercase() != "tcp" - val isOnion = host.endsWith(".onion") - // All custom servers use the pinned trust store. ElectrumX - // servers almost universally use self-signed certs, so we - // route them through our pinned SSLSocketFactory (hardcoded - // defaults + TOFU-pinned certs + system CAs). - return ElectrumxServer( - host = host, - port = port, - useSsl = useSsl, - usePinnedTrustStore = true, - ) - } - - /** - * Format an [ElectrumxServer] back to the `host:port[:tcp]` string form. - */ - fun formatServerString(server: ElectrumxServer): String { - val base = "${server.host}:${server.port}" - return if (server.useSsl) base else "$base:tcp" - } - } -} +typealias NamecoinSettings = com.vitorpamplona.amethyst.commons.model.nip05DnsIdentifiers.namecoin.NamecoinSettings diff --git a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/Main.kt b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/Main.kt index 67639e0ec..7ff47ed4d 100644 --- a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/Main.kt +++ b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/Main.kt @@ -719,10 +719,6 @@ fun App( } val localCache = remember { DesktopLocalCache() } - val namecoinPreferences = remember { DesktopNamecoinPreferences() } - val namecoinService = remember { - DesktopNamecoinNameService(preferencesProvider = { namecoinPreferences.current }) - } val accountState by accountManager.accountState.collectAsState() val scope = remember { CoroutineScope(SupervisorJob() + Dispatchers.Main) } @@ -900,10 +896,6 @@ fun App( ProvideMaterialSymbols( weight = com.vitorpamplona.amethyst.desktop.platform.PlatformIconWeight.current, ) { - CompositionLocalProvider( - LocalNamecoinPreferences provides namecoinPreferences, - LocalNamecoinService provides namecoinService, - ) { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background, @@ -1068,7 +1060,6 @@ fun App( } } } - } // end CompositionLocalProvider } }