From 28279cc671fbe2542d29ff0b419d742c72dbbc5c Mon Sep 17 00:00:00 2001 From: FooIbar <118464521+FooIbar@users.noreply.github.com> Date: Mon, 29 Jul 2024 17:30:15 +0800 Subject: [PATCH] Fix page transitions when reading with volume keys --- .../hippo/ehviewer/ui/reader/GalleryPager.kt | 37 +-------------- .../hippo/ehviewer/ui/reader/ReaderScreen.kt | 12 +++-- .../ui/reader/SliderPagerDoubleSync.kt | 4 +- .../com/hippo/ehviewer/ui/reader/Utils.kt | 45 +++++++++++++++++++ .../ehviewer/ui/reader/VolumeKeysHandler.kt | 17 ++++--- 5 files changed, 69 insertions(+), 46 deletions(-) diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/GalleryPager.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/GalleryPager.kt index 86e10a520..9ec5e8fc8 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/GalleryPager.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/GalleryPager.kt @@ -1,7 +1,5 @@ package com.hippo.ehviewer.ui.reader -import androidx.compose.foundation.gestures.animateScrollBy -import androidx.compose.foundation.gestures.scrollBy import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues @@ -177,11 +175,10 @@ fun GalleryPager( val size = lazyListState.layoutInfo.viewportSize val x = it.x / size.width val y = it.y / size.height - val distance = size.height * 0.75f when (navigatorState.value.getAction(x, y)) { NavigationRegion.MENU -> onMenuRegionClick() - NavigationRegion.NEXT, NavigationRegion.RIGHT -> performScrollBy(distance) - NavigationRegion.PREV, NavigationRegion.LEFT -> performScrollBy(-distance) + NavigationRegion.NEXT, NavigationRegion.RIGHT -> scrollDown() + NavigationRegion.PREV, NavigationRegion.LEFT -> scrollUp() } } } @@ -353,36 +350,6 @@ suspend fun ZoomableState.panRight(distance: Float): Boolean { return canPan } -suspend fun PagerState.performScrollToPage(page: Int) { - if (Settings.pageTransitions.value) { - animateScrollToPage(page) - } else { - scrollToPage(page) - } -} - -suspend fun PagerState.moveToPrevious() { - val target = currentPage - 1 - if (target >= 0) { - performScrollToPage(target) - } -} - -suspend fun PagerState.moveToNext() { - val target = currentPage + 1 - if (target < pageCount) { - performScrollToPage(target) - } -} - -suspend fun LazyListState.performScrollBy(value: Float) { - if (Settings.pageTransitions.value) { - animateScrollBy(value) - } else { - scrollBy(value) - } -} - object DoubleTapZoom : DoubleClickToZoomListener { override suspend fun onDoubleClick(state: ZoomableState, centroid: Offset) { if (Settings.doubleTapToZoom.value) { diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/ReaderScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/ReaderScreen.kt index d4b4efebb..929f5f140 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/ReaderScreen.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/ReaderScreen.kt @@ -36,6 +36,7 @@ import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment @@ -160,7 +161,8 @@ fun AnimatedVisibilityScope.ReaderScreen(pageLoader: PageLoader2, info: BaseGall Box { var appbarVisible by remember { mutableStateOf(false) } val bgColor by collectBackgroundColorAsState() - syncState.Sync(ReadingModeType.isWebtoon(readingMode)) { appbarVisible = false } + val isWebtoon by rememberUpdatedState(ReadingModeType.isWebtoon(readingMode)) + syncState.Sync(isWebtoon, appbarVisible) { appbarVisible = false } if (fullscreen) { LaunchedEffect(Unit) { snapshotFlow { appbarVisible }.collect { @@ -170,8 +172,12 @@ fun AnimatedVisibilityScope.ReaderScreen(pageLoader: PageLoader2, info: BaseGall } VolumeKeysHandler( enabled = { volumeKeysEnabled && !appbarVisible }, - movePrevious = { syncState.sliderScrollTo(syncState.sliderValue - 1) }, - moveNext = { syncState.sliderScrollTo(syncState.sliderValue + 1) }, + movePrevious = { + if (isWebtoon) lazyListState.scrollUp() else pagerState.moveToPrevious() + }, + moveNext = { + if (isWebtoon) lazyListState.scrollDown() else pagerState.moveToNext() + }, ) GalleryPager( type = readingMode, diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/SliderPagerDoubleSync.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/SliderPagerDoubleSync.kt index 322a19128..f96d737e2 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/SliderPagerDoubleSync.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/SliderPagerDoubleSync.kt @@ -32,10 +32,10 @@ class SliderPagerDoubleSync( } @Composable - fun Sync(webtoon: Boolean, onPageSelected: () -> Unit) { + fun Sync(webtoon: Boolean, appbarVisible: Boolean, onPageSelected: () -> Unit) { val fling by lazyListState.interactionSource.collectIsDraggedAsState() val pagerFling by pagerState.interactionSource.collectIsDraggedAsState() - if (fling || pagerFling) sliderFollowPager = true + if (fling || pagerFling || !appbarVisible) sliderFollowPager = true val currentIndexFlow = remember(webtoon) { val initialIndex = sliderValue - 1 if (webtoon) { diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/Utils.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/Utils.kt index d29912cdd..2ac63140a 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/Utils.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/Utils.kt @@ -3,6 +3,10 @@ package com.hippo.ehviewer.ui.reader import android.app.Activity import android.view.Window import android.view.WindowManager +import androidx.compose.foundation.gestures.animateScrollBy +import androidx.compose.foundation.gestures.scrollBy +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.pager.PagerState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.Stable @@ -82,3 +86,44 @@ fun ContentScale.Companion.fromPreferences(value: Int, srcSize: Size, dstSize: S 6 -> if (srcSize.width > srcSize.height) FillHeight else FillWidth else -> Fit } + +suspend fun PagerState.performScrollToPage(page: Int) { + if (Settings.pageTransitions.value) { + animateScrollToPage(page) + } else { + scrollToPage(page) + } +} + +suspend fun PagerState.moveToPrevious() { + val target = currentPage - 1 + if (target >= 0) { + performScrollToPage(target) + } +} + +suspend fun PagerState.moveToNext() { + val target = currentPage + 1 + if (target < pageCount) { + performScrollToPage(target) + } +} + +suspend fun LazyListState.performScrollBy(value: Float) { + if (Settings.pageTransitions.value) { + animateScrollBy(value) + } else { + scrollBy(value) + } +} + +suspend fun LazyListState.scrollUp() { + performScrollBy(-scrollDistance) +} + +suspend fun LazyListState.scrollDown() { + performScrollBy(scrollDistance) +} + +private val LazyListState.scrollDistance + get() = layoutInfo.viewportSize.height * 0.75f diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/VolumeKeysHandler.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/VolumeKeysHandler.kt index 5f712fb04..37edfe0e3 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/VolumeKeysHandler.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/VolumeKeysHandler.kt @@ -8,12 +8,15 @@ import androidx.compose.runtime.DisposableEffect import androidx.compose.ui.platform.LocalView import androidx.core.view.ViewCompat import com.hippo.ehviewer.Settings +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +context(CoroutineScope) @Composable fun VolumeKeysHandler( enabled: () -> Boolean, - movePrevious: () -> Unit, - moveNext: () -> Unit, + movePrevious: suspend () -> Unit, + moveNext: suspend () -> Unit, ) { val view = LocalView.current DisposableEffect(view) { @@ -24,10 +27,12 @@ fun VolumeKeysHandler( val interval = Settings.readWithVolumeKeysInterval.value + 1 val inverted = Settings.readWithVolumeKeysInverted.value if (event.action == ACTION_DOWN && event.repeatCount % interval == 0) { - if (inverted.xor(keyCode == KEYCODE_VOLUME_UP)) { - movePrevious() - } else { - moveNext() + launch { + if (inverted.xor(keyCode == KEYCODE_VOLUME_UP)) { + movePrevious() + } else { + moveNext() + } } } true