Fix losing reading progress on reading mode change

This commit is contained in:
FooIbar committed 2024-04-21 22:35:22 +08:00
1 parent 9013778f58
commit d6c36146ba
1 file changed
+41 -34
@@ -8,7 +8,6 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow import androidx.compose.runtime.snapshotFlow
@@ -16,7 +15,7 @@ import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.gallery.PageLoader2 import com.hippo.ehviewer.gallery.PageLoader2
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.filterNotNull
@Stable @Stable
class SliderPagerDoubleSync( class SliderPagerDoubleSync(
@@ -24,8 +23,10 @@ class SliderPagerDoubleSync(
private val pagerState: PagerState, private val pagerState: PagerState,
private val pageLoader: PageLoader2, private val pageLoader: PageLoader2,
) { ) {
private var sliderFollowPager by mutableStateOf(true) private var requestScroll = true
var sliderValue by mutableIntStateOf(1) private var sliderFollowPager = true
var sliderValue by mutableIntStateOf(pageLoader.startPage + 1)
private set
fun sliderScrollTo(index: Int) { fun sliderScrollTo(index: Int) {
sliderFollowPager = false sliderFollowPager = false
@@ -37,52 +38,55 @@ class SliderPagerDoubleSync(
val fling by lazyListState.interactionSource.collectIsDraggedAsState() val fling by lazyListState.interactionSource.collectIsDraggedAsState()
val pagerFling by pagerState.interactionSource.collectIsDraggedAsState() val pagerFling by pagerState.interactionSource.collectIsDraggedAsState()
if (fling || pagerFling) sliderFollowPager = true if (fling || pagerFling) sliderFollowPager = true
val startPage = remember { pageLoader.startPage }
val currentIndexFlow = remember(webtoon) { val currentIndexFlow = remember(webtoon) {
requestScroll = true
if (webtoon) { if (webtoon) {
snapshotFlow { lazyListState.layoutInfo }.mapNotNull { info -> snapshotFlow {
info.visibleItemsInfo.lastOrNull { with(lazyListState.layoutInfo) {
it.offset <= maxOf(info.viewportStartOffset, info.viewportEndOffset - it.size) visibleItemsInfo.lastOrNull {
}?.index it.offset <= maxOf(viewportStartOffset, viewportEndOffset - it.size)
} }?.index
}
}.filterNotNull()
} else { } else {
snapshotFlow { pagerState.currentPage } snapshotFlow { pagerState.currentPage }
} }
} }
if (sliderFollowPager) { LaunchedEffect(currentIndexFlow) {
LaunchedEffect(currentIndexFlow) { currentIndexFlow.collect { index ->
currentIndexFlow.collect { index -> if (sliderFollowPager && !requestScroll) {
sliderValue = index + 1 sliderValue = index + 1
pageLoader.startPage = index pageLoader.startPage = index
} }
} }
} else { }
LaunchedEffect(webtoon) { LaunchedEffect(webtoon) {
snapshotFlow { sliderValue - 1 }.collectLatest { index -> snapshotFlow { sliderValue - 1 }.collectLatest { index ->
if (webtoon) { if (sliderFollowPager && !requestScroll) return@collectLatest
val noAnim = (index - lazyListState.firstVisibleItemIndex).absoluteValue > SMOOTH_SCROLL_THRESHOLD || !Settings.pageTransitions.value if (webtoon) {
if (noAnim) { if (requestScroll) {
lazyListState.scrollToItem(index) lazyListState.requestScrollToItem(index)
} else { requestScroll = false
lazyListState.animateScrollToItem(index)
}
} else { } else {
val noAnim = (index - pagerState.currentPage).absoluteValue > SMOOTH_SCROLL_THRESHOLD || !Settings.pageTransitions.value if (smoothScroll((index - lazyListState.firstVisibleItemIndex))) {
if (noAnim) { lazyListState.animateScrollToItem(index)
pagerState.scrollToPage(index)
} else { } else {
lazyListState.scrollToItem(index)
}
}
} else {
if (requestScroll) {
pagerState.requestScrollToPage(index)
requestScroll = false
} else {
if (smoothScroll((index - pagerState.currentPage))) {
pagerState.animateScrollToPage(index) pagerState.animateScrollToPage(index)
} else {
pagerState.scrollToPage(index)
} }
} }
pageLoader.startPage = index
} }
} pageLoader.startPage = index
}
LaunchedEffect(Unit) {
if (webtoon) {
lazyListState.scrollToItem(startPage)
} else {
pagerState.scrollToPage(startPage)
} }
} }
} }
@@ -100,4 +104,7 @@ fun rememberSliderPagerDoubleSyncState(
} }
} }
private fun smoothScroll(distance: Int) =
distance.absoluteValue < SMOOTH_SCROLL_THRESHOLD && Settings.pageTransitions.value
private const val SMOOTH_SCROLL_THRESHOLD = 50 private const val SMOOTH_SCROLL_THRESHOLD = 50