Poll history : use pager to keep scrolling state when switching filter
This commit is contained in:
parent
99e3ac7c63
commit
424e9e266e
6 changed files with 82 additions and 38 deletions
|
|
@ -23,6 +23,5 @@ sealed interface PollHistoryEvents {
|
||||||
data object LoadMore : PollHistoryEvents
|
data object LoadMore : PollHistoryEvents
|
||||||
data class PollAnswerSelected(val pollStartId: EventId, val answerId: String) : PollHistoryEvents
|
data class PollAnswerSelected(val pollStartId: EventId, val answerId: String) : PollHistoryEvents
|
||||||
data class PollEndClicked(val pollStartId: EventId) : PollHistoryEvents
|
data class PollEndClicked(val pollStartId: EventId) : PollHistoryEvents
|
||||||
data object EditPoll : PollHistoryEvents
|
|
||||||
data class OnFilterSelected(val filter: PollHistoryFilter) : PollHistoryEvents
|
data class OnFilterSelected(val filter: PollHistoryFilter) : PollHistoryEvents
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ class PollHistoryNode @AssistedInject constructor(
|
||||||
PollHistoryView(
|
PollHistoryView(
|
||||||
state = presenter.present(),
|
state = presenter.present(),
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
onEditPoll = {},
|
||||||
goBack = this::navigateUp,
|
goBack = this::navigateUp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ import io.element.android.libraries.matrix.ui.room.rememberPollHistory
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class PollHistoryPresenter @Inject constructor(
|
class PollHistoryPresenter @Inject constructor(
|
||||||
|
|
@ -82,32 +81,23 @@ class PollHistoryPresenter @Inject constructor(
|
||||||
is PollHistoryEvents.PollEndClicked -> appCoroutineScope.launch {
|
is PollHistoryEvents.PollEndClicked -> appCoroutineScope.launch {
|
||||||
endPollAction.execute(pollStartId = event.pollStartId)
|
endPollAction.execute(pollStartId = event.pollStartId)
|
||||||
}
|
}
|
||||||
PollHistoryEvents.EditPoll -> Unit
|
|
||||||
is PollHistoryEvents.OnFilterSelected -> {
|
is PollHistoryEvents.OnFilterSelected -> {
|
||||||
activeFilter = event.filter
|
activeFilter = event.filter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentItems by remember {
|
|
||||||
derivedStateOf {
|
|
||||||
when (activeFilter) {
|
|
||||||
PollHistoryFilter.ONGOING -> pollHistoryItems.ongoing
|
|
||||||
PollHistoryFilter.PAST -> pollHistoryItems.past
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return PollHistoryState(
|
return PollHistoryState(
|
||||||
isLoading = isLoading,
|
isLoading = isLoading,
|
||||||
hasMoreToLoad = paginationState.hasMoreToLoadBackwards,
|
hasMoreToLoad = paginationState.hasMoreToLoadBackwards,
|
||||||
currentItems = currentItems,
|
pollHistoryItems = pollHistoryItems,
|
||||||
activeFilter = activeFilter,
|
activeFilter = activeFilter,
|
||||||
eventSink = ::handleEvents,
|
eventSink = ::handleEvents,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CoroutineScope.loadMore(pollHistory: MatrixTimeline) = launch {
|
private fun CoroutineScope.loadMore(pollHistory: MatrixTimeline) = launch {
|
||||||
Timber.d("LoadMore poll history")
|
pollHistory.paginateBackwards(200)
|
||||||
pollHistory.paginateBackwards(50, 3)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.PollHistoryFilter
|
||||||
import io.element.android.features.poll.impl.history.model.PollHistoryItem
|
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.ImmutableList
|
||||||
|
|
||||||
data class PollHistoryState(
|
data class PollHistoryState(
|
||||||
val isLoading: Boolean,
|
val isLoading: Boolean,
|
||||||
val hasMoreToLoad: Boolean,
|
val hasMoreToLoad: Boolean,
|
||||||
val activeFilter: PollHistoryFilter,
|
val activeFilter: PollHistoryFilter,
|
||||||
val currentItems: ImmutableList<PollHistoryItem>,
|
val pollHistoryItems: PollHistoryItems,
|
||||||
val eventSink: (PollHistoryEvents) -> Unit,
|
val eventSink: (PollHistoryEvents) -> Unit,
|
||||||
)
|
) {
|
||||||
|
|
||||||
|
fun pollHistoryForFilter(filter: PollHistoryFilter): ImmutableList<PollHistoryItem> {
|
||||||
|
return when (filter) {
|
||||||
|
PollHistoryFilter.ONGOING -> pollHistoryItems.ongoing
|
||||||
|
PollHistoryFilter.PAST -> pollHistoryItems.past
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.api.pollcontent.aPollContentState
|
||||||
import io.element.android.features.poll.impl.history.model.PollHistoryFilter
|
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.PollHistoryItem
|
||||||
|
import io.element.android.features.poll.impl.history.model.PollHistoryItems
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
|
|
@ -51,7 +52,9 @@ private fun aPollHistoryState(
|
||||||
isLoading = isLoading,
|
isLoading = isLoading,
|
||||||
hasMoreToLoad = hasMoreToLoad,
|
hasMoreToLoad = hasMoreToLoad,
|
||||||
activeFilter = activeFilter,
|
activeFilter = activeFilter,
|
||||||
currentItems = currentItems,
|
pollHistoryItems = PollHistoryItems(
|
||||||
|
ongoing = currentItems,
|
||||||
|
past = currentItems,),
|
||||||
eventSink = {},
|
eventSink = {},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package io.element.android.features.poll.impl.history
|
package io.element.android.features.poll.impl.history
|
||||||
|
|
||||||
import androidx.compose.foundation.BorderStroke
|
import androidx.compose.foundation.BorderStroke
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
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.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
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.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
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.Text
|
||||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun PollHistoryView(
|
fun PollHistoryView(
|
||||||
state: PollHistoryState,
|
state: PollHistoryState,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
onEditPoll: (EventId) -> Unit,
|
||||||
goBack: () -> 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(
|
Scaffold(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
topBar = {
|
topBar = {
|
||||||
|
|
@ -79,6 +99,12 @@ fun PollHistoryView(
|
||||||
.padding(padding)
|
.padding(padding)
|
||||||
.consumeWindowInsets(padding)
|
.consumeWindowInsets(padding)
|
||||||
) {
|
) {
|
||||||
|
val pagerState = rememberPagerState(state.activeFilter.ordinal, 0f) {
|
||||||
|
PollHistoryFilter.entries.size
|
||||||
|
}
|
||||||
|
LaunchedEffect(state.activeFilter) {
|
||||||
|
pagerState.scrollToPage(state.activeFilter.ordinal)
|
||||||
|
}
|
||||||
PollHistoryFilterButtons(
|
PollHistoryFilterButtons(
|
||||||
activeFilter = state.activeFilter,
|
activeFilter = state.activeFilter,
|
||||||
onFilterSelected = { state.eventSink(PollHistoryEvents.OnFilterSelected(it)) },
|
onFilterSelected = { state.eventSink(PollHistoryEvents.OnFilterSelected(it)) },
|
||||||
|
|
@ -86,10 +112,25 @@ fun PollHistoryView(
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
)
|
)
|
||||||
PollHistoryList(
|
HorizontalPager(
|
||||||
state = state,
|
state = pagerState,
|
||||||
modifier = Modifier.fillMaxSize()
|
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
|
@Composable
|
||||||
private fun PollHistoryList(
|
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,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
val lazyListState = rememberLazyListState()
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
|
state = lazyListState,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
items(state.currentItems) { pollHistoryItem ->
|
items(pollHistoryItems) { pollHistoryItem ->
|
||||||
PollHistoryItemRow(
|
PollHistoryItemRow(
|
||||||
pollHistoryItem = pollHistoryItem,
|
pollHistoryItem = pollHistoryItem,
|
||||||
onAnswerSelected = fun(pollStartId: EventId, answerId: String) {
|
onAnswerSelected = onAnswerSelected,
|
||||||
state.eventSink(PollHistoryEvents.PollAnswerSelected(pollStartId, answerId))
|
onPollEdit = onPollEdit,
|
||||||
},
|
onPollEnd = onPollEnd,
|
||||||
onPollEdit = {
|
|
||||||
state.eventSink(PollHistoryEvents.EditPoll)
|
|
||||||
},
|
|
||||||
onPollEnd = {
|
|
||||||
state.eventSink(PollHistoryEvents.PollEndClicked(it))
|
|
||||||
},
|
|
||||||
modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp)
|
modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (state.hasMoreToLoad) {
|
if (hasMoreToLoad) {
|
||||||
item {
|
item {
|
||||||
Button(
|
Button(
|
||||||
text = "Load more",
|
text = "Load more",
|
||||||
showProgress = state.isLoading,
|
showProgress = isLoading,
|
||||||
onClick = {
|
onClick = onLoadMore,
|
||||||
state.eventSink(PollHistoryEvents.LoadMore)
|
|
||||||
},
|
|
||||||
modifier = Modifier.padding(vertical = 24.dp),
|
modifier = Modifier.padding(vertical = 24.dp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -190,6 +231,7 @@ internal fun PollHistoryViewPreview(
|
||||||
) = ElementPreview {
|
) = ElementPreview {
|
||||||
PollHistoryView(
|
PollHistoryView(
|
||||||
state = state,
|
state = state,
|
||||||
|
onEditPoll = {},
|
||||||
goBack = {},
|
goBack = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue