fix(nip46): show the same identity in the connected-app list and detail

The dedicated NIP-46 apps list always rendered the client's npub, while the
detail header showed the app's self-declared website (url) when it had one — so
an app that advertised a website looked like a bare pubkey in the list but a
website once opened. Extract one nip46ClientSubtitle(url, clientPubKey) helper
(website host when declared, npub otherwise) and use it in both places so a row
and the screen it opens never disagree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FHr2mu5SiHwYNR7evYUuF
This commit is contained in:
Claude
2026-07-17 15:18:34 +00:00
parent 052459567c
commit 0734fdb8de
2 changed files with 25 additions and 3 deletions
@@ -90,6 +90,7 @@ import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.nip46.Nip46ActivityCard
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.nip46.nip46ClientSubtitle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -319,7 +320,7 @@ private fun Nip46AppHeader(
Column(modifier = Modifier.weight(1f)) {
Text(title, style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold, maxLines = 1, overflow = TextOverflow.Ellipsis)
Text(
url?.ifBlank { null } ?: (clientPubKey.take(16) + ""),
nip46ClientSubtitle(url, clientPubKey),
style = MaterialTheme.typography.bodySmall,
fontFamily = FontFamily.Monospace,
color = MaterialTheme.colorScheme.onSurfaceVariant,
@@ -160,7 +160,9 @@ private fun Nip46AppCard(
entry: Nip46AppEntry,
onClick: () -> Unit,
) {
val npub = remember(entry.clientPubKey) { runCatching { NPub.create(entry.clientPubKey) }.getOrDefault(entry.clientPubKey.take(12) + "") }
// Same identity line the detail screen (Nip46AppHeader) uses: the app's self-declared website
// when it has one, npub otherwise — so a row and its detail never disagree.
val subtitle = remember(entry.info?.url, entry.clientPubKey) { nip46ClientSubtitle(entry.info?.url, entry.clientPubKey) }
val title = entry.info?.name?.ifBlank { null } ?: stringResource(R.string.nip46_signer_remote_app)
val relayCount = entry.info?.relays?.size ?: 0
@@ -190,7 +192,7 @@ private fun Nip46AppCard(
overflow = TextOverflow.Ellipsis,
)
Text(
npub,
subtitle,
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
fontFamily = FontFamily.Monospace,
@@ -241,6 +243,25 @@ private fun AppSignerPolicy.shortLabel(): String =
AppSignerPolicy.PARANOID -> stringResource(R.string.napplet_policy_paranoid)
}
/**
* The identity line shown for a NIP-46 client: its self-declared website (host only) when it
* advertised one, otherwise its npub. Shared by the list card and the detail header so a row and
* the screen it opens always agree.
*/
internal fun nip46ClientSubtitle(
url: String?,
clientPubKey: HexKey,
): String {
val host =
url
?.ifBlank { null }
?.removePrefix("https://")
?.removePrefix("http://")
?.substringBefore('/')
?.ifBlank { null }
return host ?: runCatching { NPub.create(clientPubKey) }.getOrDefault(clientPubKey.take(12) + "")
}
private suspend fun loadNip46Apps(signerPubKey: HexKey): List<Nip46AppEntry> {
val store = Amethyst.instance.signerPermissionStore
val clientStore = Amethyst.instance.nip46ClientStore