mirror of
https://github.com/greenart7c3/Amber.git
synced 2026-10-06 11:28:22 +00:00
Remove mutable state from AmberBunkerRequest and IntentData
Replaces MutableState<Boolean> (checked) and MutableState<RememberType> (rememberType) fields in AmberBunkerRequest and IntentData with plain immutable values. UI state is now managed in MultiEventScreenIntents via a SnapshotStateMap (checkedStates) and a mutableStateOf (rememberType), keeping Compose state out of pure data models and fixing data class semantics (copy/equals/hashCode). https://claude.ai/code/session_01PRSKjmFms1Tj1QJ5FhfqZm
This commit is contained in:
@@ -1,8 +1,5 @@
|
||||
package com.greenart7c3.nostrsigner.models
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import com.greenart7c3.nostrsigner.ui.RememberType
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerRequest
|
||||
@@ -22,8 +19,6 @@ data class AmberBunkerRequest(
|
||||
val name: String,
|
||||
val signedEvent: Event?,
|
||||
val encryptedData: EncryptedDataKind?,
|
||||
val checked: MutableState<Boolean> = mutableStateOf(true),
|
||||
val rememberType: MutableState<RememberType> = mutableStateOf(RememberType.NEVER),
|
||||
val encryptionType: EncryptionType,
|
||||
val isNostrConnectUri: Boolean,
|
||||
)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.greenart7c3.nostrsigner.models
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import com.greenart7c3.nostrsigner.ui.RememberType
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
|
||||
@@ -16,8 +14,6 @@ data class IntentData(
|
||||
val returnType: ReturnType,
|
||||
val permissions: List<Permission>?,
|
||||
val currentAccount: String,
|
||||
val checked: MutableState<Boolean>,
|
||||
val rememberType: MutableState<RememberType>,
|
||||
val route: String?,
|
||||
val event: Event?,
|
||||
val encryptedData: EncryptedDataKind?,
|
||||
|
||||
@@ -8,7 +8,6 @@ import android.net.Uri
|
||||
import android.provider.Browser
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.platform.ClipEntry
|
||||
import androidx.compose.ui.platform.Clipboard
|
||||
import androidx.compose.ui.text.intl.Locale
|
||||
@@ -173,8 +172,6 @@ object IntentUtils {
|
||||
returnType = returnType,
|
||||
permissions = listOf(),
|
||||
currentAccount = Hex.decode(signedEvent.pubKey).toNpub(),
|
||||
checked = mutableStateOf(true),
|
||||
rememberType = mutableStateOf(RememberType.NEVER),
|
||||
route = route,
|
||||
event = signedEvent,
|
||||
encryptedData = null,
|
||||
@@ -219,8 +216,6 @@ object IntentUtils {
|
||||
returnType = returnType,
|
||||
permissions = listOf(),
|
||||
currentAccount = Hex.decode(pubKey).toNpub(),
|
||||
checked = mutableStateOf(true),
|
||||
rememberType = mutableStateOf(RememberType.NEVER),
|
||||
route = route,
|
||||
event = null,
|
||||
encryptedData = encryptedDataKind,
|
||||
@@ -238,8 +233,6 @@ object IntentUtils {
|
||||
returnType = returnType,
|
||||
permissions = listOf(),
|
||||
currentAccount = "",
|
||||
checked = mutableStateOf(true),
|
||||
rememberType = mutableStateOf(RememberType.NEVER),
|
||||
route = route,
|
||||
event = null,
|
||||
encryptedData = null,
|
||||
@@ -257,8 +250,6 @@ object IntentUtils {
|
||||
returnType = returnType,
|
||||
permissions = listOf(),
|
||||
currentAccount = "",
|
||||
checked = mutableStateOf(true),
|
||||
rememberType = mutableStateOf(RememberType.NEVER),
|
||||
route = route,
|
||||
event = null,
|
||||
encryptedData = null,
|
||||
@@ -359,8 +350,6 @@ object IntentUtils {
|
||||
returnType = returnType,
|
||||
permissions = permissions?.map { Permission(it.type.trim(), it.kind, it.checked) },
|
||||
currentAccount = npub ?: Hex.decode(signed.pubKey).toNpub(),
|
||||
checked = mutableStateOf(true),
|
||||
rememberType = mutableStateOf(RememberType.NEVER),
|
||||
route = route,
|
||||
event = signed,
|
||||
encryptedData = null,
|
||||
@@ -411,8 +400,6 @@ object IntentUtils {
|
||||
returnType = returnType,
|
||||
permissions = permissions?.map { Permission(it.type.trim(), it.kind, it.checked) },
|
||||
currentAccount = npub ?: Hex.decode(pubKey).toNpub(),
|
||||
checked = mutableStateOf(true),
|
||||
rememberType = mutableStateOf(RememberType.NEVER),
|
||||
route = route,
|
||||
event = null,
|
||||
encryptedData = encryptedDataKind,
|
||||
@@ -435,8 +422,6 @@ object IntentUtils {
|
||||
returnType = returnType,
|
||||
permissions = permissions?.map { Permission(it.type.trim(), it.kind, it.checked) },
|
||||
currentAccount = npub ?: Hex.decode(pubKey).toNpub(),
|
||||
checked = mutableStateOf(true),
|
||||
rememberType = mutableStateOf(RememberType.NEVER),
|
||||
route = route,
|
||||
event = null,
|
||||
encryptedData = null,
|
||||
@@ -459,8 +444,6 @@ object IntentUtils {
|
||||
returnType = returnType,
|
||||
permissions = permissions?.map { Permission(it.type.trim(), it.kind, it.checked) },
|
||||
currentAccount = npub ?: Hex.decode(pubKey).toNpub(),
|
||||
checked = mutableStateOf(true),
|
||||
rememberType = mutableStateOf(RememberType.NEVER),
|
||||
route = route,
|
||||
event = null,
|
||||
encryptedData = null,
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
package com.greenart7c3.nostrsigner.service
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import com.greenart7c3.nostrsigner.models.AmberBunkerRequest
|
||||
import com.greenart7c3.nostrsigner.models.IntentData
|
||||
import com.greenart7c3.nostrsigner.ui.RememberType
|
||||
|
||||
object MultiEventScreenIntents {
|
||||
var intents = listOf<IntentData>()
|
||||
var bunkerRequests = listOf<AmberBunkerRequest>()
|
||||
var appName = ""
|
||||
val checkedStates = mutableStateMapOf<String, Boolean>()
|
||||
var rememberType by mutableStateOf(RememberType.NEVER)
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ fun SeeDetailsScreen(
|
||||
.weight(1f)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
) {
|
||||
var rememberType by remember { mutableStateOf(MultiEventScreenIntents.intents.firstOrNull()?.rememberType?.value ?: MultiEventScreenIntents.bunkerRequests.first().rememberType.value) }
|
||||
var rememberType by remember { mutableStateOf(MultiEventScreenIntents.rememberType) }
|
||||
val type = if (MultiEventScreenIntents.intents.isNotEmpty()) {
|
||||
MultiEventScreenIntents.intents.first().type
|
||||
} else {
|
||||
@@ -96,15 +96,14 @@ fun SeeDetailsScreen(
|
||||
onReject = {},
|
||||
onChanged = {
|
||||
rememberType = it
|
||||
MultiEventScreenIntents.intents.forEach { intent ->
|
||||
intent.rememberType.value = rememberType
|
||||
}
|
||||
MultiEventScreenIntents.rememberType = it
|
||||
},
|
||||
packageName = null,
|
||||
)
|
||||
}
|
||||
|
||||
MultiEventScreenIntents.intents.forEach { intent ->
|
||||
val intentChecked = MultiEventScreenIntents.checkedStates[intent.id] ?: true
|
||||
Card(
|
||||
Modifier
|
||||
.padding(4.dp),
|
||||
@@ -118,13 +117,13 @@ fun SeeDetailsScreen(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
intent.checked.value = !intent.checked.value
|
||||
MultiEventScreenIntents.checkedStates[intent.id] = !intentChecked
|
||||
},
|
||||
) {
|
||||
Checkbox(
|
||||
checked = intent.checked.value,
|
||||
checked = intentChecked,
|
||||
onCheckedChange = { _ ->
|
||||
intent.checked.value = !intent.checked.value
|
||||
MultiEventScreenIntents.checkedStates[intent.id] = !intentChecked
|
||||
},
|
||||
colors = CheckboxDefaults.colors().copy(
|
||||
uncheckedBorderColor = Color.Gray,
|
||||
@@ -163,13 +162,14 @@ fun SeeDetailsScreen(
|
||||
.weight(1f)
|
||||
.padding(vertical = 8.dp),
|
||||
text = data.ifBlank { message },
|
||||
color = if (intent.checked.value) Color.Unspecified else Color.Gray,
|
||||
color = if (intentChecked) Color.Unspecified else Color.Gray,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MultiEventScreenIntents.bunkerRequests.forEach { bunkerRequest ->
|
||||
val bunkerChecked = MultiEventScreenIntents.checkedStates[bunkerRequest.request.id] ?: true
|
||||
Card(
|
||||
Modifier
|
||||
.padding(4.dp),
|
||||
@@ -183,13 +183,13 @@ fun SeeDetailsScreen(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
bunkerRequest.checked.value = !bunkerRequest.checked.value
|
||||
MultiEventScreenIntents.checkedStates[bunkerRequest.request.id] = !bunkerChecked
|
||||
},
|
||||
) {
|
||||
Checkbox(
|
||||
checked = bunkerRequest.checked.value,
|
||||
checked = bunkerChecked,
|
||||
onCheckedChange = { _ ->
|
||||
bunkerRequest.checked.value = !bunkerRequest.checked.value
|
||||
MultiEventScreenIntents.checkedStates[bunkerRequest.request.id] = !bunkerChecked
|
||||
},
|
||||
colors = CheckboxDefaults.colors().copy(
|
||||
uncheckedBorderColor = Color.Gray,
|
||||
@@ -228,7 +228,7 @@ fun SeeDetailsScreen(
|
||||
.weight(1f)
|
||||
.padding(vertical = 8.dp),
|
||||
text = data.ifBlank { message },
|
||||
color = if (bunkerRequest.checked.value) Color.Unspecified else Color.Gray,
|
||||
color = if (bunkerChecked) Color.Unspecified else Color.Gray,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+50
-29
@@ -53,6 +53,7 @@ import com.greenart7c3.nostrsigner.service.AmberUtils
|
||||
import com.greenart7c3.nostrsigner.service.ApplicationNameCache
|
||||
import com.greenart7c3.nostrsigner.service.BunkerRequestUtils
|
||||
import com.greenart7c3.nostrsigner.service.EventNotificationConsumer
|
||||
import com.greenart7c3.nostrsigner.service.MultiEventScreenIntents
|
||||
import com.greenart7c3.nostrsigner.service.model.AmberEvent
|
||||
import com.greenart7c3.nostrsigner.service.toShortenHex
|
||||
import com.greenart7c3.nostrsigner.ui.RememberType
|
||||
@@ -82,6 +83,12 @@ fun BunkerMultiEventHomeScreen(
|
||||
var relayAuthScope by remember { mutableStateOf(RelayAuthScope.SPECIFIC) }
|
||||
var appName by remember { mutableStateOf(ApplicationNameCache.names["$localAccount-$key"] ?: key.toShortenHex()) }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
MultiEventScreenIntents.checkedStates.clear()
|
||||
MultiEventScreenIntents.rememberType = RememberType.NEVER
|
||||
bunkerRequests.forEach { MultiEventScreenIntents.checkedStates[it.request.id] = true }
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
launch(Dispatchers.IO) {
|
||||
localAccount = LocalPreferences.loadFromEncryptedStorage(
|
||||
@@ -116,8 +123,8 @@ fun BunkerMultiEventHomeScreen(
|
||||
SigningAs(accountParam)
|
||||
|
||||
val allCheckedState = when {
|
||||
bunkerRequests.all { it.checked.value } -> ToggleableState.On
|
||||
bunkerRequests.none { it.checked.value } -> ToggleableState.Off
|
||||
bunkerRequests.all { MultiEventScreenIntents.checkedStates[it.request.id] ?: true } -> ToggleableState.On
|
||||
bunkerRequests.none { MultiEventScreenIntents.checkedStates[it.request.id] ?: true } -> ToggleableState.Off
|
||||
else -> ToggleableState.Indeterminate
|
||||
}
|
||||
Row(
|
||||
@@ -126,14 +133,14 @@ fun BunkerMultiEventHomeScreen(
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
val newValue = allCheckedState != ToggleableState.On
|
||||
bunkerRequests.forEach { it.checked.value = newValue }
|
||||
bunkerRequests.forEach { MultiEventScreenIntents.checkedStates[it.request.id] = newValue }
|
||||
},
|
||||
) {
|
||||
TriStateCheckbox(
|
||||
state = allCheckedState,
|
||||
onClick = {
|
||||
val newValue = allCheckedState != ToggleableState.On
|
||||
bunkerRequests.forEach { it.checked.value = newValue }
|
||||
bunkerRequests.forEach { MultiEventScreenIntents.checkedStates[it.request.id] = newValue }
|
||||
},
|
||||
)
|
||||
Text(stringResource(R.string.select_deselect_all))
|
||||
@@ -145,7 +152,15 @@ fun BunkerMultiEventHomeScreen(
|
||||
.verticalScroll(rememberScrollState()),
|
||||
) {
|
||||
bunkerRequests.forEach { bunkerRequest ->
|
||||
BunkerRequestCard(context = context, bunkerRequest = bunkerRequest)
|
||||
BunkerRequestCard(
|
||||
context = context,
|
||||
bunkerRequest = bunkerRequest,
|
||||
checked = MultiEventScreenIntents.checkedStates[bunkerRequest.request.id] ?: true,
|
||||
onToggleChecked = {
|
||||
val current = MultiEventScreenIntents.checkedStates[bunkerRequest.request.id] ?: true
|
||||
MultiEventScreenIntents.checkedStates[bunkerRequest.request.id] = !current
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,9 +199,7 @@ fun BunkerMultiEventHomeScreen(
|
||||
onReject = {},
|
||||
onChanged = {
|
||||
rememberType = it
|
||||
bunkerRequests.forEach { bunkerRequest ->
|
||||
bunkerRequest.rememberType.value = rememberType
|
||||
}
|
||||
MultiEventScreenIntents.rememberType = it
|
||||
},
|
||||
packageName = packageName,
|
||||
)
|
||||
@@ -247,7 +260,8 @@ fun BunkerMultiEventHomeScreen(
|
||||
permissions = mutableListOf(),
|
||||
)
|
||||
|
||||
if (request.rememberType.value != RememberType.NEVER && request.checked.value) {
|
||||
val isChecked = MultiEventScreenIntents.checkedStates[request.request.id] ?: true
|
||||
if (rememberType != RememberType.NEVER && isChecked) {
|
||||
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) {
|
||||
if (relayAuthScope == RelayAuthScope.ALL) {
|
||||
@@ -272,7 +286,7 @@ fun BunkerMultiEventHomeScreen(
|
||||
BunkerRequestUtils.getTypeFromBunker(request.request),
|
||||
rejectKind,
|
||||
false,
|
||||
request.rememberType.value,
|
||||
rememberType,
|
||||
thisAccount,
|
||||
relay = rejectRelay,
|
||||
)
|
||||
@@ -345,10 +359,12 @@ fun BunkerMultiEventHomeScreen(
|
||||
permissions = mutableListOf(),
|
||||
)
|
||||
|
||||
val isChecked = MultiEventScreenIntents.checkedStates[request.request.id] ?: true
|
||||
|
||||
if (request.request is BunkerRequestSign) {
|
||||
val localEvent = request.signedEvent!!
|
||||
|
||||
if (request.rememberType.value != RememberType.NEVER && request.checked.value) {
|
||||
if (rememberType != RememberType.NEVER && isChecked) {
|
||||
val signRelay = if (localEvent.kind == 22242) {
|
||||
if (relayAuthScope == RelayAuthScope.ALL) {
|
||||
"*"
|
||||
@@ -372,7 +388,7 @@ fun BunkerMultiEventHomeScreen(
|
||||
signerType = SignerType.SIGN_EVENT,
|
||||
kind = localEvent.kind,
|
||||
value = true,
|
||||
rememberType = request.rememberType.value,
|
||||
rememberType = rememberType,
|
||||
account = thisAccount,
|
||||
relay = signRelay,
|
||||
)
|
||||
@@ -387,7 +403,7 @@ fun BunkerMultiEventHomeScreen(
|
||||
type = SignerType.SIGN_EVENT.toString(),
|
||||
kind = localEvent.kind,
|
||||
time = TimeUtils.now(),
|
||||
accepted = request.checked.value,
|
||||
accepted = isChecked,
|
||||
content = localEvent.toJson(),
|
||||
),
|
||||
thisAccount.npub,
|
||||
@@ -395,7 +411,7 @@ fun BunkerMultiEventHomeScreen(
|
||||
|
||||
BunkerRequestUtils.remove(request.request.id)
|
||||
|
||||
if (request.checked.value) {
|
||||
if (isChecked) {
|
||||
BunkerRequestUtils.sendBunkerResponse(
|
||||
context,
|
||||
thisAccount,
|
||||
@@ -416,14 +432,14 @@ fun BunkerMultiEventHomeScreen(
|
||||
)
|
||||
}
|
||||
} else if (request.request.method == "sign_message") {
|
||||
if (request.rememberType.value != RememberType.NEVER && request.checked.value) {
|
||||
if (rememberType != RememberType.NEVER && isChecked) {
|
||||
AmberUtils.acceptOrRejectPermission(
|
||||
application,
|
||||
localKey,
|
||||
SignerType.SIGN_MESSAGE,
|
||||
null,
|
||||
true,
|
||||
request.rememberType.value,
|
||||
rememberType,
|
||||
thisAccount,
|
||||
)
|
||||
}
|
||||
@@ -436,7 +452,7 @@ fun BunkerMultiEventHomeScreen(
|
||||
SignerType.SIGN_MESSAGE.toString(),
|
||||
null,
|
||||
TimeUtils.now(),
|
||||
request.checked.value,
|
||||
isChecked,
|
||||
content = request.request.params.first(),
|
||||
),
|
||||
thisAccount.npub,
|
||||
@@ -445,7 +461,7 @@ fun BunkerMultiEventHomeScreen(
|
||||
val signedMessage = thisAccount.signString(request.request.params.first())
|
||||
BunkerRequestUtils.remove(request.request.id)
|
||||
|
||||
if (request.checked.value) {
|
||||
if (isChecked) {
|
||||
BunkerRequestUtils.sendBunkerResponse(
|
||||
context,
|
||||
thisAccount,
|
||||
@@ -476,14 +492,14 @@ fun BunkerMultiEventHomeScreen(
|
||||
SignerType.CONNECT.toString(),
|
||||
null,
|
||||
TimeUtils.now(),
|
||||
request.checked.value,
|
||||
isChecked,
|
||||
content = "",
|
||||
),
|
||||
thisAccount.npub,
|
||||
)
|
||||
|
||||
BunkerRequestUtils.remove(request.request.id)
|
||||
if (request.checked.value) {
|
||||
if (isChecked) {
|
||||
BunkerRequestUtils.sendBunkerResponse(
|
||||
context,
|
||||
thisAccount,
|
||||
@@ -506,14 +522,14 @@ fun BunkerMultiEventHomeScreen(
|
||||
}
|
||||
} else {
|
||||
val type = BunkerRequestUtils.getTypeFromBunker(request.request)
|
||||
if (request.rememberType.value != RememberType.NEVER && request.checked.value) {
|
||||
if (rememberType != RememberType.NEVER && isChecked) {
|
||||
AmberUtils.acceptOrRejectPermission(
|
||||
application,
|
||||
localKey,
|
||||
type,
|
||||
null,
|
||||
true,
|
||||
request.rememberType.value,
|
||||
rememberType,
|
||||
thisAccount,
|
||||
)
|
||||
}
|
||||
@@ -527,7 +543,7 @@ fun BunkerMultiEventHomeScreen(
|
||||
type.toString(),
|
||||
null,
|
||||
TimeUtils.now(),
|
||||
request.checked.value,
|
||||
isChecked,
|
||||
content = if (type == SignerType.NIP04_DECRYPT || type == SignerType.NIP44_DECRYPT || type == SignerType.DECRYPT_ZAP_EVENT) {
|
||||
request.encryptedData?.result ?: ""
|
||||
} else {
|
||||
@@ -539,7 +555,7 @@ fun BunkerMultiEventHomeScreen(
|
||||
|
||||
val signature = request.encryptedData?.result ?: continue
|
||||
BunkerRequestUtils.remove(request.request.id)
|
||||
if (request.checked.value) {
|
||||
if (isChecked) {
|
||||
BunkerRequestUtils.sendBunkerResponse(
|
||||
context,
|
||||
thisAccount,
|
||||
@@ -572,7 +588,12 @@ fun BunkerMultiEventHomeScreen(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BunkerRequestCard(context: Context, bunkerRequest: AmberBunkerRequest) {
|
||||
private fun BunkerRequestCard(
|
||||
context: Context,
|
||||
bunkerRequest: AmberBunkerRequest,
|
||||
checked: Boolean,
|
||||
onToggleChecked: () -> Unit,
|
||||
) {
|
||||
val type = BunkerRequestUtils.getTypeFromBunker(bunkerRequest.request)
|
||||
var showDetails by remember { mutableStateOf(false) }
|
||||
val hasDetails = (type == SignerType.SIGN_EVENT && bunkerRequest.signedEvent != null) ||
|
||||
@@ -655,11 +676,11 @@ private fun BunkerRequestCard(context: Context, bunkerRequest: AmberBunkerReques
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { bunkerRequest.checked.value = !bunkerRequest.checked.value },
|
||||
.clickable { onToggleChecked() },
|
||||
) {
|
||||
Checkbox(
|
||||
checked = bunkerRequest.checked.value,
|
||||
onCheckedChange = { bunkerRequest.checked.value = !bunkerRequest.checked.value },
|
||||
checked = checked,
|
||||
onCheckedChange = { onToggleChecked() },
|
||||
colors = CheckboxDefaults.colors().copy(
|
||||
uncheckedBorderColor = Color.Gray,
|
||||
),
|
||||
@@ -671,7 +692,7 @@ private fun BunkerRequestCard(context: Context, bunkerRequest: AmberBunkerReques
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
color = if (bunkerRequest.checked.value) Color.Unspecified else Color.Gray,
|
||||
color = if (checked) Color.Unspecified else Color.Gray,
|
||||
)
|
||||
if (preview.isNotBlank()) {
|
||||
Text(
|
||||
|
||||
@@ -16,6 +16,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import com.greenart7c3.nostrsigner.service.MultiEventScreenIntents
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -66,14 +67,14 @@ fun BunkerPermissionCard(
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
acceptEventsGroup[index].value = !acceptEventsGroup[index].value
|
||||
item.second.forEach { it.checked.value = acceptEventsGroup[index].value }
|
||||
item.second.forEach { MultiEventScreenIntents.checkedStates[it.request.id] = acceptEventsGroup[index].value }
|
||||
},
|
||||
) {
|
||||
Checkbox(
|
||||
checked = acceptEventsGroup[index].value,
|
||||
onCheckedChange = { _ ->
|
||||
acceptEventsGroup[index].value = !acceptEventsGroup[index].value
|
||||
item.second.forEach { it.checked.value = acceptEventsGroup[index].value }
|
||||
item.second.forEach { MultiEventScreenIntents.checkedStates[it.request.id] = acceptEventsGroup[index].value }
|
||||
},
|
||||
colors = CheckboxDefaults.colors().copy(
|
||||
uncheckedBorderColor = Color.Gray,
|
||||
@@ -134,7 +135,7 @@ fun BunkerPermissionCard(
|
||||
)
|
||||
}
|
||||
if (acceptEventsGroup[index].value) {
|
||||
val selected = item.second.filter { it.checked.value }.size
|
||||
val selected = item.second.filter { MultiEventScreenIntents.checkedStates[it.request.id] ?: true }.size
|
||||
val total = item.second.size
|
||||
Row(
|
||||
Modifier
|
||||
|
||||
+48
-27
@@ -55,6 +55,7 @@ import com.greenart7c3.nostrsigner.models.SignerType
|
||||
import com.greenart7c3.nostrsigner.models.TagArrayEncryptedDataKind
|
||||
import com.greenart7c3.nostrsigner.service.AmberUtils
|
||||
import com.greenart7c3.nostrsigner.service.ApplicationNameCache
|
||||
import com.greenart7c3.nostrsigner.service.MultiEventScreenIntents
|
||||
import com.greenart7c3.nostrsigner.service.model.AmberEvent
|
||||
import com.greenart7c3.nostrsigner.service.toShortenHex
|
||||
import com.greenart7c3.nostrsigner.ui.RememberType
|
||||
@@ -82,6 +83,12 @@ fun IntentMultiEventHomeScreen(
|
||||
var rememberType by remember { mutableStateOf(RememberType.NEVER) }
|
||||
var relayAuthScope by remember { mutableStateOf(RelayAuthScope.SPECIFIC) }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
MultiEventScreenIntents.checkedStates.clear()
|
||||
MultiEventScreenIntents.rememberType = RememberType.NEVER
|
||||
intents.forEach { MultiEventScreenIntents.checkedStates[it.id] = true }
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
launch(Dispatchers.IO) {
|
||||
localAccount = LocalPreferences.loadFromEncryptedStorage(
|
||||
@@ -124,8 +131,8 @@ fun IntentMultiEventHomeScreen(
|
||||
SigningAs(accountParam)
|
||||
|
||||
val allCheckedState = when {
|
||||
intents.all { it.checked.value } -> ToggleableState.On
|
||||
intents.none { it.checked.value } -> ToggleableState.Off
|
||||
intents.all { MultiEventScreenIntents.checkedStates[it.id] ?: true } -> ToggleableState.On
|
||||
intents.none { MultiEventScreenIntents.checkedStates[it.id] ?: true } -> ToggleableState.Off
|
||||
else -> ToggleableState.Indeterminate
|
||||
}
|
||||
Row(
|
||||
@@ -134,14 +141,14 @@ fun IntentMultiEventHomeScreen(
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
val newValue = allCheckedState != ToggleableState.On
|
||||
intents.forEach { it.checked.value = newValue }
|
||||
intents.forEach { MultiEventScreenIntents.checkedStates[it.id] = newValue }
|
||||
},
|
||||
) {
|
||||
TriStateCheckbox(
|
||||
state = allCheckedState,
|
||||
onClick = {
|
||||
val newValue = allCheckedState != ToggleableState.On
|
||||
intents.forEach { it.checked.value = newValue }
|
||||
intents.forEach { MultiEventScreenIntents.checkedStates[it.id] = newValue }
|
||||
},
|
||||
)
|
||||
Text(stringResource(R.string.select_deselect_all))
|
||||
@@ -153,7 +160,15 @@ fun IntentMultiEventHomeScreen(
|
||||
.verticalScroll(rememberScrollState()),
|
||||
) {
|
||||
intents.forEach { intent ->
|
||||
IntentRequestCard(context = context, intent = intent)
|
||||
IntentRequestCard(
|
||||
context = context,
|
||||
intent = intent,
|
||||
checked = MultiEventScreenIntents.checkedStates[intent.id] ?: true,
|
||||
onToggleChecked = {
|
||||
val current = MultiEventScreenIntents.checkedStates[intent.id] ?: true
|
||||
MultiEventScreenIntents.checkedStates[intent.id] = !current
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,9 +207,7 @@ fun IntentMultiEventHomeScreen(
|
||||
onReject = {},
|
||||
onChanged = {
|
||||
rememberType = it
|
||||
intents.forEach { intent ->
|
||||
intent.rememberType.value = rememberType
|
||||
}
|
||||
MultiEventScreenIntents.rememberType = it
|
||||
},
|
||||
packageName = packageName,
|
||||
)
|
||||
@@ -250,7 +263,8 @@ fun IntentMultiEventHomeScreen(
|
||||
permissions = mutableListOf(),
|
||||
)
|
||||
|
||||
if (intentData.rememberType.value != RememberType.NEVER && intentData.checked.value) {
|
||||
val isChecked = MultiEventScreenIntents.checkedStates[intentData.id] ?: true
|
||||
if (rememberType != RememberType.NEVER && isChecked) {
|
||||
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) {
|
||||
if (relayAuthScope == RelayAuthScope.ALL) {
|
||||
@@ -275,7 +289,7 @@ fun IntentMultiEventHomeScreen(
|
||||
intentData.type,
|
||||
rejectKind,
|
||||
false,
|
||||
intentData.rememberType.value,
|
||||
rememberType,
|
||||
thisAccount,
|
||||
relay = rejectRelay,
|
||||
)
|
||||
@@ -356,10 +370,12 @@ fun IntentMultiEventHomeScreen(
|
||||
closeApp = false
|
||||
}
|
||||
|
||||
val isChecked = MultiEventScreenIntents.checkedStates[intentData.id] ?: true
|
||||
|
||||
if (intentData.type == SignerType.SIGN_EVENT) {
|
||||
val localEvent = intentData.event!!
|
||||
|
||||
if (intentData.rememberType.value != RememberType.NEVER && intentData.checked.value) {
|
||||
if (rememberType != RememberType.NEVER && isChecked) {
|
||||
val signRelay = if (localEvent.kind == 22242) {
|
||||
if (relayAuthScope == RelayAuthScope.ALL) {
|
||||
"*"
|
||||
@@ -383,7 +399,7 @@ fun IntentMultiEventHomeScreen(
|
||||
intentData.type,
|
||||
localEvent.kind,
|
||||
true,
|
||||
intentData.rememberType.value,
|
||||
rememberType,
|
||||
thisAccount,
|
||||
relay = signRelay,
|
||||
)
|
||||
@@ -398,13 +414,13 @@ fun IntentMultiEventHomeScreen(
|
||||
intentData.type.toString(),
|
||||
localEvent.kind,
|
||||
TimeUtils.now(),
|
||||
intentData.checked.value,
|
||||
isChecked,
|
||||
content = localEvent.toJson(),
|
||||
),
|
||||
thisAccount.npub,
|
||||
)
|
||||
|
||||
if (intentData.checked.value) {
|
||||
if (isChecked) {
|
||||
results.add(
|
||||
Result(
|
||||
null,
|
||||
@@ -432,14 +448,14 @@ fun IntentMultiEventHomeScreen(
|
||||
)
|
||||
}
|
||||
} else if (intentData.type == SignerType.SIGN_MESSAGE) {
|
||||
if (intentData.rememberType.value != RememberType.NEVER && intentData.checked.value) {
|
||||
if (rememberType != RememberType.NEVER && isChecked) {
|
||||
AmberUtils.acceptOrRejectPermission(
|
||||
application,
|
||||
localKey,
|
||||
intentData.type,
|
||||
null,
|
||||
true,
|
||||
intentData.rememberType.value,
|
||||
rememberType,
|
||||
thisAccount,
|
||||
)
|
||||
}
|
||||
@@ -452,14 +468,14 @@ fun IntentMultiEventHomeScreen(
|
||||
intentData.type.toString(),
|
||||
null,
|
||||
TimeUtils.now(),
|
||||
intentData.checked.value,
|
||||
isChecked,
|
||||
content = intentData.data,
|
||||
),
|
||||
thisAccount.npub,
|
||||
)
|
||||
|
||||
val signedMessage = thisAccount.signString(intentData.data)
|
||||
if (intentData.checked.value) {
|
||||
if (isChecked) {
|
||||
results.add(
|
||||
Result(
|
||||
null,
|
||||
@@ -471,14 +487,14 @@ fun IntentMultiEventHomeScreen(
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (intentData.rememberType.value != RememberType.NEVER && intentData.checked.value) {
|
||||
if (rememberType != RememberType.NEVER && isChecked) {
|
||||
AmberUtils.acceptOrRejectPermission(
|
||||
application,
|
||||
localKey,
|
||||
intentData.type,
|
||||
null,
|
||||
true,
|
||||
intentData.rememberType.value,
|
||||
rememberType,
|
||||
thisAccount,
|
||||
)
|
||||
}
|
||||
@@ -492,7 +508,7 @@ fun IntentMultiEventHomeScreen(
|
||||
intentData.type.toString(),
|
||||
null,
|
||||
TimeUtils.now(),
|
||||
intentData.checked.value,
|
||||
isChecked,
|
||||
content = if (intentData.type == SignerType.NIP04_DECRYPT || intentData.type == SignerType.NIP44_DECRYPT || intentData.type == SignerType.DECRYPT_ZAP_EVENT) {
|
||||
intentData.encryptedData?.result ?: ""
|
||||
} else {
|
||||
@@ -503,7 +519,7 @@ fun IntentMultiEventHomeScreen(
|
||||
)
|
||||
|
||||
val signature = intentData.encryptedData?.result ?: continue
|
||||
if (intentData.checked.value) {
|
||||
if (isChecked) {
|
||||
results.add(
|
||||
Result(
|
||||
null,
|
||||
@@ -533,7 +549,12 @@ fun IntentMultiEventHomeScreen(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun IntentRequestCard(context: Context, intent: IntentData) {
|
||||
private fun IntentRequestCard(
|
||||
context: Context,
|
||||
intent: IntentData,
|
||||
checked: Boolean,
|
||||
onToggleChecked: () -> Unit,
|
||||
) {
|
||||
val type = intent.type
|
||||
var showDetails by remember { mutableStateOf(false) }
|
||||
val hasDetails = (type == SignerType.SIGN_EVENT && intent.event != null) ||
|
||||
@@ -615,11 +636,11 @@ private fun IntentRequestCard(context: Context, intent: IntentData) {
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { intent.checked.value = !intent.checked.value },
|
||||
.clickable { onToggleChecked() },
|
||||
) {
|
||||
Checkbox(
|
||||
checked = intent.checked.value,
|
||||
onCheckedChange = { intent.checked.value = !intent.checked.value },
|
||||
checked = checked,
|
||||
onCheckedChange = { onToggleChecked() },
|
||||
colors = CheckboxDefaults.colors().copy(
|
||||
uncheckedBorderColor = Color.Gray,
|
||||
),
|
||||
@@ -631,7 +652,7 @@ private fun IntentRequestCard(context: Context, intent: IntentData) {
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
color = if (intent.checked.value) Color.Unspecified else Color.Gray,
|
||||
color = if (checked) Color.Unspecified else Color.Gray,
|
||||
)
|
||||
if (preview.isNotBlank()) {
|
||||
Text(
|
||||
|
||||
@@ -16,6 +16,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import com.greenart7c3.nostrsigner.service.MultiEventScreenIntents
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -66,14 +67,14 @@ fun PermissionCard(
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
acceptEventsGroup[index].value = !acceptEventsGroup[index].value
|
||||
item.second.forEach { it.checked.value = acceptEventsGroup[index].value }
|
||||
item.second.forEach { MultiEventScreenIntents.checkedStates[it.id] = acceptEventsGroup[index].value }
|
||||
},
|
||||
) {
|
||||
Checkbox(
|
||||
checked = acceptEventsGroup[index].value,
|
||||
onCheckedChange = { _ ->
|
||||
acceptEventsGroup[index].value = !acceptEventsGroup[index].value
|
||||
item.second.forEach { it.checked.value = acceptEventsGroup[index].value }
|
||||
item.second.forEach { MultiEventScreenIntents.checkedStates[it.id] = acceptEventsGroup[index].value }
|
||||
},
|
||||
colors = CheckboxDefaults.colors().copy(
|
||||
uncheckedBorderColor = Color.Gray,
|
||||
@@ -134,7 +135,7 @@ fun PermissionCard(
|
||||
)
|
||||
}
|
||||
if (acceptEventsGroup[index].value) {
|
||||
val selected = item.second.filter { it.checked.value }.size
|
||||
val selected = item.second.filter { MultiEventScreenIntents.checkedStates[it.id] ?: true }.size
|
||||
val total = item.second.size
|
||||
Row(
|
||||
Modifier
|
||||
|
||||
Reference in New Issue
Block a user