Skip to content

Commit 2b67062

Browse files
committed
feat: cache chat Flow's in app scope to prevent unneccesary API calls to repopulate feeds
* keep an eye on this due to GlobalScope use Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent e24aaf8 commit 2b67062

3 files changed

Lines changed: 24 additions & 6 deletions

File tree

api/src/main/java/com/getcode/network/HistoryController.kt

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package com.getcode.network
33
import android.annotation.SuppressLint
44
import androidx.paging.Pager
55
import androidx.paging.PagingConfig
6+
import androidx.paging.PagingData
7+
import androidx.paging.PagingSource
8+
import androidx.paging.cachedIn
69
import com.getcode.ed25519.Ed25519.KeyPair
710
import com.getcode.manager.SessionManager
811
import com.getcode.model.Chat
@@ -20,6 +23,8 @@ import com.getcode.network.source.ChatMessagePagingSource
2023
import com.getcode.utils.ErrorUtils
2124
import kotlinx.coroutines.CoroutineScope
2225
import kotlinx.coroutines.Dispatchers
26+
import kotlinx.coroutines.GlobalScope
27+
import kotlinx.coroutines.flow.Flow
2328
import kotlinx.coroutines.flow.MutableStateFlow
2429
import kotlinx.coroutines.flow.StateFlow
2530
import kotlinx.coroutines.flow.asStateFlow
@@ -53,9 +58,21 @@ class HistoryController @Inject constructor(
5358
val chats: StateFlow<List<Chat>?>
5459
get() = _chats.asStateFlow()
5560

56-
fun chatMessagePager(chatId: ID) = Pager(
61+
62+
private val pagerMap = mutableMapOf<ID, PagingSource<Cursor, ChatMessage>>()
63+
private val chatFlows = mutableMapOf<ID, Flow<PagingData<ChatMessage>>>()
64+
65+
private fun chatMessagePager(chatId: ID) = Pager(
5766
PagingConfig(pageSize = 20)
58-
) { ChatMessagePagingSource(client, owner()!!, chatId) }
67+
) {
68+
pagerMap[chatId] ?: ChatMessagePagingSource(client, owner()!!, chatId).also {
69+
pagerMap[chatId] = it
70+
}
71+
}
72+
73+
fun chatFlow(chatId: ID) = chatFlows[chatId] ?: chatMessagePager(chatId).flow.cachedIn(GlobalScope).also {
74+
chatFlows[chatId] = it
75+
}
5976

6077
val unreadCount = chats
6178
.filterNotNull()
@@ -143,7 +160,7 @@ class HistoryController @Inject constructor(
143160

144161
private suspend fun fetchLatestMessageForChat(id: List<Byte>): Result<ChatMessage?> {
145162
val encodedId = id.toByteArray().encodeBase64()
146-
Timber.d("fetching messages for $encodedId")
163+
Timber.d("fetching last message for $encodedId")
147164
val owner = owner() ?: return Result.success(null)
148165
return client.fetchMessagesFor(owner, id, limit = 1)
149166
.onFailure {

app/src/main/java/com/getcode/navigation/screens/ChatScreens.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ data object BalanceModal : ChatGraph, ModalRoot {
7878
}
7979

8080
@Parcelize
81-
data class ChatScreen(val chatId: ID): ChatGraph, ModalContent {
81+
data class ChatScreen(val chatId: ID) : ChatGraph, ModalContent {
8282
@IgnoredOnParcel
8383
override val key: ScreenKey = uniqueScreenKey
8484

app/src/main/java/com/getcode/view/main/chat/ChatViewModel.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import com.getcode.view.main.home.PresentationStyle
2222
import dagger.hilt.android.lifecycle.HiltViewModel
2323
import kotlinx.coroutines.Dispatchers
2424
import kotlinx.coroutines.ExperimentalCoroutinesApi
25+
import kotlinx.coroutines.flow.emptyFlow
2526
import kotlinx.coroutines.flow.filter
2627
import kotlinx.coroutines.flow.filterIsInstance
2728
import kotlinx.coroutines.flow.filterNotNull
@@ -66,7 +67,7 @@ class ChatViewModel @Inject constructor(
6667
)
6768

6869
sealed interface Event {
69-
data class OnChatIdChanged(val id: ID) : Event
70+
data class OnChatIdChanged(val id: ID?) : Event
7071
data class OnChatChanged(val title: Title?) : Event
7172
data object OnMuteToggled : Event
7273
data class SetMuted(val muted: Boolean) : Event
@@ -110,7 +111,7 @@ class ChatViewModel @Inject constructor(
110111
val chatMessages = stateFlow
111112
.map { it.chatId }
112113
.filterNotNull()
113-
.flatMapLatest { historyController.chatMessagePager(it).flow }
114+
.flatMapLatest { historyController.chatFlow(it) }
114115
.mapLatest { page ->
115116
page.flatMap { chat ->
116117
chat.contents

0 commit comments

Comments
 (0)