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

Hotfix/1.3.15 #4971

Merged
merged 16 commits into from
Jan 18, 2022
1 change: 1 addition & 0 deletions changelog.d/4959.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prevent crash in Timeline and add more logs.
Original file line number Diff line number Diff line change
@@ -72,6 +72,7 @@ import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import timber.log.Timber
import javax.inject.Inject
import kotlin.math.min
import kotlin.system.measureTimeMillis

class TimelineEventController @Inject constructor(private val dateFormatter: VectorDateFormatter,
@@ -185,17 +186,21 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
override fun onChanged(position: Int, count: Int, payload: Any?) {
synchronized(modelCache) {
assertUpdateCallbacksAllowed()
Timber.v("listUpdateCallback.onChanged(position: $position, count: $count). " +
"\ncurrentSnapshot has size of ${currentSnapshot.size} items")
(position until position + count).forEach {
// Invalidate cache
modelCache[it] = null
}
// Also invalidate the first previous displayable event if
// it's sent by the same user so we are sure we have up to date information.
val invalidatedSenderId: String? = currentSnapshot.getOrNull(position)?.senderInfo?.userId
val prevDisplayableEventIndex = currentSnapshot.subList(0, position).indexOfLast {
// In some cases onChanged will be called before onRemoved and onInserted so position will be smaller than currentSnapshot.size.
val prevList = currentSnapshot.subList(0, min(position, currentSnapshot.size))
val prevDisplayableEventIndex = prevList.indexOfLast {
timelineEventVisibilityHelper.shouldShowEvent(it, partialState.highlightedEventId)
}
if (prevDisplayableEventIndex != -1 && currentSnapshot[prevDisplayableEventIndex].senderInfo.userId == invalidatedSenderId) {
if (prevDisplayableEventIndex != -1 && currentSnapshot.getOrNull(prevDisplayableEventIndex)?.senderInfo?.userId == invalidatedSenderId) {
modelCache[prevDisplayableEventIndex] = null
}
requestModelBuild()
@@ -205,6 +210,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
override fun onMoved(fromPosition: Int, toPosition: Int) {
synchronized(modelCache) {
assertUpdateCallbacksAllowed()
Timber.v("listUpdateCallback.onMoved(fromPosition: $fromPosition, toPosition: $toPosition). " +
"\ncurrentSnapshot has size of ${currentSnapshot.size} items")
val model = modelCache.removeAt(fromPosition)
modelCache.add(toPosition, model)
requestModelBuild()
@@ -214,6 +221,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
override fun onInserted(position: Int, count: Int) {
synchronized(modelCache) {
assertUpdateCallbacksAllowed()
Timber.v("listUpdateCallback.onInserted(position: $position, count: $count). " +
"\ncurrentSnapshot has size of ${currentSnapshot.size} items")
repeat(count) {
modelCache.add(position, null)
}
@@ -224,6 +233,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
override fun onRemoved(position: Int, count: Int) {
synchronized(modelCache) {
assertUpdateCallbacksAllowed()
Timber.v("listUpdateCallback.onRemoved(position: $position, count: $count). " +
"\ncurrentSnapshot has size of ${currentSnapshot.size} items")
repeat(count) {
modelCache.removeAt(position)
}
@@ -306,6 +317,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
inSubmitList = true
val diffCallback = TimelineEventDiffUtilCallback(currentSnapshot, newSnapshot)
currentSnapshot = newSnapshot
Timber.v("Submit a new snapshot of ${currentSnapshot.size} items.")
val diffResult = DiffUtil.calculateDiff(diffCallback)
diffResult.dispatchUpdatesTo(listUpdateCallback)
requestDelayedModelBuild(0)