diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/poll/PollHistoryService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/poll/PollHistoryService.kt index ad53febc50..866c3e6b81 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/poll/PollHistoryService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/poll/PollHistoryService.kt @@ -35,7 +35,7 @@ interface PollHistoryService { /** * Get the current status of the loaded polls. */ - fun getLoadedPollsStatus(): LoadedPollsStatus + suspend fun getLoadedPollsStatus(): LoadedPollsStatus /** * Sync polls from last loaded polls until now. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt index dab2d340b6..17e57aa2ee 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt @@ -89,7 +89,9 @@ import org.matrix.android.sdk.internal.session.room.peeking.DefaultPeekRoomTask import org.matrix.android.sdk.internal.session.room.peeking.DefaultResolveRoomStateTask 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.GetLoadedPollsStatusTask import org.matrix.android.sdk.internal.session.room.poll.LoadMorePollsTask import org.matrix.android.sdk.internal.session.room.read.DefaultMarkAllRoomsReadTask import org.matrix.android.sdk.internal.session.room.read.DefaultSetReadMarkersTask @@ -364,4 +366,7 @@ internal abstract class RoomModule { @Binds abstract fun bindLoadMorePollsTask(task: DefaultLoadMorePollsTask): LoadMorePollsTask + + @Binds + abstract fun bindGetLoadedPollsStatusTask(task: DefaultGetLoadedPollsStatusTask): GetLoadedPollsStatusTask } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/poll/DefaultPollHistoryService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/poll/DefaultPollHistoryService.kt index 74f59b6782..c4ba89f4a6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/poll/DefaultPollHistoryService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/poll/DefaultPollHistoryService.kt @@ -34,6 +34,7 @@ internal class DefaultPollHistoryService @AssistedInject constructor( @Assisted private val roomId: String, private val clock: Clock, private val loadMorePollsTask: LoadMorePollsTask, + private val getLoadedPollsStatusTask: GetLoadedPollsStatusTask, ) : PollHistoryService { @AssistedFactory @@ -58,8 +59,12 @@ internal class DefaultPollHistoryService @AssistedInject constructor( return loadMorePollsTask.execute(params) } - override fun getLoadedPollsStatus(): LoadedPollsStatus { - TODO("Not yet implemented") + override suspend fun getLoadedPollsStatus(): LoadedPollsStatus { + val params = GetLoadedPollsStatusTask.Params( + roomId = roomId, + currentTimestampMs = clock.epochMillis(), + ) + return getLoadedPollsStatusTask.execute(params) } override suspend fun syncPolls() { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/poll/GetLoadedPollsStatusTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/poll/GetLoadedPollsStatusTask.kt new file mode 100644 index 0000000000..118c81a451 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/poll/GetLoadedPollsStatusTask.kt @@ -0,0 +1,48 @@ +/* + * 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 org.matrix.android.sdk.api.session.room.poll.LoadedPollsStatus +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.task.Task +import org.matrix.android.sdk.internal.util.awaitTransaction +import javax.inject.Inject + +internal interface GetLoadedPollsStatusTask : Task { + data class Params( + val roomId: String, + val currentTimestampMs: Long, + ) +} + +internal class DefaultGetLoadedPollsStatusTask @Inject constructor( + @SessionDatabase private val monarchy: Monarchy, +) : GetLoadedPollsStatusTask { + + override suspend fun execute(params: GetLoadedPollsStatusTask.Params): LoadedPollsStatus { + return monarchy.awaitTransaction { realm -> + val status = PollHistoryStatusEntity.getOrCreate(realm, params.roomId) + LoadedPollsStatus( + canLoadMore = status.isEndOfPollsBackward.not(), + nbSyncedDays = status.getNbSyncedDays(params.currentTimestampMs), + ) + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModel.kt index b72486402b..fccdef87b8 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModel.kt @@ -48,26 +48,21 @@ class RoomPollsViewModel @AssistedInject constructor( init { val roomId = initialState.roomId - updateLoadedPollStatus(roomId) syncPolls(roomId) observePolls(roomId) } - private fun updateLoadedPollStatus(roomId: String) { - val loadedPollsStatus = getLoadedPollsStatusUseCase.execute(roomId) - setState { - copy( - canLoadMore = loadedPollsStatus.canLoadMore, - nbSyncedDays = loadedPollsStatus.nbSyncedDays, - ) - } - } - private fun syncPolls(roomId: String) { viewModelScope.launch { setState { copy(isSyncing = true) } val result = runCatching { - syncPollsUseCase.execute(roomId) + val loadedPollsStatus = syncPollsUseCase.execute(roomId) + setState { + copy( + canLoadMore = loadedPollsStatus.canLoadMore, + nbSyncedDays = loadedPollsStatus.nbSyncedDays, + ) + } } if (result.isFailure) { _viewEvents.post(RoomPollsViewEvent.LoadingError) diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/PollHistoryError.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/PollHistoryError.kt index 37b7d934bb..67d59faebd 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/PollHistoryError.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/PollHistoryError.kt @@ -17,5 +17,5 @@ package im.vector.app.features.roomprofile.polls.list.data sealed class PollHistoryError : Exception() { - object LoadingError : PollHistoryError() + object UnknownRoomError : PollHistoryError() } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/RoomPollDataSource.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/RoomPollDataSource.kt index 72ca464951..f22f494f49 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/RoomPollDataSource.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/RoomPollDataSource.kt @@ -34,13 +34,13 @@ class RoomPollDataSource @Inject constructor( ) { private val pollsFlow = MutableSharedFlow>(replay = 1) - private var fakeLoadCounter = 0 - private fun getPollHistoryService(roomId: String): PollHistoryService? { + private fun getPollHistoryService(roomId: String): PollHistoryService { return activeSessionHolder .getSafeActiveSession() ?.getRoom(roomId) ?.pollHistoryService() + ?: throw PollHistoryError.UnknownRoomError } // TODO @@ -51,21 +51,12 @@ class RoomPollDataSource @Inject constructor( return pollsFlow.asSharedFlow() } - fun getLoadedPollsStatus(roomId: String): LoadedPollsStatus { - Timber.d("roomId=$roomId") - // TODO unmock using SDK - return LoadedPollsStatus( - canLoadMore = canLoadMore(), - nbSyncedDays = fakeLoadCounter * 30, - ) - } - - private fun canLoadMore(): Boolean { - return fakeLoadCounter < 2 + suspend fun getLoadedPollsStatus(roomId: String): LoadedPollsStatus { + return getPollHistoryService(roomId).getLoadedPollsStatus() } suspend fun loadMorePolls(roomId: String): LoadedPollsStatus { - return getPollHistoryService(roomId)?.loadMore() ?: throw PollHistoryError.LoadingError + return getPollHistoryService(roomId).loadMore() } suspend fun syncPolls(roomId: String) { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/RoomPollRepository.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/RoomPollRepository.kt index 6f9b780464..4679af4434 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/RoomPollRepository.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/RoomPollRepository.kt @@ -30,7 +30,7 @@ class RoomPollRepository @Inject constructor( return roomPollDataSource.getPolls(roomId) } - fun getLoadedPollsStatus(roomId: String): LoadedPollsStatus { + suspend fun getLoadedPollsStatus(roomId: String): LoadedPollsStatus { return roomPollDataSource.getLoadedPollsStatus(roomId) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/GetLoadedPollsStatusUseCase.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/GetLoadedPollsStatusUseCase.kt index 2bac26f79c..d37e27ff03 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/GetLoadedPollsStatusUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/GetLoadedPollsStatusUseCase.kt @@ -24,7 +24,7 @@ class GetLoadedPollsStatusUseCase @Inject constructor( private val roomPollRepository: RoomPollRepository, ) { - fun execute(roomId: String): LoadedPollsStatus { + suspend fun execute(roomId: String): LoadedPollsStatus { return roomPollRepository.getLoadedPollsStatus(roomId) } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/SyncPollsUseCase.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/SyncPollsUseCase.kt index b6a344f7f8..7346406c84 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/SyncPollsUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/SyncPollsUseCase.kt @@ -17,6 +17,7 @@ package im.vector.app.features.roomprofile.polls.list.domain import im.vector.app.features.roomprofile.polls.list.data.RoomPollRepository +import org.matrix.android.sdk.api.session.room.poll.LoadedPollsStatus import javax.inject.Inject /** @@ -24,9 +25,11 @@ import javax.inject.Inject */ class SyncPollsUseCase @Inject constructor( private val roomPollRepository: RoomPollRepository, + private val getLoadedPollsStatusUseCase: GetLoadedPollsStatusUseCase, ) { - suspend fun execute(roomId: String) { + suspend fun execute(roomId: String): LoadedPollsStatus { roomPollRepository.syncPolls(roomId) + return getLoadedPollsStatusUseCase.execute(roomId) } } diff --git a/vector/src/test/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModelTest.kt b/vector/src/test/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModelTest.kt index 1cac603ae2..adbf32006e 100644 --- a/vector/src/test/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModelTest.kt @@ -17,7 +17,6 @@ package im.vector.app.features.roomprofile.polls import com.airbnb.mvrx.test.MavericksTestRule -import im.vector.app.features.roomprofile.polls.list.data.LoadedPollsStatus import im.vector.app.features.roomprofile.polls.list.domain.GetLoadedPollsStatusUseCase import im.vector.app.features.roomprofile.polls.list.domain.GetPollsUseCase import im.vector.app.features.roomprofile.polls.list.domain.LoadMorePollsUseCase @@ -34,6 +33,7 @@ import io.mockk.verify import kotlinx.coroutines.flow.flowOf import org.junit.Rule import org.junit.Test +import org.matrix.android.sdk.api.session.room.poll.LoadedPollsStatus private const val A_ROOM_ID = "room-id" @@ -68,7 +68,7 @@ class RoomPollsViewModelTest { val expectedViewState = initialState.copy( polls = polls, canLoadMore = loadedPollsStatus.canLoadMore, - nbSyncedDays = loadedPollsStatus.nbLoadedDays, + nbSyncedDays = loadedPollsStatus.nbSyncedDays, ) // When @@ -116,7 +116,7 @@ class RoomPollsViewModelTest { val stateAfterInit = initialState.copy( polls = polls, canLoadMore = loadedPollsStatus.canLoadMore, - nbSyncedDays = loadedPollsStatus.nbLoadedDays, + nbSyncedDays = loadedPollsStatus.nbSyncedDays, ) // When @@ -128,7 +128,7 @@ class RoomPollsViewModelTest { .assertStatesChanges( stateAfterInit, { copy(isLoadingMore = true) }, - { copy(canLoadMore = newLoadedPollsStatus.canLoadMore, nbSyncedDays = newLoadedPollsStatus.nbLoadedDays) }, + { copy(canLoadMore = newLoadedPollsStatus.canLoadMore, nbSyncedDays = newLoadedPollsStatus.nbSyncedDays) }, { copy(isLoadingMore = false) }, ) .finish() @@ -148,20 +148,20 @@ class RoomPollsViewModelTest { } private fun givenLoadMoreWithSuccess(): LoadedPollsStatus { - val loadedPollsStatus = givenALoadedPollsStatus(canLoadMore = false, nbLoadedDays = 20) + val loadedPollsStatus = givenALoadedPollsStatus(canLoadMore = false, nbSyncedDays = 20) coEvery { fakeLoadMorePollsUseCase.execute(A_ROOM_ID) } returns loadedPollsStatus return loadedPollsStatus } private fun givenGetLoadedPollsStatusSuccess(): LoadedPollsStatus { val loadedPollsStatus = givenALoadedPollsStatus() - every { fakeGetLoadedPollsStatusUseCase.execute(A_ROOM_ID) } returns loadedPollsStatus + coEvery { fakeGetLoadedPollsStatusUseCase.execute(A_ROOM_ID) } returns loadedPollsStatus return loadedPollsStatus } - private fun givenALoadedPollsStatus(canLoadMore: Boolean = true, nbLoadedDays: Int = 10) = + private fun givenALoadedPollsStatus(canLoadMore: Boolean = true, nbSyncedDays: Int = 10) = LoadedPollsStatus( canLoadMore = canLoadMore, - nbLoadedDays = nbLoadedDays, + nbSyncedDays = nbSyncedDays, ) }