chore: confirm before delete contact #35

Merged
reya merged 2 commits from improve-contact-screen into master 2026-07-03 09:09:58 +00:00
2 changed files with 78 additions and 35 deletions
Showing only changes of commit 1f76f15b8a - Show all commits

View File

@@ -3,11 +3,15 @@ package su.reya.coop.screens
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
@@ -20,6 +24,7 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.SegmentedListItem
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
@@ -54,6 +59,7 @@ import kotlinx.coroutines.launch
import org.jetbrains.compose.resources.painterResource
import rust.nostr.sdk.Nip05Address
import rust.nostr.sdk.PublicKey
import su.reya.coop.LocalChatViewModel
import su.reya.coop.LocalNavigator
import su.reya.coop.LocalNostrViewModel
import su.reya.coop.LocalSnackbarHostState
@@ -67,9 +73,11 @@ fun ContactListScreen() {
val navigator = LocalNavigator.current
val snackbarHostState = LocalSnackbarHostState.current
val nostrViewModel = LocalNostrViewModel.current
val chatViewModel = LocalChatViewModel.current
val contactList by nostrViewModel.contactList.collectAsStateWithLifecycle()
var openAddContactDialog by remember { mutableStateOf(false) }
var contactToDelete by remember { mutableStateOf<PublicKey?>(null) }
Scaffold(
containerColor = MaterialTheme.colorScheme.surfaceContainer,
@@ -128,24 +136,36 @@ fun ContactListScreen() {
}
},
content = { innerPadding ->
Column(
if (contactList.isNotEmpty()) {
val contacts = remember(contactList) { contactList.toList() }
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.padding(innerPadding),
.fillMaxSize()
.padding(top = innerPadding.calculateTopPadding()),
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.spacedBy(ListItemDefaults.SegmentedGap),
) {
if (contactList.isNotEmpty()) {
contactList.forEachIndexed { index, pubkey ->
itemsIndexed(contacts) { index, pubkey ->
ContactListItem(
pubkey = pubkey,
index = index,
total = contactList.size,
onClick = {})
total = contacts.size,
onClick = {
val room = chatViewModel.createChatRoom(listOf(pubkey))
navigator.navigate(Screen.Chat(room))
},
onLongClick = {
contactToDelete = pubkey
}
)
}
}
} else {
Box(
modifier = Modifier.fillMaxSize(),
modifier = Modifier
.fillMaxSize()
.padding(innerPadding),
contentAlignment = Alignment.Center
) {
Column(
@@ -168,12 +188,34 @@ fun ContactListScreen() {
}
}
}
}
)
if (openAddContactDialog) {
AddContactDialog(onDismissRequest = { openAddContactDialog = false })
}
if (contactToDelete != null) {
AlertDialog(
onDismissRequest = { contactToDelete = null },
title = { Text("Delete Contact") },
text = { Text("Are you sure you want to remove this contact?") },
confirmButton = {
TextButton(
onClick = {
contactToDelete?.let { nostrViewModel.removeContact(it) }
contactToDelete = null
}
) {
Text("Delete")
}
},
dismissButton = {
TextButton(onClick = { contactToDelete = null }) {
Text("Cancel")
}
}
)
}
}
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@@ -282,6 +324,7 @@ fun ContactListItem(
index: Int,
total: Int = 0,
onClick: () -> Unit,
onLongClick: () -> Unit,
) {
val nostrViewModel = LocalNostrViewModel.current
val profileFlow = remember(pubkey) { nostrViewModel.getMetadata(pubkey) }
@@ -289,7 +332,7 @@ fun ContactListItem(
SegmentedListItem(
onClick = onClick,
onLongClick = { nostrViewModel.removeContact(pubkey) },
onLongClick = onLongClick,
shapes = ListItemDefaults.segmentedShapes(
index = index,
count = total

View File

@@ -130,7 +130,7 @@ class MessageManager(private val nostr: Nostr) {
val filter = Filter().identifier(giftId.toHex())
val event = client?.database()?.query(filter)?.first()
return event?.content()?.let { UnsignedEvent.fromJson(it) }
return event?.content()?.let { UnsignedEvent.fromJson(it).ensureId() }
} catch (e: Throwable) {
throw IllegalStateException("Failed to get cached rumor: ${e.message}", e)
}