[New Reader] Implement landscape zoom

This commit is contained in:
FooIbar authored and renovate[bot] committed 2024-07-24 20:36:43 +08:00
1 parent 7b1f94cf5a
commit 53a1bd9959
3 files changed
+53 -10

No files matched your search

@@ -70,6 +70,14 @@ inline fun <R, T> PrefDelegate<T>.collectAsState(crossinline transform: @Disallo
return flow.collectAsState(transform(init))
}
@Stable
@Composable
inline fun <R, T> PrefDelegate<T>.collectAsState(key1: Any?, crossinline transform: @DisallowComposableCalls (T) -> R): State<R> {
val flow = remember(key1) { valueFlow().map { transform(it) } }
val init = getValue()
return flow.collectAsState(transform(init))
}
@Stable
@Composable
fun <T> PrefDelegate<T>.collectAsState(): State<T> {
@@ -31,6 +31,8 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.FixedScale
import androidx.compose.ui.layout.times
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.toSize
import com.hippo.ehviewer.Settings
@@ -50,6 +52,7 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType.WEBTOON
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation.NavigationRegion
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import me.saket.telephoto.zoomable.DoubleClickToZoomListener
import me.saket.telephoto.zoomable.ZoomSpec
@@ -75,10 +78,11 @@ fun GalleryPager(
DEFAULT, LEFT_TO_RIGHT, RIGHT_TO_LEFT, VERTICAL -> {
val isVertical = type == VERTICAL
val scaleType by Settings.imageScaleType.collectAsState()
val alignment by Settings.zoomStart.collectAsState {
Alignment.fromPreferences(it, isVertical)
val landscapeZoom by Settings.landscapeZoom.collectAsState()
val alignment by Settings.zoomStart.collectAsState(type) {
Alignment.fromPreferences(it, type)
}
val navigatorState = Settings.readerPagerNav.collectAsState {
val navigatorState = Settings.readerPagerNav.collectAsState(isVertical) {
ViewerNavigation.fromPreference(it, isVertical)
}
val invertMode by Settings.readerPagerNavInverted.collectAsState {
@@ -105,6 +109,7 @@ fun GalleryPager(
pageLoader = pageLoader,
isRtl = false,
scaleType = scaleType,
landscapeZoom = landscapeZoom,
alignment = alignment,
layoutSize = layoutSize,
navigatorState = navigatorState,
@@ -116,11 +121,12 @@ fun GalleryPager(
}
} else {
val isRtl = type == RIGHT_TO_LEFT
val isRtlLayout = LocalLayoutDirection.current == LayoutDirection.Rtl
HorizontalPager(
state = pagerState,
modifier = modifier,
contentPadding = contentPadding,
reverseLayout = isRtl,
reverseLayout = isRtl xor isRtlLayout,
key = { it },
) { index ->
val page = items[index]
@@ -129,6 +135,7 @@ fun GalleryPager(
pageLoader = pageLoader,
isRtl = isRtl,
scaleType = scaleType,
landscapeZoom = landscapeZoom,
alignment = alignment,
layoutSize = layoutSize,
navigatorState = navigatorState,
@@ -212,6 +219,7 @@ private fun PageContainer(
pageLoader: PageLoader2,
isRtl: Boolean,
scaleType: Int,
landscapeZoom: Boolean,
alignment: Alignment.Horizontal,
layoutSize: Size,
navigatorState: State<ViewerNavigation>,
@@ -222,7 +230,7 @@ private fun PageContainer(
) {
@Suppress("NAME_SHADOWING")
val isRtl by rememberUpdatedState(isRtl)
val zoomableState = rememberZoomableState(zoomSpec = zoomSpec)
val zoomableState = rememberZoomableState(zoomSpec = pagerZoomSpec)
val status by page.status.collectAsState()
if (status == Page.State.READY) {
val size = page.image!!.rect.size.toSize()
@@ -250,6 +258,18 @@ private fun PageContainer(
val contentLocation = ZoomableContentLocation.scaledInsideAndCenterAligned(size)
zoomableState.setContentLocation(contentLocation)
}
if (landscapeZoom && contentScale == ContentScale.Fit && size.width > size.height) {
LaunchedEffect(alignment) {
delay(500)
if (zoomableState.zoomFraction == 0f) {
val contentSize = zoomableState.transformedContentBounds.size
val scale = ContentScale.FillHeight.computeScaleFactor(contentSize, layoutSize)
val targetScale = scale.scaleX.coerceAtMost(zoomableState.zoomSpec.maxZoomFactor)
val offset = alignment.align(0, layoutSize.width.toInt(), LayoutDirection.Ltr)
zoomableState.zoomTo(targetScale, Offset(offset.toFloat(), 0f))
}
}
}
}
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
PagerItem(
@@ -350,13 +370,21 @@ suspend fun LazyListState.performScrollBy(value: Float) {
}
object DoubleTapZoom : DoubleClickToZoomListener {
private val listener = DoubleClickToZoomListener.cycle(maxZoomFactor = 2f)
override suspend fun onDoubleClick(state: ZoomableState, centroid: Offset) {
if (Settings.doubleTapToZoom.value) {
listener.onDoubleClick(state, centroid)
val zoomFraction = state.zoomFraction ?: return // Content isn't ready yet
if (zoomFraction > 0.05f) {
state.resetZoom()
} else {
// Workaround for https://github.com/saket/telephoto/issues/45
state.zoomTo(
zoomFactor = state.contentTransformation.scaleMetadata.initialScale.scaleX * 2f,
centroid = centroid,
)
}
}
}
}
private val pagerZoomSpec = ZoomSpec(maxZoomFactor = 5f)
private val zoomSpec = ZoomSpec(maxZoomFactor = 3f)
@@ -13,6 +13,9 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.FixedScale
import com.hippo.ehviewer.Settings
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType.RIGHT_TO_LEFT
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType.VERTICAL
import kotlinx.coroutines.flow.onCompletion
fun Window.updateKeepScreenOn(enabled: Boolean) {
@@ -58,8 +61,12 @@ fun Activity.setCustomBrightnessValue(value: Int) {
window.attributes = window.attributes.apply { screenBrightness = readerBrightness }
}
fun Alignment.Companion.fromPreferences(value: Int, isVertical: Boolean) = when (value) {
1 -> if (isVertical) CenterHorizontally else Start
fun Alignment.Companion.fromPreferences(value: Int, mode: ReadingModeType) = when (value) {
1 -> when (mode) {
VERTICAL -> CenterHorizontally
RIGHT_TO_LEFT -> AbsoluteAlignment.Right
else -> AbsoluteAlignment.Left
}
2 -> AbsoluteAlignment.Left
3 -> AbsoluteAlignment.Right
else -> CenterHorizontally