Fix crashes when opening Thread (#6463)
This commit is contained in:
parent
d957e24747
commit
0743140973
|
@ -0,0 +1 @@
|
||||||
|
Fix crashes when opening Thread
|
|
@ -20,6 +20,7 @@ import io.realm.Realm
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.android.asCoroutineDispatcher
|
import kotlinx.coroutines.android.asCoroutineDispatcher
|
||||||
import kotlinx.coroutines.cancelChildren
|
import kotlinx.coroutines.cancelChildren
|
||||||
|
@ -116,6 +117,7 @@ internal class DefaultTimeline(
|
||||||
)
|
)
|
||||||
|
|
||||||
private var strategy: LoadTimelineStrategy = buildStrategy(LoadTimelineStrategy.Mode.Live)
|
private var strategy: LoadTimelineStrategy = buildStrategy(LoadTimelineStrategy.Mode.Live)
|
||||||
|
private var startTimelineJob: Job? = null
|
||||||
|
|
||||||
override val isLive: Boolean
|
override val isLive: Boolean
|
||||||
get() = !getPaginationState(Timeline.Direction.FORWARDS).hasMoreToLoad
|
get() = !getPaginationState(Timeline.Direction.FORWARDS).hasMoreToLoad
|
||||||
|
@ -143,7 +145,7 @@ internal class DefaultTimeline(
|
||||||
timelineScope.launch {
|
timelineScope.launch {
|
||||||
loadRoomMembersIfNeeded()
|
loadRoomMembersIfNeeded()
|
||||||
}
|
}
|
||||||
timelineScope.launch {
|
startTimelineJob = timelineScope.launch {
|
||||||
sequencer.post {
|
sequencer.post {
|
||||||
if (isStarted.compareAndSet(false, true)) {
|
if (isStarted.compareAndSet(false, true)) {
|
||||||
isFromThreadTimeline = rootThreadEventId != null
|
isFromThreadTimeline = rootThreadEventId != null
|
||||||
|
@ -174,8 +176,10 @@ internal class DefaultTimeline(
|
||||||
|
|
||||||
override fun restartWithEventId(eventId: String?) {
|
override fun restartWithEventId(eventId: String?) {
|
||||||
timelineScope.launch {
|
timelineScope.launch {
|
||||||
openAround(eventId, rootThreadEventId)
|
sequencer.post {
|
||||||
postSnapshot()
|
openAround(eventId, rootThreadEventId)
|
||||||
|
postSnapshot()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +189,7 @@ internal class DefaultTimeline(
|
||||||
|
|
||||||
override fun paginate(direction: Timeline.Direction, count: Int) {
|
override fun paginate(direction: Timeline.Direction, count: Int) {
|
||||||
timelineScope.launch {
|
timelineScope.launch {
|
||||||
|
startTimelineJob?.join()
|
||||||
val postSnapshot = loadMore(count, direction, fetchOnServerIfNeeded = true)
|
val postSnapshot = loadMore(count, direction, fetchOnServerIfNeeded = true)
|
||||||
if (postSnapshot) {
|
if (postSnapshot) {
|
||||||
postSnapshot()
|
postSnapshot()
|
||||||
|
@ -193,6 +198,7 @@ internal class DefaultTimeline(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun awaitPaginate(direction: Timeline.Direction, count: Int): List<TimelineEvent> {
|
override suspend fun awaitPaginate(direction: Timeline.Direction, count: Int): List<TimelineEvent> {
|
||||||
|
startTimelineJob?.join()
|
||||||
withContext(timelineDispatcher) {
|
withContext(timelineDispatcher) {
|
||||||
loadMore(count, direction, fetchOnServerIfNeeded = true)
|
loadMore(count, direction, fetchOnServerIfNeeded = true)
|
||||||
}
|
}
|
||||||
|
@ -279,6 +285,7 @@ internal class DefaultTimeline(
|
||||||
direction = Timeline.Direction.BACKWARDS,
|
direction = Timeline.Direction.BACKWARDS,
|
||||||
fetchOnServerIfNeeded = false
|
fetchOnServerIfNeeded = false
|
||||||
)
|
)
|
||||||
|
|
||||||
Timber.v("$baseLogMessage finished")
|
Timber.v("$baseLogMessage finished")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,9 +319,11 @@ internal class DefaultTimeline(
|
||||||
|
|
||||||
private fun onLimitedTimeline() {
|
private fun onLimitedTimeline() {
|
||||||
timelineScope.launch {
|
timelineScope.launch {
|
||||||
initPaginationStates(null)
|
sequencer.post {
|
||||||
loadMore(settings.initialSize, Timeline.Direction.BACKWARDS, false)
|
initPaginationStates(null)
|
||||||
postSnapshot()
|
loadMore(settings.initialSize, Timeline.Direction.BACKWARDS, false)
|
||||||
|
postSnapshot()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||||
import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
|
import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
|
||||||
|
import org.matrix.android.sdk.internal.database.awaitTransaction
|
||||||
import org.matrix.android.sdk.internal.database.helper.addIfNecessary
|
import org.matrix.android.sdk.internal.database.helper.addIfNecessary
|
||||||
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
|
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
|
||||||
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
||||||
|
@ -265,7 +266,7 @@ internal class LoadTimelineStrategy constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getChunkEntity(realm: Realm): RealmResults<ChunkEntity> {
|
private suspend fun getChunkEntity(realm: Realm): RealmResults<ChunkEntity> {
|
||||||
return when (mode) {
|
return when (mode) {
|
||||||
is Mode.Live -> {
|
is Mode.Live -> {
|
||||||
ChunkEntity.where(realm, roomId)
|
ChunkEntity.where(realm, roomId)
|
||||||
|
@ -289,8 +290,8 @@ internal class LoadTimelineStrategy constructor(
|
||||||
* Clear any existing thread chunk entity and create a new one, with the
|
* Clear any existing thread chunk entity and create a new one, with the
|
||||||
* rootThreadEventId included.
|
* rootThreadEventId included.
|
||||||
*/
|
*/
|
||||||
private fun recreateThreadChunkEntity(realm: Realm, rootThreadEventId: String) {
|
private suspend fun recreateThreadChunkEntity(realm: Realm, rootThreadEventId: String) {
|
||||||
realm.executeTransaction {
|
awaitTransaction(realm.configuration) {
|
||||||
// Lets delete the chunk and start a new one
|
// Lets delete the chunk and start a new one
|
||||||
ChunkEntity.findLastForwardChunkOfThread(it, roomId, rootThreadEventId)?.deleteAndClearThreadEvents()?.let {
|
ChunkEntity.findLastForwardChunkOfThread(it, roomId, rootThreadEventId)?.deleteAndClearThreadEvents()?.let {
|
||||||
Timber.i("###THREADS LoadTimelineStrategy [onStart] thread chunk cleared..")
|
Timber.i("###THREADS LoadTimelineStrategy [onStart] thread chunk cleared..")
|
||||||
|
@ -309,8 +310,8 @@ internal class LoadTimelineStrategy constructor(
|
||||||
/**
|
/**
|
||||||
* Clear any existing thread chunk.
|
* Clear any existing thread chunk.
|
||||||
*/
|
*/
|
||||||
private fun clearThreadChunkEntity(realm: Realm, rootThreadEventId: String) {
|
private suspend fun clearThreadChunkEntity(realm: Realm, rootThreadEventId: String) {
|
||||||
realm.executeTransaction {
|
awaitTransaction(realm.configuration) {
|
||||||
ChunkEntity.findLastForwardChunkOfThread(it, roomId, rootThreadEventId)?.deleteAndClearThreadEvents()?.let {
|
ChunkEntity.findLastForwardChunkOfThread(it, roomId, rootThreadEventId)?.deleteAndClearThreadEvents()?.let {
|
||||||
Timber.i("###THREADS LoadTimelineStrategy [onStop] thread chunk cleared..")
|
Timber.i("###THREADS LoadTimelineStrategy [onStop] thread chunk cleared..")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue