diff --git a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/SearchScreen.kt b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/SearchScreen.kt index 0a47d4e69..89a369ba6 100644 --- a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/SearchScreen.kt +++ b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/SearchScreen.kt @@ -173,22 +173,29 @@ fun SearchScreen( var namecoinState by remember { mutableStateOf(null) } - // Resolve Namecoin identifiers with cancellation of stale lookups + // Resolve Namecoin identifiers with cancellation of stale lookups. + // Uses resolveDetailed() which returns typed outcomes instead of throwing, + // so we get proper NotFound/Expired/ServersUnreachable states. LaunchedEffect(displayText, namecoinEnabled) { if (!namecoinEnabled || !isNamecoinQuery || namecoinService == null) { namecoinState = null return@LaunchedEffect } namecoinState = NamecoinResolveState.Loading - try { - val result = namecoinService.resolve(displayText.trim()) - namecoinState = if (result != null) { - NamecoinResolveState.Resolved(result) - } else { + val outcome = namecoinService.resolveDetailed(displayText.trim()) + namecoinState = when (outcome) { + is NamecoinResolveOutcome.Success -> + NamecoinResolveState.Resolved(outcome.result) + is NamecoinResolveOutcome.NameNotFound -> NamecoinResolveState.NotFound - } - } catch (e: Exception) { - namecoinState = NamecoinResolveState.Error(e.message ?: "Resolution failed") + is NamecoinResolveOutcome.NoNostrField -> + NamecoinResolveState.Error("Name exists but has no Nostr pubkey") + is NamecoinResolveOutcome.ServersUnreachable -> + NamecoinResolveState.Error("ElectrumX servers unreachable — check your connection or try again") + is NamecoinResolveOutcome.InvalidIdentifier -> + NamecoinResolveState.Error("Invalid Namecoin identifier") + is NamecoinResolveOutcome.Timeout -> + NamecoinResolveState.Error("Resolution timed out — servers may be slow, try again") } }