mirror of
https://github.com/element-hq/element-android
synced 2024-11-27 03:48:12 +03:00
Fake loading more process
This commit is contained in:
parent
e8e94b5189
commit
dba9e29881
11 changed files with 102 additions and 27 deletions
|
@ -18,4 +18,6 @@ package im.vector.app.features.roomprofile.polls
|
|||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
|
||||
sealed interface RoomPollsAction : VectorViewModelAction
|
||||
sealed interface RoomPollsAction : VectorViewModelAction {
|
||||
object LoadMorePolls : RoomPollsAction
|
||||
}
|
||||
|
|
|
@ -23,12 +23,16 @@ import dagger.assisted.AssistedInject
|
|||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.roomprofile.polls.list.domain.GetPollsUseCase
|
||||
import im.vector.app.features.roomprofile.polls.list.domain.LoadMorePollsUseCase
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class RoomPollsViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: RoomPollsViewState,
|
||||
private val getPollsUseCase: GetPollsUseCase,
|
||||
private val loadMorePollsUseCase: LoadMorePollsUseCase,
|
||||
) : VectorViewModel<RoomPollsViewState, RoomPollsAction, RoomPollsViewEvent>(initialState) {
|
||||
|
||||
@AssistedFactory
|
||||
|
@ -42,13 +46,24 @@ class RoomPollsViewModel @AssistedInject constructor(
|
|||
observePolls()
|
||||
}
|
||||
|
||||
private fun observePolls() {
|
||||
getPollsUseCase.execute()
|
||||
private fun observePolls() = withState { viewState ->
|
||||
getPollsUseCase.execute(viewState.roomId)
|
||||
.onEach { setState { copy(polls = it) } }
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
// TODO add unit tests
|
||||
override fun handle(action: RoomPollsAction) {
|
||||
// do nothing for now
|
||||
when (action) {
|
||||
RoomPollsAction.LoadMorePolls -> handleLoadMore()
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleLoadMore() = withState { viewState ->
|
||||
viewModelScope.launch {
|
||||
setState { copy(isLoadingMore = true) }
|
||||
loadMorePollsUseCase.execute(viewState.roomId)
|
||||
setState { copy(isLoadingMore = false) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,10 +18,14 @@ package im.vector.app.features.roomprofile.polls
|
|||
|
||||
import com.airbnb.mvrx.MavericksState
|
||||
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||
import im.vector.app.features.roomprofile.polls.list.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<PollSummary> = emptyList(),
|
||||
val isLoadingMore: Boolean = false,
|
||||
) : MavericksState {
|
||||
|
||||
constructor(roomProfileArgs: RoomProfileArgs) : this(roomId = roomProfileArgs.roomId)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
* 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.
|
||||
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.roomprofile.polls
|
||||
package im.vector.app.features.roomprofile.polls.list
|
||||
|
||||
import im.vector.app.features.home.room.detail.timeline.item.PollOptionViewState
|
||||
|
|
@ -17,6 +17,8 @@
|
|||
package im.vector.app.features.roomprofile.polls.list
|
||||
|
||||
import android.widget.Button
|
||||
import android.widget.ProgressBar
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
|
@ -28,15 +30,21 @@ import im.vector.app.core.epoxy.onClick
|
|||
@EpoxyModelClass
|
||||
abstract class RoomPollLoadMoreItem : VectorEpoxyModel<RoomPollLoadMoreItem.Holder>(R.layout.item_poll_load_more) {
|
||||
|
||||
@EpoxyAttribute
|
||||
var loadingMore: Boolean = false
|
||||
|
||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
|
||||
var clickListener: ClickListener? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.loadMoreButton.isEnabled = loadingMore.not()
|
||||
holder.loadMoreButton.onClick(clickListener)
|
||||
holder.loadMoreProgressBar.isVisible = loadingMore
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val loadMoreButton by bind<Button>(R.id.roomPollsLoadMore)
|
||||
val loadMoreProgressBar by bind<ProgressBar>(R.id.roomPollsLoadMoreProgress)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,13 +21,14 @@ import im.vector.app.R
|
|||
import im.vector.app.core.date.DateFormatKind
|
||||
import im.vector.app.core.date.VectorDateFormatter
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.roomprofile.polls.PollSummary
|
||||
import im.vector.app.features.roomprofile.polls.RoomPollsViewState
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomPollsController @Inject constructor(
|
||||
val dateFormatter: VectorDateFormatter,
|
||||
val stringProvider: StringProvider,
|
||||
) : TypedEpoxyController<List<PollSummary>>() {
|
||||
) : TypedEpoxyController<RoomPollsViewState>() {
|
||||
|
||||
interface Listener {
|
||||
fun onPollClicked(pollId: String)
|
||||
|
@ -36,19 +37,20 @@ class RoomPollsController @Inject constructor(
|
|||
|
||||
var listener: Listener? = null
|
||||
|
||||
override fun buildModels(data: List<PollSummary>?) {
|
||||
if (data.isNullOrEmpty()) {
|
||||
override fun buildModels(viewState: RoomPollsViewState?) {
|
||||
val polls = viewState?.polls
|
||||
if (polls.isNullOrEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
for (poll in data) {
|
||||
for (poll in polls) {
|
||||
when (poll) {
|
||||
is PollSummary.ActivePoll -> buildActivePollItem(poll)
|
||||
is PollSummary.EndedPoll -> buildEndedPollItem(poll)
|
||||
}
|
||||
}
|
||||
|
||||
buildLoadMoreItem()
|
||||
buildLoadMoreItem(viewState.isLoadingMore)
|
||||
}
|
||||
|
||||
private fun buildActivePollItem(poll: PollSummary.ActivePoll) {
|
||||
|
@ -77,11 +79,14 @@ class RoomPollsController @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun buildLoadMoreItem() {
|
||||
private fun buildLoadMoreItem(isLoadingMore: Boolean) {
|
||||
val host = this
|
||||
roomPollLoadMoreItem {
|
||||
id("roomPollLoadMore")
|
||||
host.listener?.onLoadMoreClicked()
|
||||
id(UUID.randomUUID().toString())
|
||||
loadingMore(isLoadingMore)
|
||||
clickListener {
|
||||
host.listener?.onLoadMoreClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,10 @@ import im.vector.app.core.extensions.cleanup
|
|||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentRoomPollsListBinding
|
||||
import im.vector.app.features.roomprofile.polls.PollSummary
|
||||
import im.vector.app.features.roomprofile.polls.RoomPollsAction
|
||||
import im.vector.app.features.roomprofile.polls.RoomPollsType
|
||||
import im.vector.app.features.roomprofile.polls.RoomPollsViewModel
|
||||
import im.vector.app.features.roomprofile.polls.RoomPollsViewState
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -74,15 +75,16 @@ abstract class RoomPollsListFragment :
|
|||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) { viewState ->
|
||||
when (getRoomPollsType()) {
|
||||
RoomPollsType.ACTIVE -> renderList(viewState.polls.filterIsInstance(PollSummary.ActivePoll::class.java))
|
||||
RoomPollsType.ENDED -> renderList(viewState.polls.filterIsInstance(PollSummary.EndedPoll::class.java))
|
||||
val filteredPolls = when (getRoomPollsType()) {
|
||||
RoomPollsType.ACTIVE -> viewState.polls.filterIsInstance(PollSummary.ActivePoll::class.java)
|
||||
RoomPollsType.ENDED -> viewState.polls.filterIsInstance(PollSummary.EndedPoll::class.java)
|
||||
}
|
||||
renderList(viewState.copy(polls = filteredPolls))
|
||||
}
|
||||
|
||||
private fun renderList(polls: List<PollSummary>) {
|
||||
roomPollsController.setData(polls)
|
||||
views.roomPollsEmptyTitle.isVisible = polls.isEmpty()
|
||||
private fun renderList(viewState: RoomPollsViewState) {
|
||||
roomPollsController.setData(viewState)
|
||||
views.roomPollsEmptyTitle.isVisible = viewState.polls.isEmpty()
|
||||
}
|
||||
|
||||
override fun onPollClicked(pollId: String) {
|
||||
|
@ -91,6 +93,6 @@ abstract class RoomPollsListFragment :
|
|||
}
|
||||
|
||||
override fun onLoadMoreClicked() {
|
||||
// TODO call viewAction
|
||||
viewModel.handle(RoomPollsAction.LoadMorePolls)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
* 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.
|
||||
|
@ -14,18 +14,23 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.roomprofile.polls
|
||||
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.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() {
|
||||
|
||||
fun execute(): Flow<List<PollSummary>> {
|
||||
// TODO unmock and add unit tests
|
||||
// TODO create a repo + datasources (local + remote) with mocked data by passing a room Id
|
||||
fun execute(roomId: String): Flow<List<PollSummary>> {
|
||||
// TODO call repository to get flow on polls
|
||||
Timber.d("roomId=$roomId")
|
||||
return flowOf(getActivePolls() + getEndedPolls())
|
||||
.map { it.sortedByDescending { poll -> poll.creationTimestamp } }
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.domain
|
||||
|
||||
import kotlinx.coroutines.delay
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
// TODO add unit tests
|
||||
class LoadMorePollsUseCase @Inject constructor() {
|
||||
|
||||
suspend fun execute(roomId: String) {
|
||||
// TODO call repository to load more polls to be published in a flow
|
||||
Timber.d("roomId=$roomId")
|
||||
delay(5000)
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
android:layout_marginBottom="46dp"
|
||||
android:padding="0dp"
|
||||
android:text="@string/room_polls_load_more"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package im.vector.app.features.roomprofile.polls
|
||||
|
||||
import com.airbnb.mvrx.test.MavericksTestRule
|
||||
import im.vector.app.features.roomprofile.polls.list.PollSummary
|
||||
import im.vector.app.features.roomprofile.polls.list.domain.GetPollsUseCase
|
||||
import im.vector.app.test.test
|
||||
import im.vector.app.test.testDispatcher
|
||||
import io.mockk.every
|
||||
|
|
Loading…
Reference in a new issue