Poll history : use pager to keep scrolling state when switching filter

This commit is contained in:
ganfra 2023-12-12 14:24:41 +01:00
parent 449c331879
commit 7307e0fb13
6 changed files with 82 additions and 38 deletions

View file

@ -23,6 +23,5 @@ sealed interface PollHistoryEvents {
data object LoadMore : PollHistoryEvents
data class PollAnswerSelected(val pollStartId: EventId, val answerId: String) : PollHistoryEvents
data class PollEndClicked(val pollStartId: EventId) : PollHistoryEvents
data object EditPoll : PollHistoryEvents
data class OnFilterSelected(val filter: PollHistoryFilter) : PollHistoryEvents
}

View file

@ -41,6 +41,7 @@ class PollHistoryNode @AssistedInject constructor(
PollHistoryView(
state = presenter.present(),
modifier = modifier,
onEditPoll = {},
goBack = this::navigateUp,
)
}

View file

@ -38,7 +38,6 @@ import io.element.android.libraries.matrix.ui.room.rememberPollHistory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
class PollHistoryPresenter @Inject constructor(
@ -82,32 +81,23 @@ class PollHistoryPresenter @Inject constructor(
is PollHistoryEvents.PollEndClicked -> appCoroutineScope.launch {
endPollAction.execute(pollStartId = event.pollStartId)
}
PollHistoryEvents.EditPoll -> Unit
is PollHistoryEvents.OnFilterSelected -> {
activeFilter = event.filter
}
}
}
val currentItems by remember {
derivedStateOf {
when (activeFilter) {
PollHistoryFilter.ONGOING -> pollHistoryItems.ongoing
PollHistoryFilter.PAST -> pollHistoryItems.past
}
}
}
return PollHistoryState(
isLoading = isLoading,
hasMoreToLoad = paginationState.hasMoreToLoadBackwards,
currentItems = currentItems,
pollHistoryItems = pollHistoryItems,
activeFilter = activeFilter,
eventSink = ::handleEvents,
)
}
private fun CoroutineScope.loadMore(pollHistory: MatrixTimeline) = launch {
Timber.d("LoadMore poll history")
pollHistory.paginateBackwards(50, 3)
pollHistory.paginateBackwards(200)
}
}

View file

@ -18,12 +18,21 @@ package io.element.android.features.poll.impl.history
import io.element.android.features.poll.impl.history.model.PollHistoryFilter
import io.element.android.features.poll.impl.history.model.PollHistoryItem
import io.element.android.features.poll.impl.history.model.PollHistoryItems
import kotlinx.collections.immutable.ImmutableList
data class PollHistoryState(
val isLoading: Boolean,
val hasMoreToLoad: Boolean,
val activeFilter: PollHistoryFilter,
val currentItems: ImmutableList<PollHistoryItem>,
val pollHistoryItems: PollHistoryItems,
val eventSink: (PollHistoryEvents) -> Unit,
)
) {
fun pollHistoryForFilter(filter: PollHistoryFilter): ImmutableList<PollHistoryItem> {
return when (filter) {
PollHistoryFilter.ONGOING -> pollHistoryItems.ongoing
PollHistoryFilter.PAST -> pollHistoryItems.past
}
}
}

View file

@ -21,6 +21,7 @@ import io.element.android.features.poll.api.pollcontent.PollContentState
import io.element.android.features.poll.api.pollcontent.aPollContentState
import io.element.android.features.poll.impl.history.model.PollHistoryFilter
import io.element.android.features.poll.impl.history.model.PollHistoryItem
import io.element.android.features.poll.impl.history.model.PollHistoryItems
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
@ -51,7 +52,9 @@ private fun aPollHistoryState(
isLoading = isLoading,
hasMoreToLoad = hasMoreToLoad,
activeFilter = activeFilter,
currentItems = currentItems,
pollHistoryItems = PollHistoryItems(
ongoing = currentItems,
past = currentItems,),
eventSink = {},
)

View file

@ -17,6 +17,7 @@
package io.element.android.features.poll.impl.history
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.consumeWindowInsets
@ -26,11 +27,15 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.PreviewParameter
@ -50,14 +55,29 @@ import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.matrix.api.core.EventId
import kotlinx.collections.immutable.ImmutableList
@OptIn(ExperimentalMaterial3Api::class)
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
fun PollHistoryView(
state: PollHistoryState,
modifier: Modifier = Modifier,
onEditPoll: (EventId) -> Unit,
goBack: () -> Unit,
) {
fun onLoadMore() {
state.eventSink(PollHistoryEvents.LoadMore)
}
fun onAnswerSelected(pollStartId: EventId, answerId: String) {
state.eventSink(PollHistoryEvents.PollAnswerSelected(pollStartId, answerId))
}
fun onPollEnd(pollStartId: EventId) {
state.eventSink(PollHistoryEvents.PollEndClicked(pollStartId))
}
Scaffold(
modifier = modifier,
topBar = {
@ -79,6 +99,12 @@ fun PollHistoryView(
.padding(padding)
.consumeWindowInsets(padding)
) {
val pagerState = rememberPagerState(state.activeFilter.ordinal, 0f) {
PollHistoryFilter.entries.size
}
LaunchedEffect(state.activeFilter) {
pagerState.scrollToPage(state.activeFilter.ordinal)
}
PollHistoryFilterButtons(
activeFilter = state.activeFilter,
onFilterSelected = { state.eventSink(PollHistoryEvents.OnFilterSelected(it)) },
@ -86,10 +112,25 @@ fun PollHistoryView(
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
)
PollHistoryList(
state = state,
modifier = Modifier.fillMaxSize()
)
HorizontalPager(
state = pagerState,
userScrollEnabled = false,
modifier = modifier.fillMaxSize()
) { page ->
val filter = PollHistoryFilter.entries[page]
val pollHistoryItems = state.pollHistoryForFilter(filter)
PollHistoryList(
pollHistoryItems = pollHistoryItems,
hasMoreToLoad = state.hasMoreToLoad,
isLoading = state.isLoading,
onAnswerSelected = ::onAnswerSelected,
onPollEdit = onEditPoll,
onPollEnd = ::onPollEnd,
onLoadMore = ::onLoadMore,
modifier = Modifier.fillMaxSize(),
)
}
}
}
}
@ -116,36 +157,36 @@ private fun PollHistoryFilterButtons(
@Composable
private fun PollHistoryList(
state: PollHistoryState,
pollHistoryItems: ImmutableList<PollHistoryItem>,
hasMoreToLoad: Boolean,
isLoading: Boolean,
onAnswerSelected: (pollStartId: EventId, answerId: String) -> Unit,
onPollEdit: (pollStartId: EventId) -> Unit,
onPollEnd: (pollStartId: EventId) -> Unit,
onLoadMore: () -> Unit,
modifier: Modifier = Modifier,
) {
val lazyListState = rememberLazyListState()
LazyColumn(
state = lazyListState,
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally,
) {
items(state.currentItems) { pollHistoryItem ->
items(pollHistoryItems) { pollHistoryItem ->
PollHistoryItemRow(
pollHistoryItem = pollHistoryItem,
onAnswerSelected = fun(pollStartId: EventId, answerId: String) {
state.eventSink(PollHistoryEvents.PollAnswerSelected(pollStartId, answerId))
},
onPollEdit = {
state.eventSink(PollHistoryEvents.EditPoll)
},
onPollEnd = {
state.eventSink(PollHistoryEvents.PollEndClicked(it))
},
onAnswerSelected = onAnswerSelected,
onPollEdit = onPollEdit,
onPollEnd = onPollEnd,
modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp)
)
}
if (state.hasMoreToLoad) {
if (hasMoreToLoad) {
item {
Button(
text = "Load more",
showProgress = state.isLoading,
onClick = {
state.eventSink(PollHistoryEvents.LoadMore)
},
showProgress = isLoading,
onClick = onLoadMore,
modifier = Modifier.padding(vertical = 24.dp),
)
}
@ -190,6 +231,7 @@ internal fun PollHistoryViewPreview(
) = ElementPreview {
PollHistoryView(
state = state,
onEditPoll = {},
goBack = {},
)
}