mirror of
https://github.com/greenart7c3/Amber.git
synced 2026-10-05 19:08:23 +00:00
Make request groups collapsible, collapsed by default
Group headers in the multi-request approval screens now expand and collapse their items. Tapping the header row toggles expansion (with a rotating chevron); the tri-state checkbox still selects or deselects the whole group without expanding it. Groups start collapsed so a large batch reads as a short summary. A homogeneous batch (single group) has no header and stays fully visible as before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TioEdhZRp9W78DbsHzEypZ
This commit is contained in:
+19
-10
@@ -21,6 +21,7 @@ import androidx.compose.material3.TriStateCheckbox
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
@@ -161,10 +162,12 @@ fun BunkerMultiEventHomeScreen(
|
||||
)
|
||||
}
|
||||
}
|
||||
val expandedGroups = remember { mutableStateMapOf<RequestGroupKey, Boolean>() }
|
||||
LazyColumn(
|
||||
Modifier.weight(1f),
|
||||
) {
|
||||
groups.forEach { (groupKey, groupItems) ->
|
||||
val expanded = groups.size == 1 || (expandedGroups[groupKey] ?: false)
|
||||
if (groups.size > 1) {
|
||||
item(key = "group-header:${groupKey.type.name}:${groupKey.payload?.name ?: ""}:${groupKey.kind ?: ""}") {
|
||||
val groupState = when {
|
||||
@@ -176,23 +179,29 @@ fun BunkerMultiEventHomeScreen(
|
||||
label = groupKey.toLabel(context),
|
||||
count = groupItems.size,
|
||||
state = groupState,
|
||||
expanded = expanded,
|
||||
onToggle = {
|
||||
val newValue = groupState != ToggleableState.On
|
||||
MultiEventScreenIntents.checkedStates.putAll(groupItems.associate { it.request.id to newValue })
|
||||
},
|
||||
onExpandToggle = {
|
||||
expandedGroups[groupKey] = !(expandedGroups[groupKey] ?: false)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
items(groupItems, key = { it.request.id }) { 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
|
||||
},
|
||||
)
|
||||
if (expanded) {
|
||||
items(groupItems, key = { it.request.id }) { 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
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-10
@@ -23,6 +23,7 @@ import androidx.compose.material3.TriStateCheckbox
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
@@ -127,10 +128,12 @@ fun IntentMultiEventHomeScreen(
|
||||
requestGroupKey(it.type, it.event?.kind, it.encryptedData, it.nip44v3Kind)
|
||||
}
|
||||
}
|
||||
val expandedGroups = remember { mutableStateMapOf<RequestGroupKey, Boolean>() }
|
||||
LazyColumn(
|
||||
Modifier.weight(1f),
|
||||
) {
|
||||
groups.forEach { (groupKey, groupIntents) ->
|
||||
val expanded = groups.size == 1 || (expandedGroups[groupKey] ?: false)
|
||||
if (groups.size > 1) {
|
||||
item(key = "group-header:${groupKey.type.name}:${groupKey.payload?.name ?: ""}:${groupKey.kind ?: ""}") {
|
||||
val groupState = when {
|
||||
@@ -142,23 +145,29 @@ fun IntentMultiEventHomeScreen(
|
||||
label = groupKey.toLabel(context),
|
||||
count = groupIntents.size,
|
||||
state = groupState,
|
||||
expanded = expanded,
|
||||
onToggle = {
|
||||
val newValue = groupState != ToggleableState.On
|
||||
MultiEventScreenIntents.checkedStates.putAll(groupIntents.associate { it.id to newValue })
|
||||
},
|
||||
onExpandToggle = {
|
||||
expandedGroups[groupKey] = !(expandedGroups[groupKey] ?: false)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
items(groupIntents, key = { it.id }) { 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
|
||||
},
|
||||
)
|
||||
if (expanded) {
|
||||
items(groupIntents, key = { it.id }) { 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
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
package com.greenart7c3.nostrsigner.ui.components
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ExpandMore
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TriStateCheckbox
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.state.ToggleableState
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.greenart7c3.nostrsigner.R
|
||||
import com.greenart7c3.nostrsigner.models.ClearTextEncryptedDataKind
|
||||
import com.greenart7c3.nostrsigner.models.EncryptedDataKind
|
||||
@@ -106,13 +114,19 @@ fun RequestGroupHeader(
|
||||
label: String,
|
||||
count: Int,
|
||||
state: ToggleableState,
|
||||
expanded: Boolean,
|
||||
onToggle: () -> Unit,
|
||||
onExpandToggle: () -> Unit,
|
||||
) {
|
||||
val rotation by animateFloatAsState(
|
||||
targetValue = if (expanded) 180f else 0f,
|
||||
label = "group header chevron rotation",
|
||||
)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onToggle() },
|
||||
.clickable { onExpandToggle() },
|
||||
) {
|
||||
TriStateCheckbox(
|
||||
state = state,
|
||||
@@ -121,6 +135,14 @@ fun RequestGroupHeader(
|
||||
Text(
|
||||
text = "$label ($count)",
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.Default.ExpandMore,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(end = 12.dp)
|
||||
.rotate(rotation),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user