Skip to content

Commit

Permalink
fix: Scroll states, animations
Browse files Browse the repository at this point in the history
  • Loading branch information
Lastaapps committed May 21, 2024
1 parent 8a249e0 commit 1e704e6
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Videocam
import androidx.compose.material3.FloatingActionButton
Expand All @@ -42,6 +40,8 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.listSaver
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
Expand All @@ -52,11 +52,11 @@ import cz.lastaapps.menza.features.settings.domain.model.DishListMode
import cz.lastaapps.menza.features.settings.domain.model.DishListMode.COMPACT
import cz.lastaapps.menza.features.settings.domain.model.DishListMode.GRID
import cz.lastaapps.menza.features.settings.domain.model.DishListMode.HORIZONTAL
import cz.lastaapps.menza.features.settings.ui.widget.ImageSizeSetting
import cz.lastaapps.menza.features.today.ui.vm.DishListState
import cz.lastaapps.menza.features.today.ui.vm.DishListViewModel
import cz.lastaapps.menza.features.today.ui.widget.DishListViewModeSwitch
import cz.lastaapps.menza.features.today.ui.widget.Experimental
import cz.lastaapps.menza.features.today.ui.widget.ImageSizeSetting
import cz.lastaapps.menza.features.today.ui.widget.TodayDishGrid
import cz.lastaapps.menza.features.today.ui.widget.TodayDishHorizontal
import cz.lastaapps.menza.features.today.ui.widget.TodayDishList
Expand All @@ -70,8 +70,7 @@ internal fun DishListScreen(
viewModel: DishListViewModel,
hostState: SnackbarHostState,
modifier: Modifier = Modifier,
scrollState: LazyListState = rememberLazyListState(),
scrollGridState: LazyStaggeredGridState = rememberLazyStaggeredGridState(),
scrollStates: ScrollStates,
) {
DishListEffects(viewModel, hostState)

Expand All @@ -86,8 +85,7 @@ internal fun DishListScreen(
onImageScale = viewModel::setImageScale,
onOliverRow = viewModel::setOliverRow,
onDishSelected = onDishSelected,
scrollListState = scrollState,
scrollGridState = scrollGridState,
scrollStates = scrollStates,
)
}

Expand All @@ -111,8 +109,7 @@ private fun DishListContent(
onImageScale: (Float) -> Unit,
onDishSelected: (Dish) -> Unit,
onOliverRow: (Boolean) -> Unit,
scrollListState: LazyListState,
scrollGridState: LazyStaggeredGridState,
scrollStates: ScrollStates,
modifier: Modifier = Modifier,
) = Column {
val userSettings = state.userSettings
Expand Down Expand Up @@ -181,7 +178,7 @@ private fun DishListContent(
}
},
modifier = modifier.fillMaxSize(),
scroll = scrollListState,
scroll = scrollStates.list,
)

GRID ->
Expand All @@ -201,7 +198,7 @@ private fun DishListContent(
}
},
modifier = modifier.fillMaxSize(),
scrollGrid = scrollGridState,
scrollGrid = scrollStates.grid,
)

HORIZONTAL ->
Expand All @@ -222,7 +219,7 @@ private fun DishListContent(
}
},
modifier = modifier.fillMaxSize(),
scroll = scrollListState,
scroll = scrollStates.horizontal,
)

null -> {}
Expand All @@ -249,4 +246,35 @@ private fun LiveVideoFeedFab(
modifier = Modifier.size(size / 2),
)
}
}

/**
* Holds all the scroll states for different scroll modes.
* The states must not be shared as some animations will get broken
*/
internal data class ScrollStates(
val list: LazyListState = LazyListState(),
val grid: LazyStaggeredGridState = LazyStaggeredGridState(),
val horizontal: LazyListState = LazyListState(),
) {
companion object {
val Saver: Saver<ScrollStates, *> = listSaver(
save = {
listOf(
with(LazyListState.Saver) { save(it.list) },
with(LazyStaggeredGridState.Saver) { save(it.grid) },
with(LazyListState.Saver) { save(it.horizontal) },
)
},
restore = { list ->
@Suppress("UNCHECKED_CAST")
val llsSaver = LazyListState.Saver as Saver<LazyListState, Any>
ScrollStates(
list[0]?.let { llsSaver.restore(it) }!!,
list[1]?.let { LazyStaggeredGridState.Saver.restore(it) }!!,
list[2]?.let { llsSaver.restore(it) }!!,
)
},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ErrorOutline
import androidx.compose.material.icons.filled.Videocam
Expand Down Expand Up @@ -113,14 +111,10 @@ private fun TodayContent(
modifier: Modifier = Modifier,

// resets scroll position when new menza is selected
scrollState: LazyListState = rememberSaveable(
scrollStates: ScrollStates = rememberSaveable(
state.selectedMenza,
saver = LazyListState.Saver,
) { LazyListState() },
scrollGridState: LazyStaggeredGridState = rememberSaveable(
state.selectedMenza,
saver = LazyStaggeredGridState.Saver,
) { LazyStaggeredGridState() },
saver = ScrollStates.Saver,
) { ScrollStates() },
) {
var videoFeedUrl by remember(state.selectedMenza) {
mutableStateOf<String?>(null)
Expand All @@ -133,8 +127,7 @@ private fun TodayContent(
viewModel = dishListViewModel,
modifier = Modifier.fillMaxSize(),
hostState = hostState,
scrollState = scrollState,
scrollGridState = scrollGridState,
scrollStates = scrollStates,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* along with Menza. If not, see <https://www.gnu.org/licenses/>.
*/

package cz.lastaapps.menza.features.settings.ui.widget
package cz.lastaapps.menza.features.today.ui.widget

import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.interaction.MutableInteractionSource
Expand Down Expand Up @@ -49,7 +49,7 @@ import cz.lastaapps.menza.ui.theme.Padding
import cz.lastaapps.menza.ui.util.PreviewWrapper

private const val imageSizeMin = .5f
private const val imageSizeMax = 3f
private const val imageSizeMax = 2f

@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
Expand Down Expand Up @@ -127,13 +128,13 @@ private fun DishContent(
}

data.forEach { category ->
item {
item(key = category.name + "_cat_header") {
DishHeader(
courseType = category,
modifier = Modifier.padding(bottom = Padding.Smaller),
)
}
item {
item(key = category.name + "_content") {
val isOnlyItem = category.dishList.size == 1

if (isOnlyItem) {
Expand All @@ -142,7 +143,9 @@ private fun DishContent(
onDishSelected = onDishSelected,
userSettings = userSettings,
isOnMetered = isOnMetered,
modifier = Modifier.fillMaxWidth(),
modifier = Modifier
.fillMaxWidth()
.animateItem(),
)
} else {

Expand All @@ -168,6 +171,7 @@ private fun DishContent(
modifier = Modifier
.fillMaxWidth()
.horizontalScroll(rememberScrollState())
.animateItem()
.animateContentSize(),
) {
category.dishList.forEach { dish ->
Expand All @@ -180,6 +184,7 @@ private fun DishContent(
horizontalArrangement = horizontalArrangement,
modifier = Modifier
.fillMaxWidth()
.animateItem()
.animateContentSize(),
) {
items(
Expand Down Expand Up @@ -249,7 +254,7 @@ private fun DishItem(
) {
DishNameRow(
dish = dish,
modifier = modifier.weight(1f),
modifier = Modifier.weight(1f),
)
if (dish.photoLink == null) {
DishBadge(
Expand Down Expand Up @@ -324,4 +329,5 @@ private fun OliverRowSwitch(
}
}

private fun amIOliver() = Build.MODEL == "CPH2305"
@Composable
private fun amIOliver() = remember { Build.MODEL == "CPH2305" }
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ private fun DishContent(
val placedItems = 2 + // header, footer
data.size + // sticky headers
data.sumOf { it.dishList.size } // items
delay(420.milliseconds)
// as the other nodes are resizing, we need to wait for them to (almost) stop
delay(666.milliseconds)
scroll.animateScrollToItem(placedItems)
}
}
Expand Down

0 comments on commit 1e704e6

Please sign in to comment.