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
This commit is contained in:
Claude
2026-03-09 11:03:43 +00:00
parent b44bfacf46
commit 34da50029c
3 changed files with 83 additions and 5 deletions
@@ -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,
@@ -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 {
""
}
@@ -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 {
""
}