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 220690fe90..3000f53a18 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 @@ -43,6 +43,7 @@ class RoomPollsViewModel @AssistedInject constructor( companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() init { + // TODO update canLoadMore in viewState observePolls() } @@ -62,8 +63,8 @@ class RoomPollsViewModel @AssistedInject constructor( private fun handleLoadMore() = withState { viewState -> viewModelScope.launch { setState { copy(isLoadingMore = true) } - loadMorePollsUseCase.execute(viewState.roomId) - setState { copy(isLoadingMore = false) } + val result = loadMorePollsUseCase.execute(viewState.roomId) + setState { copy(isLoadingMore = false, canLoadMore = result.canLoadMore) } } } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsViewState.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsViewState.kt index 8512d58acf..99ebaab07b 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsViewState.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsViewState.kt @@ -20,12 +20,12 @@ import com.airbnb.mvrx.MavericksState import im.vector.app.features.roomprofile.RoomProfileArgs import im.vector.app.features.roomprofile.polls.list.ui.PollSummary -// TODO parameter to know whether load more is possible // TODO parameter to know whether initial loading is in progress data class RoomPollsViewState( val roomId: String, val polls: List = emptyList(), val isLoadingMore: Boolean = false, + val canLoadMore: Boolean = true, ) : MavericksState { constructor(roomProfileArgs: RoomProfileArgs) : this(roomId = roomProfileArgs.roomId) diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/LoadMorePollsResult.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/LoadMorePollsResult.kt new file mode 100644 index 0000000000..9b5cda4f23 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/LoadMorePollsResult.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * 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 im.vector.app.features.roomprofile.polls.list.data + +data class LoadMorePollsResult( + val canLoadMore: Boolean, +) 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 new file mode 100644 index 0000000000..5eb491e14f --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/RoomPollDataSource.kt @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * 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 im.vector.app.features.roomprofile.polls.list.data + +import im.vector.app.features.home.room.detail.timeline.item.PollOptionViewState +import im.vector.app.features.roomprofile.polls.list.ui.PollSummary +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf +import timber.log.Timber +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class RoomPollDataSource @Inject constructor() { + + // TODO + // unmock using SDK service + add unit tests + // after unmock, expose domain layer model (entity) and do the mapping to PollSummary in the UI layer + fun getPolls(roomId: String): Flow> { + Timber.d("roomId=$roomId") + return flowOf(getActivePolls() + getEndedPolls()) + } + + private fun getActivePolls(): List { + return listOf( + PollSummary.ActivePoll( + id = "id1", + // 2022/06/28 UTC+1 + creationTimestamp = 1656367200000, + title = "Which charity would you like to support?" + ), + PollSummary.ActivePoll( + id = "id2", + // 2022/06/26 UTC+1 + creationTimestamp = 1656194400000, + title = "Which sport should the pupils do this year?" + ), + PollSummary.ActivePoll( + id = "id3", + // 2022/06/24 UTC+1 + creationTimestamp = 1656021600000, + title = "What type of food should we have at the party?" + ), + PollSummary.ActivePoll( + id = "id4", + // 2022/06/22 UTC+1 + creationTimestamp = 1655848800000, + title = "What film should we show at the end of the year party?" + ), + ) + } + + private fun getEndedPolls(): List { + return listOf( + PollSummary.EndedPoll( + id = "id1-ended", + // 2022/06/28 UTC+1 + creationTimestamp = 1656367200000, + title = "Which charity would you like to support?", + totalVotes = 22, + winnerOptions = listOf( + PollOptionViewState.PollEnded( + optionId = "id1", + optionAnswer = "Cancer research", + voteCount = 13, + votePercentage = 13 / 22.0, + isWinner = true, + ) + ), + ), + PollSummary.EndedPoll( + id = "id2-ended", + // 2022/06/26 UTC+1 + creationTimestamp = 1656194400000, + title = "Where should we do the offsite?", + totalVotes = 92, + winnerOptions = listOf( + PollOptionViewState.PollEnded( + optionId = "id1", + optionAnswer = "Hawaii", + voteCount = 43, + votePercentage = 43 / 92.0, + isWinner = true, + ) + ), + ), + PollSummary.EndedPoll( + id = "id3-ended", + // 2022/06/24 UTC+1 + creationTimestamp = 1656021600000, + title = "What type of food should we have at the party?", + totalVotes = 22, + winnerOptions = listOf( + PollOptionViewState.PollEnded( + optionId = "id1", + optionAnswer = "Brazilian", + voteCount = 13, + votePercentage = 13 / 22.0, + isWinner = true, + ) + ), + ), + ) + } + + suspend fun loadMorePolls(roomId: String): LoadMorePollsResult { + Timber.d("roomId=$roomId") + // TODO + // mock getting more polls + update the given flow + // unmock using SDK service + add unit tests + delay(5000) + return LoadMorePollsResult(canLoadMore = false) + } +} 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 new file mode 100644 index 0000000000..f00fac711d --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/data/RoomPollRepository.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * 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 im.vector.app.features.roomprofile.polls.list.data + +import im.vector.app.features.roomprofile.polls.list.ui.PollSummary +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +// TODO add unit tests +class RoomPollRepository @Inject constructor( + private val roomPollDataSource: RoomPollDataSource, +) { + + // TODO after unmock, expose domain layer model (entity) and do the mapping to PollSummary in the UI layer + fun getPolls(roomId: String): Flow> { + return roomPollDataSource.getPolls(roomId) + } + + suspend fun loadMorePolls(roomId: String): LoadMorePollsResult { + return roomPollDataSource.loadMorePolls(roomId) + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/GetPollsUseCase.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/GetPollsUseCase.kt index b97eb7d032..c2dace1d6f 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/GetPollsUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/GetPollsUseCase.kt @@ -16,104 +16,19 @@ package im.vector.app.features.roomprofile.polls.list.domain -import im.vector.app.features.home.room.detail.timeline.item.PollOptionViewState +import im.vector.app.features.roomprofile.polls.list.data.RoomPollRepository import im.vector.app.features.roomprofile.polls.list.ui.PollSummary import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map -import timber.log.Timber import javax.inject.Inject // TODO add unit tests -class GetPollsUseCase @Inject constructor() { +class GetPollsUseCase @Inject constructor( + private val roomPollRepository: RoomPollRepository, +) { - // TODO create a repo + datasources (local + remote) with mocked data by passing a room Id fun execute(roomId: String): Flow> { - // TODO call repository to get flow on polls - Timber.d("roomId=$roomId") - return flowOf(getActivePolls() + getEndedPolls()) + return roomPollRepository.getPolls(roomId) .map { it.sortedByDescending { poll -> poll.creationTimestamp } } } - - private fun getActivePolls(): List { - return listOf( - PollSummary.ActivePoll( - id = "id1", - // 2022/06/28 UTC+1 - creationTimestamp = 1656367200000, - title = "Which charity would you like to support?" - ), - PollSummary.ActivePoll( - id = "id2", - // 2022/06/26 UTC+1 - creationTimestamp = 1656194400000, - title = "Which sport should the pupils do this year?" - ), - PollSummary.ActivePoll( - id = "id3", - // 2022/06/24 UTC+1 - creationTimestamp = 1656021600000, - title = "What type of food should we have at the party?" - ), - PollSummary.ActivePoll( - id = "id4", - // 2022/06/22 UTC+1 - creationTimestamp = 1655848800000, - title = "What film should we show at the end of the year party?" - ), - ) - } - - private fun getEndedPolls(): List { - return listOf( - PollSummary.EndedPoll( - id = "id1-ended", - // 2022/06/28 UTC+1 - creationTimestamp = 1656367200000, - title = "Which charity would you like to support?", - totalVotes = 22, - winnerOptions = listOf( - PollOptionViewState.PollEnded( - optionId = "id1", - optionAnswer = "Cancer research", - voteCount = 13, - votePercentage = 13 / 22.0, - isWinner = true, - ) - ), - ), - PollSummary.EndedPoll( - id = "id2-ended", - // 2022/06/26 UTC+1 - creationTimestamp = 1656194400000, - title = "Where should we do the offsite?", - totalVotes = 92, - winnerOptions = listOf( - PollOptionViewState.PollEnded( - optionId = "id1", - optionAnswer = "Hawaii", - voteCount = 43, - votePercentage = 43 / 92.0, - isWinner = true, - ) - ), - ), - PollSummary.EndedPoll( - id = "id3-ended", - // 2022/06/24 UTC+1 - creationTimestamp = 1656021600000, - title = "What type of food should we have at the party?", - totalVotes = 22, - winnerOptions = listOf( - PollOptionViewState.PollEnded( - optionId = "id1", - optionAnswer = "Brazilian", - voteCount = 13, - votePercentage = 13 / 22.0, - isWinner = true, - ) - ), - ), - ) - } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/LoadMorePollsUseCase.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/LoadMorePollsUseCase.kt index 2ed50786aa..fc74a7d581 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/LoadMorePollsUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/domain/LoadMorePollsUseCase.kt @@ -16,16 +16,16 @@ package im.vector.app.features.roomprofile.polls.list.domain -import kotlinx.coroutines.delay -import timber.log.Timber +import im.vector.app.features.roomprofile.polls.list.data.LoadMorePollsResult +import im.vector.app.features.roomprofile.polls.list.data.RoomPollRepository import javax.inject.Inject // TODO add unit tests -class LoadMorePollsUseCase @Inject constructor() { +class LoadMorePollsUseCase @Inject constructor( + private val roomPollRepository: RoomPollRepository, +) { - suspend fun execute(roomId: String) { - // TODO call repository to load more polls to be published in a flow - Timber.d("roomId=$roomId") - delay(5000) + suspend fun execute(roomId: String): LoadMorePollsResult { + return roomPollRepository.loadMorePolls(roomId) } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/ui/RoomPollsController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/ui/RoomPollsController.kt index 5a2bc0a4b5..3009b07374 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/ui/RoomPollsController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/ui/RoomPollsController.kt @@ -50,7 +50,9 @@ class RoomPollsController @Inject constructor( } } - buildLoadMoreItem(viewState.isLoadingMore) + if (viewState.canLoadMore) { + buildLoadMoreItem(viewState.isLoadingMore) + } } private fun buildActivePollItem(poll: PollSummary.ActivePoll) {