Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When expanding a long Thread, display Messages by batches so it doesn't freeze the UI anymore #2044

Merged
merged 5 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ class RefreshController @Inject constructor(
// Add Sentry log and leave if the Message already exists
if (existingMessage != null && !existingMessage.isOrphan()) {
SentryLog.i(
TAG,
"Realm",
"Already existing message in folder ${folder.displayForSentry()} | threadMode = ${localSettings.threadMode}",
)
return true
Expand Down Expand Up @@ -817,8 +817,4 @@ class RefreshController @Inject constructor(
val onStart: (() -> Unit),
val onStop: (() -> Unit),
)

companion object {
private val TAG = RefreshController::class.java.simpleName
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ class ThreadFragment : Fragment() {
observeLightThemeToggle()
observeThreadLive()
observeMessagesLive()
observeBatchedMessages()
observeFailedMessages()
observeQuickActionBarClicks()
observeSubjectUpdateTriggers()
Expand Down Expand Up @@ -428,13 +429,22 @@ class ThreadFragment : Fragment() {
return@observe
}

threadAdapter.submitList(items)
if (threadState.hasSuperCollapsedBlockBeenClicked) {
displayBatchedMessages(items)
} else {
threadAdapter.submitList(items)
}

if (messagesToFetch.isNotEmpty()) fetchMessagesHeavyData(messagesToFetch)

fetchCalendarEvents(items)
}
}

private fun observeBatchedMessages() {
threadViewModel.batchedMessages.observe(viewLifecycleOwner, threadAdapter::submitList)
}

private fun observeFailedMessages() {
threadViewModel.failedMessagesUids.observe(viewLifecycleOwner, threadAdapter::updateFailedMessages)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class ThreadViewModel @Inject constructor(

val threadLive = MutableLiveData<Thread?>()
val messagesLive = MutableLiveData<Pair<ThreadAdapterItems, MessagesWithoutHeavyData>>()
val batchedMessages = SingleLiveEvent<List<Any>>()

val quickActionBarClicks = SingleLiveEvent<QuickActionBarResult>()

Expand Down Expand Up @@ -246,6 +247,25 @@ class ThreadViewModel @Inject constructor(
return@withContext message
}

fun displayBatchedMessages(items: List<Any>) = viewModelScope.launch(ioCoroutineContext) {

tailrec suspend fun sendBatchesRecursively(input: List<Any>, output: MutableList<Any>, batchSize: Int = 1) {

val batch = input.take(batchSize)
output.addAll(batch)

// We need to post a different list each time, because the `submitList` function in AsyncListDiffer
// won't trigger if we send the same list object (https://stackoverflow.com/questions/49726385).
batchedMessages.postValue(ArrayList(output))

if (batch.size < batchSize) return
delay(DELAY_BETWEEN_EACH_BATCHED_MESSAGES)
sendBatchesRecursively(input.subList(batchSize, input.size), output)
}

sendBatchesRecursively(input = items, output = mutableListOf(), batchSize = 2)
}

fun openThread(threadUid: String) = liveData(ioCoroutineContext) {

val thread = threadController.getThread(threadUid) ?: run {
Expand Down Expand Up @@ -451,5 +471,6 @@ class ThreadViewModel @Inject constructor(
companion object {
private const val SUPER_COLLAPSED_BLOCK_MINIMUM_MESSAGES_LIMIT = 5
private const val SUPER_COLLAPSED_BLOCK_FIRST_INDEX_LIMIT = 3
private const val DELAY_BETWEEN_EACH_BATCHED_MESSAGES = 50L
}
}
Loading