add verify contact steps

This commit is contained in:
2026-06-18 09:47:05 +07:00
parent 31a20122d3
commit 7a31749b4f
3 changed files with 86 additions and 1 deletions

View File

@@ -85,6 +85,8 @@ fun ProfileScreen(pubkey: String, screening: Boolean = false) {
var addressVerified by remember { mutableStateOf(false) }
var lastActivity by remember { mutableStateOf<Timestamp?>(null) }
var isContact by remember { mutableStateOf(false) }
var mutualContacts by remember { mutableStateOf<Set<PublicKey>>(emptySet()) }
LaunchedEffect(screening) {
if (screening) {
@@ -95,6 +97,10 @@ fun ProfileScreen(pubkey: String, screening: Boolean = false) {
}
// Get the last activity
viewModel.verifyActivity(pubkey)?.let { lastActivity = it }
// Check contact
viewModel.verifyContact(pubkey).let { isContact = it }
// Get mutual contacts
viewModel.mutualContacts(pubkey).let { mutualContacts = it }
}
}
}

View File

@@ -296,7 +296,11 @@ class Nostr {
if (event.kind().asStd()?.equals(KindStandard.CONTACT_LIST) == true) {
if (isSignedByUser(event = event)) {
onContactListUpdate(event.tags().publicKeys())
val pubkeys = event.tags().publicKeys();
// Get mutual contacts
getMutualContacts(pubkeys)
// Emit contact list update
onContactListUpdate(pubkeys)
}
}
@@ -313,6 +317,7 @@ class Nostr {
// Logic to notify UI after processing
// Cancel previous tracker if it exists
eoseTrackerJob?.cancel()
// Start a new tracker
eoseTrackerJob = launch {
delay(10000.milliseconds) // Wait for 10 seconds
@@ -360,6 +365,27 @@ class Nostr {
}
}
private suspend fun getMutualContacts(pubkeys: List<PublicKey>) {
try {
val kind = Kind.fromStd(KindStandard.CONTACT_LIST);
val filter = Filter().kind(kind).authors(pubkeys).limit(200u)
val opts = SubscribeAutoCloseOptions().exitPolicy(ReqExitPolicy.ExitOnEose)
val target = mutableMapOf<RelayUrl, List<Filter>>()
NostrManager.BOOTSTRAP_RELAYS.forEach { relay ->
target[RelayUrl.parse(relay)] = listOf(filter)
}
client?.subscribe(
target = ReqTarget.manual(target),
id = "mutual-contacts",
closeOn = opts,
)
} catch (e: Exception) {
throw IllegalStateException("Failed to fetch mutual contacts: ${e.message}", e)
}
}
private suspend fun getCachedRumor(giftId: EventId): UnsignedEvent? {
try {
val filter = Filter().identifier(giftId.toHex())
@@ -977,4 +1003,39 @@ class Nostr {
throw IllegalStateException("Failed to get latest activity: ${e.message}", e)
}
}
suspend fun verifyContact(pubkey: PublicKey): Boolean {
try {
val kind = Kind.fromStd(KindStandard.CONTACT_LIST)
val filter = Filter().kind(kind).author(pubkey).limit(1u)
val events = client?.database()?.query(filter)
val pubkeys = events?.first()?.tags()?.publicKeys() ?: listOf()
return pubkeys.contains(pubkey)
} catch (e: Exception) {
throw IllegalStateException("Failed to get mutual contacts: ${e.message}", e)
}
}
suspend fun mutualContacts(pubkey: PublicKey): Set<PublicKey> {
try {
val currentUser =
signer.getPublicKeyAsync() ?: throw IllegalStateException("User not signed in")
val kind = Kind.fromStd(KindStandard.CONTACT_LIST)
val filter = Filter().kind(kind).pubkey(pubkey).limit(1u)
val events = client?.database()?.query(filter)
val contacts = mutableSetOf<PublicKey>()
events?.toVec()?.filter { it.author() != currentUser }?.forEach { event ->
contacts.add(event.author())
}
return contacts.toSet()
} catch (e: Exception) {
throw IllegalStateException("Failed to get mutual contacts: ${e.message}", e)
}
}
}

View File

@@ -839,6 +839,24 @@ class NostrViewModel(
null
}
}
suspend fun verifyContact(pubkey: PublicKey): Boolean {
return try {
nostr.verifyContact(pubkey)
} catch (e: Exception) {
showError("Error: ${e.message}")
false
}
}
suspend fun mutualContacts(pubkey: PublicKey): Set<PublicKey> {
return try {
nostr.mutualContacts(pubkey)
} catch (e: Exception) {
showError("Error: ${e.message}")
setOf()
}
}
}
fun PublicKey.short(): String {