Add 'Send private message' action to chat user sheet (#649)

* Add 'Send private message' action to chat user sheet

* Change 'Send private message' action color to purple

* Fix: Resolve short ID against all participants, not just cached nicknames

* Fix: Correctly open private chat sheet for mesh peers

---------

Co-authored-by: a1denvalu3 <>
This commit is contained in:
a1denvalu3
2026-03-25 14:45:36 +01:00
committed by GitHub
co-authored by a1denvalu3 <>
parent dac81b2c3b
commit 96b35e957c
5 changed files with 77 additions and 1 deletions
@@ -43,6 +43,20 @@ class GeohashRepository(
}?.key
}
fun findPubkeyByShortId(shortId: String): String? {
// First check cached nicknames (fastest)
var found = geoNicknames.keys.firstOrNull { it.startsWith(shortId, ignoreCase = true) }
if (found != null) return found
// If not found in nicknames (e.g. anon user), check all known participants across all geohashes
for (participants in geohashParticipants.values) {
found = participants.keys.firstOrNull { it.startsWith(shortId, ignoreCase = true) }
if (found != null) return found
}
return null
}
// peerID alias -> nostr pubkey mapping for geohash DMs and temp aliases
private val nostrKeyMapping: MutableMap<String, String> = mutableMapOf()
@@ -40,6 +40,7 @@ fun ChatUserSheet(
val isDark = colorScheme.background.red + colorScheme.background.green + colorScheme.background.blue < 1.5f
val standardGreen = if (isDark) Color(0xFF32D74B) else Color(0xFF248A3D) // iOS green
val standardBlue = Color(0xFF007AFF) // iOS blue
val standardPurple = if (isDark) Color(0xFFBF5AF2) else Color(0xFFAF52DE) // iOS purple
val standardRed = Color(0xFFFF3B30) // iOS red
val standardGrey = if (isDark) Color(0xFF8E8E93) else Color(0xFF6D6D70) // iOS grey
@@ -92,6 +93,33 @@ fun ChatUserSheet(
// Only show user actions for other users' messages or when no message is selected
if (selectedMessage?.sender != viewModel.nickname.value) {
// Send private message action
item {
UserActionRow(
title = stringResource(R.string.action_private_message_title, targetNickname),
subtitle = stringResource(R.string.action_private_message_subtitle),
titleColor = standardPurple,
onClick = {
val selectedLocationChannel = viewModel.selectedLocationChannel.value
if (selectedLocationChannel is com.bitchat.android.geohash.ChannelID.Location) {
if (selectedMessage?.senderPeerID?.startsWith("nostr:") == true) {
val shortId = selectedMessage.senderPeerID!!.substring(6)
viewModel.startGeohashDMByShortId(shortId)
} else {
viewModel.startGeohashDMByNickname(targetNickname)
}
} else {
// Mesh chat
val peerID = selectedMessage?.senderPeerID ?: viewModel.getPeerIDForNickname(targetNickname)
if (peerID != null) {
viewModel.showPrivateChatSheet(peerID)
}
}
onDismiss()
}
)
}
// Slap action
item {
UserActionRow(
@@ -1065,6 +1065,18 @@ class ChatViewModel(
}
}
fun startGeohashDMByNickname(nickname: String) {
geohashViewModel.startGeohashDMByNickname(nickname) { convKey ->
showPrivateChatSheet(convKey)
}
}
fun startGeohashDMByShortId(shortId: String) {
geohashViewModel.startGeohashDMByShortId(shortId) { convKey ->
showPrivateChatSheet(convKey)
}
}
fun selectLocationChannel(channel: com.bitchat.android.geohash.ChannelID) {
geohashViewModel.selectLocationChannel(channel)
}
@@ -282,6 +282,25 @@ class GeohashViewModel(
Log.d(TAG, "🗨️ Started geohash DM with ${pubkeyHex} -> ${convKey} (geohash=${gh})")
}
fun startGeohashDMByNickname(nickname: String, onStartPrivateChat: (String) -> Unit) {
val pubkey = repo.findPubkeyByNickname(nickname)
if (pubkey != null) {
startGeohashDM(pubkey, onStartPrivateChat)
} else {
Log.w(TAG, "Cannot start geohash DM: nickname '$nickname' not found in repo")
// Optionally notify user
}
}
fun startGeohashDMByShortId(shortId: String, onStartPrivateChat: (String) -> Unit) {
val pubkey = repo.findPubkeyByShortId(shortId)
if (pubkey != null) {
startGeohashDM(pubkey, onStartPrivateChat)
} else {
Log.w(TAG, "Cannot start geohash DM: shortId '$shortId' not found in repo")
}
}
fun getNostrKeyMapping(): Map<String, String> = repo.getNostrKeyMapping()
fun blockUserInGeohash(targetNickname: String) {
+4 -1
View File
@@ -201,7 +201,10 @@
<string name="action_hug_title">hug %1$s</string>
<string name="action_hug_subtitle">send a friendly hug message</string>
<string name="action_block_title">block %1$s</string>
<string name="action_block_subtitle">block all messages from this user</string>
<string name="action_block_subtitle">block all messages from this user</string>
<string name="action_private_message_title">message %1$s</string>
<string name="action_private_message_subtitle">send a private message</string>
<!-- Location channels sheet -->
<string name="location_channels_title">#location channels</string>