mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-04-10 04:49:25 +02:00
Fixes long term issue with the video in the Shorts feed not aligning with the padding of the screen
This commit is contained in:
parent
86e6d56dcd
commit
d320b951ae
@ -20,7 +20,6 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.feeds
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.grid.LazyGridState
|
||||
import androidx.compose.foundation.pager.PagerState
|
||||
@ -115,20 +114,35 @@ fun rememberForeverLazyListState(
|
||||
return scrollState
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun rememberForeverPagerState(
|
||||
key: String,
|
||||
initialFirstVisibleItemIndex: Int = 0,
|
||||
initialFirstVisibleItemScrollOffset: Float = 0.0f,
|
||||
pageCount: () -> Int,
|
||||
): PagerState =
|
||||
rememberForeverPagerState(key, initialFirstVisibleItemIndex, initialFirstVisibleItemScrollOffset, pageCount) { initialPage, initialPageOffsetFraction, pageCount ->
|
||||
rememberPagerState(initialPage, initialPageOffsetFraction, pageCount)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberForeverPagerState(
|
||||
key: String,
|
||||
initialFirstVisibleItemIndex: Int = 0,
|
||||
initialFirstVisibleItemScrollOffset: Float = 0.0f,
|
||||
pageCount: () -> Int,
|
||||
rememberPagerStateFunction: @Composable (
|
||||
initialPage: Int,
|
||||
initialPageOffsetFraction: Float,
|
||||
pageCount: () -> Int,
|
||||
) -> PagerState,
|
||||
): PagerState {
|
||||
val savedValue = savedScrollStates[key]
|
||||
val savedIndex = savedValue?.index ?: initialFirstVisibleItemIndex
|
||||
val savedOffset = savedValue?.scrollOffsetFraction ?: initialFirstVisibleItemScrollOffset
|
||||
|
||||
val scrollState =
|
||||
rememberPagerState(
|
||||
rememberPagerStateFunction(
|
||||
savedIndex,
|
||||
savedOffset,
|
||||
pageCount,
|
||||
|
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.video
|
||||
|
||||
import androidx.annotation.FloatRange
|
||||
import androidx.compose.foundation.MutatePriority
|
||||
import androidx.compose.foundation.gestures.ScrollScope
|
||||
import androidx.compose.foundation.pager.PagerState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.Saver
|
||||
import androidx.compose.runtime.saveable.listSaver
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import com.vitorpamplona.amethyst.ui.feeds.rememberForeverPagerState
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
* This file only exists to fix an interference between the Disappearing Top
|
||||
* and Bottom Scaffold bars and the offsetFraction of the pager. The current
|
||||
* implementation ends the scroll at a state where some fraction is still present
|
||||
* which places videos away from their natural position in the page.
|
||||
*
|
||||
* The fix simply animates it back to the fraction = 0.
|
||||
*/
|
||||
|
||||
@Composable
|
||||
fun myRememberPagerState(
|
||||
initialPage: Int = 0,
|
||||
@FloatRange(from = -0.5, to = 0.5) initialPageOffsetFraction: Float = 0f,
|
||||
pageCount: () -> Int,
|
||||
): PagerState =
|
||||
rememberSaveable(saver = DefaultPagerState.Saver) {
|
||||
DefaultPagerState(
|
||||
initialPage,
|
||||
initialPageOffsetFraction,
|
||||
pageCount,
|
||||
)
|
||||
}.apply {
|
||||
pageCountState.value = pageCount
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun myRememberForeverPagerState(
|
||||
key: String,
|
||||
initialFirstVisibleItemIndex: Int = 0,
|
||||
initialFirstVisibleItemScrollOffset: Float = 0.0f,
|
||||
pageCount: () -> Int,
|
||||
): PagerState =
|
||||
rememberForeverPagerState(key, initialFirstVisibleItemIndex, initialFirstVisibleItemScrollOffset, pageCount) { initialPage, initialPageOffsetFraction, pageCount ->
|
||||
myRememberPagerState(initialPage, initialPageOffsetFraction, pageCount)
|
||||
}
|
||||
|
||||
private class DefaultPagerState(
|
||||
currentPage: Int,
|
||||
currentPageOffsetFraction: Float,
|
||||
updatedPageCount: () -> Int,
|
||||
) : PagerState(currentPage, currentPageOffsetFraction) {
|
||||
var pageCountState = mutableStateOf(updatedPageCount)
|
||||
override val pageCount: Int get() = pageCountState.value.invoke()
|
||||
|
||||
override suspend fun scroll(
|
||||
scrollPriority: MutatePriority,
|
||||
block: suspend ScrollScope.() -> Unit,
|
||||
) {
|
||||
super.scroll(scrollPriority, block)
|
||||
if (abs(currentPageOffsetFraction) > 0) {
|
||||
animateScrollToPage(currentPage, 0f)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* To keep current page and current page offset saved
|
||||
*/
|
||||
val Saver: Saver<DefaultPagerState, *> =
|
||||
listSaver(
|
||||
save = {
|
||||
listOf(
|
||||
it.currentPage,
|
||||
(it.currentPageOffsetFraction).coerceIn(-0.5f, 0.5f),
|
||||
it.pageCount,
|
||||
)
|
||||
},
|
||||
restore = {
|
||||
DefaultPagerState(
|
||||
currentPage = it[0] as Int,
|
||||
currentPageOffsetFraction = it[1] as Float,
|
||||
updatedPageCount = { it[2] as Int },
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
@ -21,7 +21,6 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.video
|
||||
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@ -33,7 +32,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.pager.VerticalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material3.Icon
|
||||
@ -47,11 +45,11 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.FeatureSetType
|
||||
@ -69,7 +67,6 @@ import com.vitorpamplona.amethyst.ui.feeds.LoadingFeed
|
||||
import com.vitorpamplona.amethyst.ui.feeds.RefresheableBox
|
||||
import com.vitorpamplona.amethyst.ui.feeds.ScrollStateKeys
|
||||
import com.vitorpamplona.amethyst.ui.feeds.WatchScrollToTop
|
||||
import com.vitorpamplona.amethyst.ui.feeds.rememberForeverPagerState
|
||||
import com.vitorpamplona.amethyst.ui.navigation.AppBottomBar
|
||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.Route
|
||||
@ -236,7 +233,6 @@ private fun LoadedState(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun SlidingCarousel(
|
||||
loaded: FeedState.Loaded,
|
||||
@ -249,9 +245,9 @@ fun SlidingCarousel(
|
||||
|
||||
val pagerState =
|
||||
if (pagerStateKey != null) {
|
||||
rememberForeverPagerState(pagerStateKey, items.list.size) { items.list.size }
|
||||
myRememberForeverPagerState(pagerStateKey, items.list.size) { items.list.size }
|
||||
} else {
|
||||
rememberPagerState(items.list.size) { items.list.size }
|
||||
myRememberPagerState(items.list.size) { items.list.size }
|
||||
}
|
||||
|
||||
WatchScrollToTop(videoFeedContentState, pagerState)
|
||||
|
Loading…
x
Reference in New Issue
Block a user