Put friend and block on one line in the Android client sheet; remove contacts from their page

The client sheet keeps only "Edit contact" for contacts. The contact page's
remove button takes the remove-friend/foe icon instead of the trash can.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-01 08:52:41 +00:00
parent 7f30a27d73
commit f80f619a65
3 changed files with 12 additions and 17 deletions

View File

@@ -156,7 +156,7 @@ private fun ContactScreen(vm: SessionController, uniqueId: String, onBack: () ->
}
SubScreen(label(contact), leave, actions = {
IconButton(onClick = { removing = true }) { PackIcon("DELETE", "Remove from contacts") }
IconButton(onClick = { removing = true }) { PackIcon(if (contact.type == ContactType.BLOCKED) "REMOVE_FOE" else "REMOVE_FRIEND", "Remove from contacts") }
}) { padding ->
Column(Modifier.padding(padding).imePadding().verticalScroll(rememberScrollState()).padding(vertical = 8.dp)) {
OutlinedTextField(customName, { customName = it }, Modifier.fillMaxWidth().padding(horizontal = 16.dp),

View File

@@ -239,7 +239,6 @@ fun ServerScreen(
onAway = { server.setAway(it); clientSheet = null },
onAddContact = { server.addContact(id, it) },
onEditContact = { clientSheet = null; onContacts(client.uniqueId) },
onRemoveContact = { vm.removeContact(client.uniqueId) },
onMove = if (server.canMoveClients) ({ clientSheet = null; moving = id }) else null,
onMoveToOwnChannel = if (server.canMoveClients && tree.channel(state.channelId)?.clients?.none { it.id == id } == true) {
{ server.moveClient(id, state.channelId); clientSheet = null }

View File

@@ -53,7 +53,6 @@ fun ClientSheet(
onAway: (Boolean) -> Unit,
onAddContact: (ContactType) -> Unit,
onEditContact: () -> Unit,
onRemoveContact: () -> Unit,
/** Null when the client cannot be moved. */
onMove: (() -> Unit)?,
/** Null when the client cannot be moved, or is in our channel already. */
@@ -86,20 +85,17 @@ fun ClientSheet(
if (client.self) {
Action("AWAY", if (away) "Back" else "Away") { onAway(!away) }
} else {
Action("PLAYER_CHAT", "Send message", onMessage)
Action("PLAYER_CHAT", "Send message", onClick = onMessage)
Action("POKE", "Poke") { poking = true }
onMove?.let { Action("CHANNEL_SWITCH", "Move to channel…", it) }
onMoveToOwnChannel?.let { Action("MOVE_CLIENT_TO_OWN_CHANNEL", "Move to own channel", it) }
when (client.contactType) {
null -> {
Action("ADD_FRIEND", "Add as friend") { onAddContact(ContactType.FRIEND) }
Action("ADD_FOE", "Block") { onAddContact(ContactType.BLOCKED) }
}
else -> {
Action("EDIT_FRIEND_FOE_STATUS", "Edit contact", onEditContact)
Action(if (client.contactType == ContactType.BLOCKED) "REMOVE_FOE" else "REMOVE_FRIEND",
"Remove from contacts", onRemoveContact)
onMove?.let { Action("CHANNEL_SWITCH", "Move to channel…", onClick = it) }
onMoveToOwnChannel?.let { Action("MOVE_CLIENT_TO_OWN_CHANNEL", "Move to own channel", onClick = it) }
if (client.contactType == null) {
Row {
Action("ADD_FRIEND", "Add as friend", Modifier.weight(1f)) { onAddContact(ContactType.FRIEND) }
Action("ADD_FOE", "Block", Modifier.weight(1f)) { onAddContact(ContactType.BLOCKED) }
}
} else {
Action("EDIT_FRIEND_FOE_STATUS", "Edit contact", onClick = onEditContact)
}
var volume by remember { mutableFloatStateOf(initialVolume.toFloat()) }
Text("Volume: ${if (volume > 0) "+" else ""}${volume.roundToInt()} dB",
@@ -183,12 +179,12 @@ fun ServerSheet(details: Details, onLink: (String) -> Unit, onDismiss: () -> Uni
}
@Composable
private fun Action(iconKey: String, label: String, onClick: () -> Unit) {
private fun Action(iconKey: String, label: String, modifier: Modifier = Modifier.fillMaxWidth(), onClick: () -> Unit) {
ListItem(
headlineContent = { Text(label) },
leadingContent = { PackIcon(iconKey, null) },
colors = ListItemDefaults.colors(containerColor = Color.Transparent),
modifier = Modifier.fillMaxWidth().clickable(onClick = onClick).padding(horizontal = 8.dp),
modifier = modifier.clickable(onClick = onClick).padding(horizontal = 8.dp),
)
}