mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-24 23:25:19 +00:00
nostr: fix block feature (#427)
* fix block feature * fix nostr nickname in sidebar
This commit is contained in:
@@ -22,7 +22,8 @@ class GeohashMessageHandler(
|
||||
private val state: ChatState,
|
||||
private val messageManager: MessageManager,
|
||||
private val repo: GeohashRepository,
|
||||
private val scope: CoroutineScope
|
||||
private val scope: CoroutineScope,
|
||||
private val dataManager: com.bitchat.android.ui.DataManager
|
||||
) {
|
||||
companion object { private const val TAG = "GeohashMessageHandler" }
|
||||
|
||||
@@ -56,8 +57,8 @@ class GeohashMessageHandler(
|
||||
if (!NostrProofOfWork.validateDifficulty(event, pow.difficulty)) return@launch
|
||||
}
|
||||
|
||||
// Blocked users check
|
||||
if (com.bitchat.android.ui.DataManager(application).isGeohashUserBlocked(event.pubkey)) return@launch
|
||||
// Blocked users check (use injected DataManager which has loaded state)
|
||||
if (dataManager.isGeohashUserBlocked(event.pubkey)) return@launch
|
||||
|
||||
// Update repository (participants, nickname, teleport)
|
||||
// Update repository on a background-safe path; repository will post updates to LiveData
|
||||
|
||||
@@ -14,7 +14,8 @@ import java.util.Date
|
||||
*/
|
||||
class GeohashRepository(
|
||||
private val application: Application,
|
||||
private val state: ChatState
|
||||
private val state: ChatState,
|
||||
private val dataManager: com.bitchat.android.ui.DataManager
|
||||
) {
|
||||
companion object { private const val TAG = "GeohashRepository" }
|
||||
|
||||
@@ -103,7 +104,8 @@ class GeohashRepository(
|
||||
val e = it.next()
|
||||
if (e.value.before(cutoff)) it.remove()
|
||||
}
|
||||
return participants.size
|
||||
// exclude blocked users
|
||||
return participants.keys.count { !dataManager.isGeohashUserBlocked(it) }
|
||||
}
|
||||
|
||||
fun refreshGeohashPeople() {
|
||||
@@ -122,8 +124,18 @@ class GeohashRepository(
|
||||
if (e.value.before(cutoff)) it.remove()
|
||||
}
|
||||
geohashParticipants[geohash] = participants
|
||||
val people = participants.map { (pubkeyHex, lastSeen) ->
|
||||
val base = getCachedNickname(pubkeyHex) ?: "anon"
|
||||
// exclude blocked users from people list
|
||||
val people = participants.filterKeys { !dataManager.isGeohashUserBlocked(it) }
|
||||
.map { (pubkeyHex, lastSeen) ->
|
||||
// Use our actual nickname for self; otherwise use cached nickname or anon
|
||||
val base = try {
|
||||
val myHex = currentGeohash?.let { NostrIdentityBridge.deriveIdentity(it, application).publicKeyHex }
|
||||
if (myHex != null && myHex.equals(pubkeyHex, true)) {
|
||||
state.getNicknameValue() ?: "anon"
|
||||
} else {
|
||||
getCachedNickname(pubkeyHex) ?: "anon"
|
||||
}
|
||||
} catch (_: Exception) { getCachedNickname(pubkeyHex) ?: "anon" }
|
||||
GeoPerson(
|
||||
id = pubkeyHex.lowercase(),
|
||||
displayName = base, // UI can add #hash if necessary
|
||||
@@ -138,7 +150,8 @@ class GeohashRepository(
|
||||
val cutoff = Date(System.currentTimeMillis() - 5 * 60 * 1000)
|
||||
val counts = mutableMapOf<String, Int>()
|
||||
for ((gh, participants) in geohashParticipants) {
|
||||
val active = participants.values.count { !it.before(cutoff) }
|
||||
val active = participants.filterKeys { !dataManager.isGeohashUserBlocked(it) }
|
||||
.values.count { !it.before(cutoff) }
|
||||
counts[gh] = active
|
||||
}
|
||||
// Use postValue for thread safety - this can be called from background threads
|
||||
@@ -186,6 +199,7 @@ class GeohashRepository(
|
||||
val participants = geohashParticipants[current] ?: emptyMap()
|
||||
var count = 0
|
||||
for ((k, t) in participants) {
|
||||
if (dataManager.isGeohashUserBlocked(k)) continue
|
||||
if (t.before(cutoff)) continue
|
||||
val name = if (k.equals(lower, true)) base else (geoNicknames[k.lowercase()] ?: "anon")
|
||||
if (name.equals(base, true)) { count++; if (count > 1) break }
|
||||
@@ -207,6 +221,7 @@ class GeohashRepository(
|
||||
val participants = geohashParticipants[sourceGeohash] ?: emptyMap()
|
||||
var count = 0
|
||||
for ((k, t) in participants) {
|
||||
if (dataManager.isGeohashUserBlocked(k)) continue
|
||||
if (t.before(cutoff)) continue
|
||||
val name = if (k.equals(lower, true)) base else (geoNicknames[k.lowercase()] ?: "anon")
|
||||
if (name.equals(base, true)) { count++; if (count > 1) break }
|
||||
|
||||
@@ -21,7 +21,8 @@ class NostrDirectMessageHandler(
|
||||
private val privateChatManager: PrivateChatManager,
|
||||
private val meshDelegateHandler: MeshDelegateHandler,
|
||||
private val scope: CoroutineScope,
|
||||
private val repo: GeohashRepository
|
||||
private val repo: GeohashRepository,
|
||||
private val dataManager: com.bitchat.android.ui.DataManager
|
||||
) {
|
||||
companion object { private const val TAG = "NostrDirectMessageHandler" }
|
||||
|
||||
@@ -58,6 +59,10 @@ class NostrDirectMessageHandler(
|
||||
}
|
||||
|
||||
val (content, senderPubkey, rumorTimestamp) = decryptResult
|
||||
|
||||
// If sender is blocked for geohash contexts, drop any events from this pubkey
|
||||
// Applies to both geohash DMs (geohash != "") and account DMs (geohash == "")
|
||||
if (dataManager.isGeohashUserBlocked(senderPubkey)) return@launch
|
||||
if (!content.startsWith("bitchat1:")) return@launch
|
||||
|
||||
val base64Content = content.removePrefix("bitchat1:")
|
||||
|
||||
@@ -415,7 +415,7 @@ fun AboutSheet(
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text("Tor On", fontFamily = FontFamily.Monospace)
|
||||
Text("tor on", fontFamily = FontFamily.Monospace)
|
||||
val statusColor = when {
|
||||
torStatus.running && torStatus.bootstrapPercent < 100 -> Color(0xFFFF9500)
|
||||
torStatus.running && torStatus.bootstrapPercent >= 100 -> if (isDark) Color(0xFF32D74B) else Color(0xFF248A3D)
|
||||
|
||||
@@ -30,10 +30,25 @@ class GeohashViewModel(
|
||||
|
||||
companion object { private const val TAG = "GeohashViewModel" }
|
||||
|
||||
private val repo = GeohashRepository(application, state)
|
||||
private val repo = GeohashRepository(application, state, dataManager)
|
||||
private val subscriptionManager = NostrSubscriptionManager(application, viewModelScope)
|
||||
private val geohashMessageHandler = GeohashMessageHandler(application, state, messageManager, repo, viewModelScope)
|
||||
private val dmHandler = NostrDirectMessageHandler(application, state, privateChatManager, meshDelegateHandler, viewModelScope, repo)
|
||||
private val geohashMessageHandler = GeohashMessageHandler(
|
||||
application = application,
|
||||
state = state,
|
||||
messageManager = messageManager,
|
||||
repo = repo,
|
||||
scope = viewModelScope,
|
||||
dataManager = dataManager
|
||||
)
|
||||
private val dmHandler = NostrDirectMessageHandler(
|
||||
application = application,
|
||||
state = state,
|
||||
privateChatManager = privateChatManager,
|
||||
meshDelegateHandler = meshDelegateHandler,
|
||||
scope = viewModelScope,
|
||||
repo = repo,
|
||||
dataManager = dataManager
|
||||
)
|
||||
|
||||
private var currentGeohashSubId: String? = null
|
||||
private var currentDmSubId: String? = null
|
||||
@@ -141,25 +156,6 @@ class GeohashViewModel(
|
||||
fun geohashParticipantCount(geohash: String): Int = repo.geohashParticipantCount(geohash)
|
||||
fun isPersonTeleported(pubkeyHex: String): Boolean = repo.isPersonTeleported(pubkeyHex)
|
||||
|
||||
fun startGeohashDM(pubkeyHex: String, onStartPrivateChat: (String) -> Unit) {
|
||||
val convKey = "nostr_${pubkeyHex.take(16)}"
|
||||
repo.putNostrKeyMapping(convKey, pubkeyHex)
|
||||
onStartPrivateChat(convKey)
|
||||
Log.d(TAG, "🗨️ Started geohash DM with $pubkeyHex -> $convKey")
|
||||
}
|
||||
|
||||
fun getNostrKeyMapping(): Map<String, String> = repo.getNostrKeyMapping()
|
||||
|
||||
fun blockUserInGeohash(targetNickname: String) {
|
||||
val pubkey = repo.findPubkeyByNickname(targetNickname)
|
||||
if (pubkey != null) {
|
||||
dataManager.addGeohashBlockedUser(pubkey)
|
||||
val sysMsg = com.bitchat.android.model.BitchatMessage(
|
||||
sender = "system",
|
||||
content = "blocked $targetNickname in geohash channels",
|
||||
timestamp = Date(),
|
||||
isRelay = false
|
||||
)
|
||||
fun startGeohashDM(pubkeyHex: String, onStartPrivateChat: (String) -> Unit) {
|
||||
val convKey = "nostr_${pubkeyHex.take(16)}"
|
||||
repo.putNostrKeyMapping(convKey, pubkeyHex)
|
||||
@@ -174,6 +170,21 @@ class GeohashViewModel(
|
||||
Log.d(TAG, "🗨️ Started geohash DM with ${pubkeyHex} -> ${convKey} (geohash=${gh})")
|
||||
}
|
||||
|
||||
fun getNostrKeyMapping(): Map<String, String> = repo.getNostrKeyMapping()
|
||||
|
||||
fun blockUserInGeohash(targetNickname: String) {
|
||||
val pubkey = repo.findPubkeyByNickname(targetNickname)
|
||||
if (pubkey != null) {
|
||||
dataManager.addGeohashBlockedUser(pubkey)
|
||||
// Refresh people list and counts to remove blocked entry immediately
|
||||
repo.refreshGeohashPeople()
|
||||
repo.updateReactiveParticipantCounts()
|
||||
val sysMsg = com.bitchat.android.model.BitchatMessage(
|
||||
sender = "system",
|
||||
content = "blocked $targetNickname in geohash channels",
|
||||
timestamp = Date(),
|
||||
isRelay = false
|
||||
)
|
||||
messageManager.addMessage(sysMsg)
|
||||
} else {
|
||||
val sysMsg = com.bitchat.android.model.BitchatMessage(
|
||||
|
||||
Reference in New Issue
Block a user