From 34da50029c6dc9adf5fb3a6d05d8b42b372671cd Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Mar 2026 11:03:33 +0000 Subject: [PATCH] Show relay in edit-permission screen; add relay scope to multi-event screens EditPermission / PermissionRow: - Kind 22242 permissions now show their relay below the main label. Wildcard "*" displays "All relays"; a specific URL is shown as-is. BunkerMultiEventHomeScreen / IntentMultiEventHomeScreen: - When a batch contains kind 22242 relay-auth events an "Authentication scope" toggle appears (same as the single-event BunkerRelayAuthScreen): "This relay only" vs "All relays". - The selected scope is applied to every kind 22242 event in both the approve-all and discard-all flows. https://claude.ai/code/session_01Dm9zoUbbzdJzuXTNdAVhfW --- .../nostrsigner/ui/EditPermission.kt | 18 +++++++++- .../components/BunkerMultiEventHomeScreen.kt | 35 +++++++++++++++++-- .../components/IntentMultiEventHomeScreen.kt | 35 +++++++++++++++++-- 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/EditPermission.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/EditPermission.kt index ea743dcb..dace6c08 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/EditPermission.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/EditPermission.kt @@ -294,7 +294,7 @@ fun PermissionRow( onDelete: (ApplicationPermissionsEntity) -> Unit, ) { val context = LocalContext.current - val message = remember(permission.type, permission.kind, permission.acceptable) { + val message = remember(permission.type, permission.kind, permission.acceptable, permission.relay) { val localPermission = Permission( permission.type.toLowerCase(Locale.current), permission.kind, @@ -344,6 +344,22 @@ fun PermissionRow( overflow = TextOverflow.Ellipsis, ) + if (permission.kind == 22242 && permission.relay.isNotEmpty()) { + Text( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, bottom = 8.dp), + text = if (permission.relay == "*") { + context.getString(R.string.for_all_relays) + } else { + permission.relay + }, + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + AmberToggles( count = 3, selectedIndex = optionIndex, diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/BunkerMultiEventHomeScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/BunkerMultiEventHomeScreen.kt index 31bbbb64..ee4a79f7 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/BunkerMultiEventHomeScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/BunkerMultiEventHomeScreen.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ButtonDefaults @@ -104,6 +105,8 @@ fun BunkerMultiEventHomeScreen( var localAccount by remember { mutableStateOf("") } val key = bunkerRequests.first().localKey var rememberType by remember { mutableStateOf(RememberType.NEVER) } + var relayAuthScope by remember { mutableStateOf(RelayAuthScope.SPECIFIC) } + val hasRelayAuthEvents = groupedEvents.keys.contains(22242) var appName by remember { mutableStateOf(ApplicationNameCache.names["$localAccount-$key"] ?: key.toShortenHex()) } LaunchedEffect(Unit) { @@ -224,6 +227,34 @@ fun BunkerMultiEventHomeScreen( } } + if (hasRelayAuthEvents) { + LabeledBorderBox( + label = stringResource(R.string.relay_auth_scope), + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 4.dp, vertical = 8.dp), + ) { + AmberToggles( + selectedIndex = if (relayAuthScope == RelayAuthScope.SPECIFIC) 0 else 1, + count = 2, + segmentWidth = 120.dp, + ) { + ToggleOption( + modifier = Modifier.width(120.dp), + text = stringResource(R.string.for_this_relay_only), + isSelected = relayAuthScope == RelayAuthScope.SPECIFIC, + onClick = { relayAuthScope = RelayAuthScope.SPECIFIC }, + ) + ToggleOption( + modifier = Modifier.width(120.dp), + text = stringResource(R.string.for_all_relays), + isSelected = relayAuthScope == RelayAuthScope.ALL, + onClick = { relayAuthScope = RelayAuthScope.ALL }, + ) + } + } + } + RememberMyChoice( alwaysShow = true, shouldRunAcceptOrReject = null, @@ -297,7 +328,7 @@ fun BunkerMultiEventHomeScreen( if (request.rememberType.value != RememberType.NEVER && request.checked.value) { val rejectKind = if (request.request is BunkerRequestSign) request.request.event.kind else null val rejectRelay = if (request.request is BunkerRequestSign && request.request.event.kind == 22242) { - AmberEvent.relay(request.request.event) ?: "" + if (relayAuthScope == RelayAuthScope.ALL) "*" else (AmberEvent.relay(request.request.event) ?: "") } else { "" } @@ -385,7 +416,7 @@ fun BunkerMultiEventHomeScreen( if (request.rememberType.value != RememberType.NEVER && request.checked.value) { val signRelay = if (localEvent.kind == 22242) { - AmberEvent.relay(localEvent) ?: "" + if (relayAuthScope == RelayAuthScope.ALL) "*" else (AmberEvent.relay(localEvent) ?: "") } else { "" } diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/IntentMultiEventHomeScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/IntentMultiEventHomeScreen.kt index ea5bcced..a1ef1671 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/IntentMultiEventHomeScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/IntentMultiEventHomeScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ButtonDefaults @@ -106,6 +107,8 @@ fun IntentMultiEventHomeScreen( var localAccount by remember { mutableStateOf("") } val key = "$packageName" var rememberType by remember { mutableStateOf(RememberType.NEVER) } + var relayAuthScope by remember { mutableStateOf(RelayAuthScope.SPECIFIC) } + val hasRelayAuthEvents = groupedEvents.keys.contains(22242) LaunchedEffect(Unit) { launch(Dispatchers.IO) { @@ -233,6 +236,34 @@ fun IntentMultiEventHomeScreen( } } + if (hasRelayAuthEvents) { + LabeledBorderBox( + label = stringResource(R.string.relay_auth_scope), + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 4.dp, vertical = 8.dp), + ) { + AmberToggles( + selectedIndex = if (relayAuthScope == RelayAuthScope.SPECIFIC) 0 else 1, + count = 2, + segmentWidth = 120.dp, + ) { + ToggleOption( + modifier = Modifier.width(120.dp), + text = stringResource(R.string.for_this_relay_only), + isSelected = relayAuthScope == RelayAuthScope.SPECIFIC, + onClick = { relayAuthScope = RelayAuthScope.SPECIFIC }, + ) + ToggleOption( + modifier = Modifier.width(120.dp), + text = stringResource(R.string.for_all_relays), + isSelected = relayAuthScope == RelayAuthScope.ALL, + onClick = { relayAuthScope = RelayAuthScope.ALL }, + ) + } + } + } + RememberMyChoice( alwaysShow = true, shouldRunAcceptOrReject = null, @@ -301,7 +332,7 @@ fun IntentMultiEventHomeScreen( if (intentData.rememberType.value != RememberType.NEVER && intentData.checked.value) { val rejectKind = if (intentData.type == SignerType.SIGN_EVENT) intentData.event?.kind else null val rejectRelay = if (intentData.type == SignerType.SIGN_EVENT && intentData.event?.kind == 22242) { - intentData.event?.let { AmberEvent.relay(it) } ?: "" + if (relayAuthScope == RelayAuthScope.ALL) "*" else (intentData.event?.let { AmberEvent.relay(it) } ?: "") } else { "" } @@ -397,7 +428,7 @@ fun IntentMultiEventHomeScreen( if (intentData.rememberType.value != RememberType.NEVER && intentData.checked.value) { val signRelay = if (localEvent.kind == 22242) { - AmberEvent.relay(localEvent) ?: "" + if (relayAuthScope == RelayAuthScope.ALL) "*" else (AmberEvent.relay(localEvent) ?: "") } else { "" }