mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-24 23:45:19 +00:00
fix geohash livedata wiring (#389)
This commit is contained in:
@@ -87,10 +87,8 @@ class NostrGeohashService(
|
|||||||
private var geohashSamplingJob: Job? = null
|
private var geohashSamplingJob: Job? = null
|
||||||
private var geoParticipantsTimer: Job? = null
|
private var geoParticipantsTimer: Job? = null
|
||||||
|
|
||||||
// MARK: - Geohash Message History Properties
|
// MARK: - Geohash Message Routing
|
||||||
|
// Geohash messages are routed through MessageManager channel timelines using key "geo:<geohash>"
|
||||||
private val geohashMessageHistory = mutableMapOf<String, MutableList<BitchatMessage>>() // geohash -> messages
|
|
||||||
private val maxGeohashMessages = 1000 // Maximum messages per geohash
|
|
||||||
|
|
||||||
// MARK: - Location Channel Management Properties
|
// MARK: - Location Channel Management Properties
|
||||||
|
|
||||||
@@ -166,7 +164,6 @@ class NostrGeohashService(
|
|||||||
try {
|
try {
|
||||||
geohashParticipants.clear()
|
geohashParticipants.clear()
|
||||||
geoNicknames.clear()
|
geoNicknames.clear()
|
||||||
geohashMessageHistory.clear()
|
|
||||||
processedNostrEvents.clear()
|
processedNostrEvents.clear()
|
||||||
processedNostrEventOrder.clear()
|
processedNostrEventOrder.clear()
|
||||||
currentGeohashSubscriptionId = null
|
currentGeohashSubscriptionId = null
|
||||||
@@ -258,10 +255,8 @@ class NostrGeohashService(
|
|||||||
powDifficulty = if (powSettingsLocal.enabled) powSettingsLocal.difficulty else null
|
powDifficulty = if (powSettingsLocal.enabled) powSettingsLocal.difficulty else null
|
||||||
)
|
)
|
||||||
|
|
||||||
// Store immediately; UI will display from geohash history (not main mesh timeline)
|
// Local echo into geohash channel timeline via unified MessageManager
|
||||||
storeGeohashMessage(channel.geohash, localMessage)
|
messageManager.addChannelMessage("geo:${channel.geohash}", localMessage)
|
||||||
// IMPORTANT: Do not add to main mesh timeline to avoid duplication in mesh chat view
|
|
||||||
// messageManager.addMessage(localMessage)
|
|
||||||
|
|
||||||
Log.d(TAG, "📝 Added geohash local echo with temp ID: $tempMessageId (not shown in mesh timeline)")
|
Log.d(TAG, "📝 Added geohash local echo with temp ID: $tempMessageId (not shown in mesh timeline)")
|
||||||
|
|
||||||
@@ -692,55 +687,7 @@ class NostrGeohashService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Geohash Message History
|
// Geohash message history is maintained in ChatState.channelMessages; no local cache here
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a message in geohash history
|
|
||||||
*/
|
|
||||||
private fun storeGeohashMessage(geohash: String, message: BitchatMessage) {
|
|
||||||
val messages = geohashMessageHistory.getOrPut(geohash) { mutableListOf() }
|
|
||||||
messages.add(message)
|
|
||||||
|
|
||||||
// Limit message history to prevent memory issues
|
|
||||||
if (messages.size > maxGeohashMessages) {
|
|
||||||
messages.removeAt(0) // Remove oldest message
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.v(TAG, "📦 Stored message in geohash $geohash history (${messages.size} total) - sender: ${message.sender}, content: '${message.content.take(30)}...'")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load stored messages for a geohash channel
|
|
||||||
*/
|
|
||||||
fun loadGeohashMessages(geohash: String) {
|
|
||||||
val storedMessages = geohashMessageHistory[geohash]
|
|
||||||
if (storedMessages == null) {
|
|
||||||
Log.d(TAG, "📥 No stored messages found for geohash $geohash")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d(TAG, "📥 Loading ${storedMessages.size} stored messages for geohash $geohash")
|
|
||||||
|
|
||||||
// Add all stored messages to the current message timeline
|
|
||||||
storedMessages.forEach { message ->
|
|
||||||
Log.v(TAG, "📥 Loading stored message: ${message.sender} - '${message.content.take(30)}...'")
|
|
||||||
messageManager.addMessage(message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get stored messages for a geohash without mutating UI state
|
|
||||||
*/
|
|
||||||
fun getGeohashMessages(geohash: String): List<BitchatMessage> {
|
|
||||||
return geohashMessageHistory[geohash]?.toList() ?: emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear geohash message history
|
|
||||||
*/
|
|
||||||
fun clearGeohashMessageHistory() {
|
|
||||||
geohashMessageHistory.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Geohash Participant Tracking
|
// MARK: - Geohash Participant Tracking
|
||||||
|
|
||||||
@@ -994,8 +941,7 @@ class NostrGeohashService(
|
|||||||
private fun switchLocationChannel(channel: com.bitchat.android.geohash.ChannelID?) {
|
private fun switchLocationChannel(channel: com.bitchat.android.geohash.ChannelID?) {
|
||||||
// STEP 1: Immediate UI updates (synchronous, no blocking)
|
// STEP 1: Immediate UI updates (synchronous, no blocking)
|
||||||
try {
|
try {
|
||||||
// NOTE: Don't clear messages here - let ChatScreen's displayMessages logic handle what to show
|
// Do not clear messages here - preserve mesh history when switching between views
|
||||||
// This preserves mesh message history when switching between views
|
|
||||||
|
|
||||||
when (channel) {
|
when (channel) {
|
||||||
is com.bitchat.android.geohash.ChannelID.Mesh -> {
|
is com.bitchat.android.geohash.ChannelID.Mesh -> {
|
||||||
@@ -1020,7 +966,10 @@ class NostrGeohashService(
|
|||||||
// Clear notifications for this geohash since user is now viewing it
|
// Clear notifications for this geohash since user is now viewing it
|
||||||
notificationManager.clearNotificationsForGeohash(channel.channel.geohash)
|
notificationManager.clearNotificationsForGeohash(channel.channel.geohash)
|
||||||
// Note: Don't clear geoNicknames - they contain cached nicknames for all geohashes
|
// Note: Don't clear geoNicknames - they contain cached nicknames for all geohashes
|
||||||
// Note: Don't load messages here - ChatScreen will get them via getGeohashMessages()
|
// Clear unread for this geohash since user is now viewing it
|
||||||
|
try {
|
||||||
|
messageManager.clearChannelUnreadCount("geo:${channel.channel.geohash}")
|
||||||
|
} catch (_: Exception) { }
|
||||||
|
|
||||||
// Immediate self-registration for instant UI feedback
|
// Immediate self-registration for instant UI feedback
|
||||||
try {
|
try {
|
||||||
@@ -1300,11 +1249,8 @@ class NostrGeohashService(
|
|||||||
powDifficulty = actualPow.takeIf { it > 0 && eventHasNonseTag } ?: null
|
powDifficulty = actualPow.takeIf { it > 0 && eventHasNonseTag } ?: null
|
||||||
)
|
)
|
||||||
|
|
||||||
// Store in geohash history for persistence across channel switches
|
// Add to geohash channel timeline (unified pipeline)
|
||||||
storeGeohashMessage(geohash, message)
|
withContext(Dispatchers.Main) { messageManager.addChannelMessage("geo:$geohash", message) }
|
||||||
|
|
||||||
// NOTE: Don't add to main message timeline here - ChatScreen will display geohash messages
|
|
||||||
// from the separate geohash history via getGeohashMessages()
|
|
||||||
|
|
||||||
// NOTIFICATION LOGIC: Check for mentions and first messages
|
// NOTIFICATION LOGIC: Check for mentions and first messages
|
||||||
checkAndTriggerGeohashNotifications(geohash, senderName, content, message)
|
checkAndTriggerGeohashNotifications(geohash, senderName, content, message)
|
||||||
@@ -1403,8 +1349,9 @@ class NostrGeohashService(
|
|||||||
* Check if this is the first message in a subscribed geohash chat
|
* Check if this is the first message in a subscribed geohash chat
|
||||||
*/
|
*/
|
||||||
private fun checkIfFirstMessage(geohash: String, message: BitchatMessage): Boolean {
|
private fun checkIfFirstMessage(geohash: String, message: BitchatMessage): Boolean {
|
||||||
// Get the message history for this geohash
|
// Use ChatState.channelMessages for geohash history
|
||||||
val messageHistory = geohashMessageHistory[geohash] ?: return true
|
val channelKey = "geo:$geohash"
|
||||||
|
val messageHistory = state.getChannelMessagesValue()[channelKey] ?: emptyList()
|
||||||
|
|
||||||
// Filter out our own messages (local echoes and messages from our identity)
|
// Filter out our own messages (local echoes and messages from our identity)
|
||||||
val otherUserMessages = messageHistory.filter { msg ->
|
val otherUserMessages = messageHistory.filter { msg ->
|
||||||
|
|||||||
@@ -74,18 +74,17 @@ fun ChatScreen(viewModel: ChatViewModel) {
|
|||||||
// Get location channel info for timeline switching
|
// Get location channel info for timeline switching
|
||||||
val selectedLocationChannel by viewModel.selectedLocationChannel.observeAsState()
|
val selectedLocationChannel by viewModel.selectedLocationChannel.observeAsState()
|
||||||
|
|
||||||
// Determine what messages to show based on current context
|
// Determine what messages to show based on current context (unified timelines)
|
||||||
val displayMessages = when {
|
val displayMessages = when {
|
||||||
selectedPrivatePeer != null -> privateChats[selectedPrivatePeer] ?: emptyList()
|
selectedPrivatePeer != null -> privateChats[selectedPrivatePeer] ?: emptyList()
|
||||||
currentChannel != null -> channelMessages[currentChannel] ?: emptyList()
|
currentChannel != null -> channelMessages[currentChannel] ?: emptyList()
|
||||||
else -> {
|
else -> {
|
||||||
val locationChannel = selectedLocationChannel
|
val locationChannel = selectedLocationChannel
|
||||||
if (locationChannel is com.bitchat.android.geohash.ChannelID.Location) {
|
if (locationChannel is com.bitchat.android.geohash.ChannelID.Location) {
|
||||||
// For geohash channels, get messages from geohash history
|
val geokey = "geo:${locationChannel.channel.geohash}"
|
||||||
val geohash = locationChannel.channel.geohash
|
channelMessages[geokey] ?: emptyList()
|
||||||
viewModel.getGeohashMessages(geohash)
|
|
||||||
} else {
|
} else {
|
||||||
messages // Mesh/public messages
|
messages // Mesh timeline
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -649,13 +649,6 @@ class ChatViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get messages for a specific geohash timeline
|
|
||||||
*/
|
|
||||||
fun getGeohashMessages(geohash: String): List<BitchatMessage> {
|
|
||||||
return nostrGeohashService.getGeohashMessages(geohash)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get participant count for a specific geohash (5-minute activity window)
|
* Get participant count for a specific geohash (5-minute activity window)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -52,8 +52,18 @@ class MessageManager(private val state: ChatState) {
|
|||||||
currentChannelMessages[channel] = channelMessageList
|
currentChannelMessages[channel] = channelMessageList
|
||||||
state.setChannelMessages(currentChannelMessages)
|
state.setChannelMessages(currentChannelMessages)
|
||||||
|
|
||||||
// Update unread count if not currently in this channel
|
// Update unread count if not currently viewing this channel
|
||||||
if (state.getCurrentChannelValue() != channel) {
|
// Consider both classic channels (state.currentChannel) and geohash location channel selection
|
||||||
|
val viewingClassicChannel = state.getCurrentChannelValue() == channel
|
||||||
|
val viewingGeohashChannel = try {
|
||||||
|
if (channel.startsWith("geo:")) {
|
||||||
|
val geo = channel.removePrefix("geo:")
|
||||||
|
val selected = state.selectedLocationChannel.value
|
||||||
|
selected is com.bitchat.android.geohash.ChannelID.Location && selected.channel.geohash.equals(geo, ignoreCase = true)
|
||||||
|
} else false
|
||||||
|
} catch (_: Exception) { false }
|
||||||
|
|
||||||
|
if (!viewingClassicChannel && !viewingGeohashChannel) {
|
||||||
val currentUnread = state.getUnreadChannelMessagesValue().toMutableMap()
|
val currentUnread = state.getUnreadChannelMessagesValue().toMutableMap()
|
||||||
currentUnread[channel] = (currentUnread[channel] ?: 0) + 1
|
currentUnread[channel] = (currentUnread[channel] ?: 0) + 1
|
||||||
state.setUnreadChannelMessages(currentUnread)
|
state.setUnreadChannelMessages(currentUnread)
|
||||||
|
|||||||
Reference in New Issue
Block a user