Skip to content

Commit 76f49e1

Browse files
DROID-4057 Chat preview | History of latest messages (#2961)
1 parent 154b72c commit 76f49e1

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

app/src/main/java/com/anytypeio/anytype/ui/vault/VaultChatCard.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ fun VaultChatSpaceCard(
181181
modifier = Modifier
182182
.fillMaxWidth()
183183
.padding(start = 12.dp),
184-
title = title,
184+
title = title.ifEmpty { stringResource(id = R.string.untitled) },
185185
subtitle = messageText ?: chatPreview?.message?.content?.text.orEmpty(),
186186
creatorName = creatorName,
187187
messageText = messageText,

domain/src/main/java/com/anytypeio/anytype/domain/chats/ChatPreviewContainer.kt

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.anytypeio.anytype.domain.debugging.Logger
1212
import com.anytypeio.anytype.domain.library.StoreSearchByIdsParams
1313
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
1414
import java.util.concurrent.ConcurrentHashMap
15+
import java.util.concurrent.ConcurrentLinkedDeque
1516
import javax.inject.Inject
1617
import kotlinx.coroutines.CoroutineScope
1718
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -76,6 +77,9 @@ interface ChatPreviewContainer {
7677
private val previews = MutableStateFlow<List<Chat.Preview>?>(null)
7778
private val attachmentIds = MutableStateFlow<Map<SpaceId, Set<Id>>>(emptyMap())
7879

80+
// Buffer of last N preview messages per chat for fallback on deletion (thread-safe)
81+
private val messageHistory = ConcurrentHashMap<Id, ConcurrentLinkedDeque<Chat.Message>>()
82+
7983
// Hot shared state for UI collectors
8084
@OptIn(ExperimentalCoroutinesApi::class)
8185
private val previewsState: StateFlow<PreviewState> = previews
@@ -115,13 +119,22 @@ interface ChatPreviewContainer {
115119

116120
attachmentIds.value = emptyMap() // Reset attachment tracking
117121
previews.value = null // Reset previews
122+
messageHistory.clear() // Reset message history
118123

119124
val initial = runCatching {
120125
repo.subscribeToMessagePreviews(SUBSCRIPTION_ID)
121126
}.onFailure {
122127
logger.logWarning("Error while getting initial previews: ${it.message}")
123128
}.getOrDefault(emptyList())
124129

130+
// Initialize history from initial previews
131+
initial.forEach { preview ->
132+
preview.message?.let { message ->
133+
val history = messageHistory.getOrPut(preview.chat) { ConcurrentLinkedDeque() }
134+
history.addLast(message)
135+
}
136+
}
137+
125138
previews.value = initial // ← Ready (may be empty)
126139
trackMissingAttachments(initial)
127140
collectEvents(initial)
@@ -133,6 +146,7 @@ interface ChatPreviewContainer {
133146
job?.cancel()
134147
job = null
135148
previews.value = null // back to Loading for next start()
149+
messageHistory.clear() // clear message history
136150
unsubscribeAll()
137151
attachmentFlows.clear() // let the cached StateFlows be GC-ed
138152
}
@@ -200,7 +214,11 @@ interface ChatPreviewContainer {
200214

201215
is Event.Command.Chats.Delete -> state.map { preview ->
202216
if (preview.chat == event.context && preview.message?.id == event.message) {
203-
preview.copy(message = null)
217+
// Remove deleted message from history and get previous message
218+
val history = messageHistory[event.context]
219+
history?.removeIf { it.id == event.message }
220+
val previousMessage = history?.lastOrNull()
221+
preview.copy(message = previousMessage)
204222
} else preview
205223
}
206224

@@ -214,6 +232,14 @@ interface ChatPreviewContainer {
214232
state: List<Chat.Preview>,
215233
event: Event.Command.Chats.Add
216234
): List<Chat.Preview> {
235+
// Store message in history buffer for fallback on deletion
236+
val chatId = event.context
237+
val history = messageHistory.getOrPut(chatId) { ConcurrentLinkedDeque() }
238+
if (history.size >= MAX_MESSAGE_HISTORY) {
239+
history.removeFirst()
240+
}
241+
history.addLast(event.message)
242+
217243
// Extract attachment IDs
218244
val messageAttachmentIds = event.message.attachments.map { it.target }.toSet()
219245
val dependencyIds = event.dependencies.map { it.id }.toSet()
@@ -359,6 +385,7 @@ interface ChatPreviewContainer {
359385
companion object {
360386
private const val SUBSCRIPTION_ID = "chat-previews-subscription"
361387
private const val ATTACHMENT_SUBSCRIPTION_POSTFIX = "chat-previews-attachments"
388+
private const val MAX_MESSAGE_HISTORY = 10
362389
}
363390
}
364391
}

0 commit comments

Comments
 (0)