feat: background prefetch of all conversation messages for offline access

On app start, after syncing the conversation list, prefetch messages
for any conversation not yet cached in Room. This ensures all chats
are readable offline, not just previously opened ones.
This commit is contained in:
Bruno Deanoz 2026-06-21 18:16:51 +02:00
parent fe5e93cdfa
commit 918659422b
5 changed files with 22 additions and 0 deletions

View file

@ -166,6 +166,10 @@ fun ChatScreen(
if (errors.isNotEmpty()) {
loadError = errors.joinToString(" · ")
}
scope.launch {
val ids = chat.conversationRepo.allUnlockedIds()
chat.messageRepo.prefetchMissing(cfg.baseUrl, cfg.token, ids)
}
}
// Warm the HTTP/2 connection pool on every app resume (covers background → foreground

View file

@ -25,4 +25,7 @@ interface ConversationDao {
@Query("SELECT cachedAt FROM conversations LIMIT 1")
suspend fun lastCachedAt(): Long?
@Query("SELECT id FROM conversations WHERE locked = 0")
suspend fun allUnlockedIds(): List<String>
}

View file

@ -22,4 +22,6 @@ class ConversationRepository(private val dao: ConversationDao) {
}
suspend fun lastCachedAt(): Long? = dao.lastCachedAt()
suspend fun allUnlockedIds(): List<String> = dao.allUnlockedIds()
}

View file

@ -18,4 +18,7 @@ interface MessageDao {
@Query("DELETE FROM messages WHERE conversationId = :convId")
suspend fun deleteByConversation(convId: String)
@Query("SELECT DISTINCT conversationId FROM messages")
suspend fun cachedConversationIds(): List<String>
}

View file

@ -21,4 +21,14 @@ class MessageRepository(private val dao: MessageDao) {
suspend fun cacheMessages(convId: String, messages: List<MessageEntity>) {
dao.upsertAll(messages)
}
suspend fun prefetchMissing(baseUrl: String, token: String, conversationIds: List<String>) {
val cached = dao.cachedConversationIds().toSet()
for (id in conversationIds) {
if (id in cached) continue
try {
fetchAndCache(baseUrl, token, id)
} catch (_: Exception) { }
}
}
}