mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-24 18:36:21 +03:00
Sync polls until now when landing on screen
This commit is contained in:
parent
073eda75a2
commit
cd1f41594d
3 changed files with 149 additions and 13 deletions
|
@ -93,8 +93,10 @@ import org.matrix.android.sdk.internal.session.room.peeking.PeekRoomTask
|
|||
import org.matrix.android.sdk.internal.session.room.peeking.ResolveRoomStateTask
|
||||
import org.matrix.android.sdk.internal.session.room.poll.DefaultGetLoadedPollsStatusTask
|
||||
import org.matrix.android.sdk.internal.session.room.poll.DefaultLoadMorePollsTask
|
||||
import org.matrix.android.sdk.internal.session.room.poll.DefaultSyncPollsTask
|
||||
import org.matrix.android.sdk.internal.session.room.poll.GetLoadedPollsStatusTask
|
||||
import org.matrix.android.sdk.internal.session.room.poll.LoadMorePollsTask
|
||||
import org.matrix.android.sdk.internal.session.room.poll.SyncPollsTask
|
||||
import org.matrix.android.sdk.internal.session.room.read.DefaultMarkAllRoomsReadTask
|
||||
import org.matrix.android.sdk.internal.session.room.read.DefaultSetReadMarkersTask
|
||||
import org.matrix.android.sdk.internal.session.room.read.MarkAllRoomsReadTask
|
||||
|
@ -374,4 +376,7 @@ internal abstract class RoomModule {
|
|||
|
||||
@Binds
|
||||
abstract fun bindFilterAndStoreEventsTask(task: DefaultFilterAndStoreEventsTask): FilterAndStoreEventsTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindSyncPollsTask(task: DefaultSyncPollsTask): SyncPollsTask
|
||||
}
|
||||
|
|
|
@ -23,7 +23,8 @@ import dagger.assisted.Assisted
|
|||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import io.realm.kotlin.where
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.room.poll.LoadedPollsStatus
|
||||
import org.matrix.android.sdk.api.session.room.poll.PollHistoryService
|
||||
|
@ -50,6 +51,7 @@ internal class DefaultPollHistoryService @AssistedInject constructor(
|
|||
private val clock: Clock,
|
||||
private val loadMorePollsTask: LoadMorePollsTask,
|
||||
private val getLoadedPollsStatusTask: GetLoadedPollsStatusTask,
|
||||
private val syncPollsTask: SyncPollsTask,
|
||||
private val timelineEventMapper: TimelineEventMapper,
|
||||
) : PollHistoryService {
|
||||
|
||||
|
@ -71,20 +73,23 @@ internal class DefaultPollHistoryService @AssistedInject constructor(
|
|||
)
|
||||
timelineService.createTimeline(eventId = null, settings = settings).also { it.start() }
|
||||
}
|
||||
private val timelineMutex = Mutex()
|
||||
|
||||
override fun dispose() {
|
||||
timeline.dispose()
|
||||
}
|
||||
|
||||
override suspend fun loadMore(): LoadedPollsStatus {
|
||||
val params = LoadMorePollsTask.Params(
|
||||
timeline = timeline,
|
||||
roomId = roomId,
|
||||
currentTimestampMs = clock.epochMillis(),
|
||||
loadingPeriodInDays = loadingPeriodInDays,
|
||||
eventsPageSize = EVENTS_PAGE_SIZE,
|
||||
)
|
||||
return loadMorePollsTask.execute(params)
|
||||
return timelineMutex.withLock {
|
||||
val params = LoadMorePollsTask.Params(
|
||||
timeline = timeline,
|
||||
roomId = roomId,
|
||||
currentTimestampMs = clock.epochMillis(),
|
||||
loadingPeriodInDays = loadingPeriodInDays,
|
||||
eventsPageSize = EVENTS_PAGE_SIZE,
|
||||
)
|
||||
loadMorePollsTask.execute(params)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getLoadedPollsStatus(): LoadedPollsStatus {
|
||||
|
@ -96,10 +101,15 @@ internal class DefaultPollHistoryService @AssistedInject constructor(
|
|||
}
|
||||
|
||||
override suspend fun syncPolls() {
|
||||
// TODO unmock
|
||||
// TODO when sync forward, jump to most recent event Id + paginate forward + jump to oldest eventId after
|
||||
// TODO avoid possibility to call sync and loadMore at the same time from the service API, how?
|
||||
delay(1000)
|
||||
timelineMutex.withLock {
|
||||
val params = SyncPollsTask.Params(
|
||||
timeline = timeline,
|
||||
roomId = roomId,
|
||||
currentTimestampMs = clock.epochMillis(),
|
||||
eventsPageSize = EVENTS_PAGE_SIZE,
|
||||
)
|
||||
syncPollsTask.execute(params)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPollEvents(): LiveData<List<TimelineEvent>> {
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2023 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.session.room.poll
|
||||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import kotlinx.coroutines.delay
|
||||
import org.matrix.android.sdk.api.session.events.model.isPoll
|
||||
import org.matrix.android.sdk.api.session.events.model.isPollResponse
|
||||
import org.matrix.android.sdk.api.session.room.poll.LoadedPollsStatus
|
||||
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.internal.database.model.PollHistoryStatusEntity
|
||||
import org.matrix.android.sdk.internal.database.query.getOrCreate
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||
import org.matrix.android.sdk.internal.session.room.event.FilterAndStoreEventsTask
|
||||
import org.matrix.android.sdk.internal.session.room.poll.PollConstants.MILLISECONDS_PER_DAY
|
||||
import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection
|
||||
import org.matrix.android.sdk.internal.session.room.timeline.PaginationResponse
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import org.matrix.android.sdk.internal.util.awaitTransaction
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface SyncPollsTask : Task<SyncPollsTask.Params, Unit> {
|
||||
data class Params(
|
||||
val timeline: Timeline,
|
||||
val roomId: String,
|
||||
val currentTimestampMs: Long,
|
||||
val eventsPageSize: Int,
|
||||
)
|
||||
}
|
||||
|
||||
internal class DefaultSyncPollsTask @Inject constructor(
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
) : SyncPollsTask {
|
||||
|
||||
override suspend fun execute(params: SyncPollsTask.Params) {
|
||||
val currentPollHistoryStatus = getCurrentPollHistoryStatus(params.roomId)
|
||||
|
||||
params.timeline.restartWithEventId(currentPollHistoryStatus.mostRecentEventIdReached)
|
||||
|
||||
var loadStatus = LoadStatus(shouldLoadMore = true)
|
||||
while (loadStatus.shouldLoadMore){
|
||||
loadStatus = fetchMorePollEventsForward(params)
|
||||
}
|
||||
|
||||
params.timeline.restartWithEventId(currentPollHistoryStatus.oldestEventIdReached)
|
||||
}
|
||||
|
||||
private suspend fun getCurrentPollHistoryStatus(roomId: String): PollHistoryStatusEntity {
|
||||
return monarchy.awaitTransaction { realm ->
|
||||
PollHistoryStatusEntity
|
||||
.getOrCreate(realm, roomId)
|
||||
.copy()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun fetchMorePollEventsForward(params: SyncPollsTask.Params): LoadStatus {
|
||||
val events = params.timeline.awaitPaginate(
|
||||
direction = Timeline.Direction.FORWARDS,
|
||||
count = params.eventsPageSize,
|
||||
)
|
||||
|
||||
val paginationState = params.timeline.getPaginationState(direction = Timeline.Direction.FORWARDS)
|
||||
|
||||
return updatePollHistoryStatus(
|
||||
roomId = params.roomId,
|
||||
currentTimestampMs = params.currentTimestampMs,
|
||||
events = events,
|
||||
paginationState = paginationState,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun updatePollHistoryStatus(
|
||||
roomId: String,
|
||||
currentTimestampMs: Long,
|
||||
events: List<TimelineEvent>,
|
||||
paginationState: Timeline.PaginationState,
|
||||
): LoadStatus {
|
||||
return monarchy.awaitTransaction { realm ->
|
||||
val status = PollHistoryStatusEntity.getOrCreate(realm, roomId)
|
||||
val mostRecentEventIdReached = status.mostRecentEventIdReached
|
||||
|
||||
val mostRecentEvent = events
|
||||
.maxByOrNull { it.root.originServerTs ?: Long.MIN_VALUE }
|
||||
?.root
|
||||
|
||||
if (mostRecentEventIdReached == null) {
|
||||
// save it for next forward pagination
|
||||
status.mostRecentEventIdReached = mostRecentEvent?.eventId
|
||||
}
|
||||
|
||||
val mostRecentTimestamp = mostRecentEvent?.ageLocalTs
|
||||
|
||||
val shouldLoadMore = paginationState.hasMoreToLoad &&
|
||||
(mostRecentTimestamp == null || mostRecentTimestamp < currentTimestampMs)
|
||||
|
||||
LoadStatus(shouldLoadMore = shouldLoadMore)
|
||||
}
|
||||
}
|
||||
|
||||
private class LoadStatus(
|
||||
val shouldLoadMore: Boolean,
|
||||
)
|
||||
}
|
Loading…
Reference in a new issue