diff --git a/app/src/main/kotlin/com/hippo/ehviewer/gallery/ArchivePageLoader.kt b/app/src/main/kotlin/com/hippo/ehviewer/gallery/ArchivePageLoader.kt index 303b78f90..6d04b1584 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/gallery/ArchivePageLoader.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/gallery/ArchivePageLoader.kt @@ -17,8 +17,10 @@ package com.hippo.ehviewer.gallery import arrow.autoCloseScope import com.ehviewer.core.files.openFileDescriptor +import com.ehviewer.core.model.GalleryInfo import com.ehviewer.core.util.logcat import com.hippo.ehviewer.Settings.archivePasswds +import com.hippo.ehviewer.client.EhUtils import com.hippo.ehviewer.image.ImageSource import com.hippo.ehviewer.image.byteBufferSource import com.hippo.ehviewer.jni.closeArchive @@ -40,7 +42,7 @@ typealias PasswdProvider = suspend (PasswdInvalidator) -> String suspend inline fun useArchivePageLoader( file: Path, - gid: Long = 0, + info: GalleryInfo? = null, startPage: Int = 0, hasAds: Boolean = false, crossinline passwdProvider: PasswdProvider, @@ -49,7 +51,7 @@ suspend inline fun useArchivePageLoader( coroutineScope { val pfd = install(file.openFileDescriptor("r")) val size = install( - { openArchive(pfd.fd, pfd.statSize, gid == 0L || file.name.endsWith(".zip")) }, + { openArchive(pfd.fd, pfd.statSize, info == null || file.name.endsWith(".zip")) }, { _, _ -> closeArchive() }, ) check(size > 0) { "Archive have no content!" } @@ -57,8 +59,14 @@ suspend inline fun useArchivePageLoader( archivePasswds += passwdProvider(::providePassword) } val loader = install( - object : PageLoader(this, gid, startPage, size, hasAds) { - override val title by lazy { FileUtils.getNameFromFilename(file.displayName)!! } + object : PageLoader(this, info, startPage, size, hasAds) { + override val title by lazy { + if (info != null) { + EhUtils.getSuitableTitle(info) + } else { + FileUtils.getNameFromFilename(file.displayName)!! + } + } override fun getImageExtension(index: Int) = getExtension(index) diff --git a/app/src/main/kotlin/com/hippo/ehviewer/gallery/EhPageLoader.kt b/app/src/main/kotlin/com/hippo/ehviewer/gallery/EhPageLoader.kt index f1b971841..6ab51b7f8 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/gallery/EhPageLoader.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/gallery/EhPageLoader.kt @@ -24,7 +24,7 @@ suspend inline fun useEhPageLoader( ) queen.awaitReady() val loader = install( - object : PageLoader(this, info.gid, startPage, queen.size, info.hasAds) { + object : PageLoader(this, info, startPage, queen.size, info.hasAds) { override val title by lazy { EhUtils.getSuitableTitle(info) } override fun getImageExtension(index: Int) = queen.getExtension(index) diff --git a/app/src/main/kotlin/com/hippo/ehviewer/gallery/PageLoader.kt b/app/src/main/kotlin/com/hippo/ehviewer/gallery/PageLoader.kt index 8edf6580f..c24ee64c0 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/gallery/PageLoader.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/gallery/PageLoader.kt @@ -4,6 +4,7 @@ import androidx.collection.SieveCache import androidx.collection.mutableIntObjectMapOf import arrow.fx.coroutines.ExitCase import arrow.fx.coroutines.bracketCase +import com.ehviewer.core.model.GalleryInfo import com.ehviewer.core.util.isAtLeastO import com.ehviewer.core.util.withNonCancellableContext import com.hippo.ehviewer.EhDB @@ -35,7 +36,7 @@ private val progressScope = CoroutineScope(Dispatchers.IO) private const val MAX_CACHE_SIZE = 512 * 1024 * 1024 private const val MIN_CACHE_SIZE = 256 * 1024 * 1024 -abstract class PageLoader(val scope: CoroutineScope, val gid: Long, startPage: Int, val size: Int, val hasAds: Boolean = false) : AutoCloseable { +abstract class PageLoader(val scope: CoroutineScope, val info: GalleryInfo?, startPage: Int, val size: Int, val hasAds: Boolean = false) : AutoCloseable { var startPage = startPage.coerceIn(0, size - 1) private val jobs = mutableIntObjectMapOf() @@ -111,14 +112,14 @@ abstract class PageLoader(val scope: CoroutineScope, val gid: Long, startPage: I override fun close() { lock.write { cache.evictAll() } - if (gid != 0L) { + info?.run { progressScope.launch { EhDB.putReadProgress(gid, startPage) } } } - protected abstract val title: String + abstract val title: String protected abstract fun getImageExtension(index: Int): String? 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 762f5863b..91bf04e37 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 @@ -13,14 +13,11 @@ import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.safeDrawing -import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.systemBars import androidx.compose.foundation.layout.windowInsetsPadding -import androidx.compose.foundation.layout.windowInsetsTopHeight import androidx.compose.foundation.lazy.layout.LazyLayoutCacheWindow import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.pager.rememberPagerState @@ -53,7 +50,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.keepScreenOn import androidx.compose.ui.res.colorResource -import androidx.compose.ui.zIndex import arrow.core.Either import arrow.core.Either.Companion.catch import arrow.core.raise.ensure @@ -82,7 +78,6 @@ import com.hippo.ehviewer.gallery.useEhPageLoader import com.hippo.ehviewer.ui.MainActivity import com.hippo.ehviewer.ui.Screen import com.hippo.ehviewer.ui.theme.EhTheme -import com.hippo.ehviewer.ui.theme.scrim import com.hippo.ehviewer.ui.tools.DialogState import com.hippo.ehviewer.ui.tools.awaitInputText import com.hippo.ehviewer.ui.tools.dialog @@ -131,15 +126,11 @@ fun AnimatedVisibilityScope.ReaderScreen(args: ReaderScreenArgs, navigator: Dest val uiController = rememberSystemUiController() DisposableEffect(uiController) { val lightStatusBar = uiController.statusBarDarkContentEnabled + uiController.statusBarDarkContentEnabled = bgColor == Color.White onDispose { uiController.statusBarDarkContentEnabled = lightStatusBar } } - LaunchedEffect(uiController) { - snapshotFlow { bgColor }.collect { - uiController.statusBarDarkContentEnabled = it == Color.White - } - } Await( block = asyncInVM(args) { alive -> @@ -184,7 +175,7 @@ fun AnimatedVisibilityScope.ReaderScreen(args: ReaderScreenArgs, navigator: Dest } @Composable -context(activity: MainActivity, _: SnackbarHostState, _: DialogState, _: CoroutineScope) +context(activity: MainActivity, _: SnackbarHostState, _: DialogState, _: CoroutineScope, _: DestinationsNavigator) fun ReaderScreen(pageLoader: PageLoader, info: BaseGalleryInfo?) { LaunchedEffect(Unit) { val orientation = activity.requestedOrientation @@ -240,18 +231,14 @@ fun ReaderScreen(pageLoader: PageLoader, info: BaseGalleryInfo?) { LaunchedEffect(Unit) { focusRequester.requestFocus() } - val bgColor by collectBackgroundColorAsState() syncState.Sync(isWebtoon) { appbarVisible = false } - if (fullscreen) { - LaunchedEffect(Unit) { - snapshotFlow { appbarVisible }.collect { - uiController.isSystemBarsVisible = it - } + val bgColor by collectBackgroundColorAsState() + val isDarkTheme = isSystemInDarkTheme() + LaunchedEffect(isDarkTheme) { + snapshotFlow { appbarVisible }.collect { + uiController.isSystemBarsVisible = it || !fullscreen + uiController.statusBarDarkContentEnabled = if (it) !isDarkTheme else bgColor == Color.White } - Box( - Modifier.windowInsetsTopHeight(WindowInsets.statusBars).fillMaxWidth() - .align(Alignment.TopCenter).background(bgColor.scrim()).zIndex(1f), - ) } var showNavigationOverlay by remember { val showOnStart = Settings.showNavigationOverlayNewUser.value || Settings.showNavigationOverlayOnStart.value @@ -353,6 +340,7 @@ fun ReaderScreen(pageLoader: PageLoader, info: BaseGalleryInfo?) { } ReaderAppBars( visible = appbarVisible, + title = pageLoader.title, isRtl = readingMode == ReadingModeType.RIGHT_TO_LEFT, showSeekBar = showSeekbar, currentPage = syncState.sliderValue, @@ -383,7 +371,6 @@ fun ReaderScreen(pageLoader: PageLoader, info: BaseGalleryInfo?) { } } }, - modifier = Modifier.align(Alignment.BottomCenter), ) } } @@ -395,7 +382,7 @@ suspend inline fun usePageLoader(args: ReaderScreenArgs, crossinline block: val page = args.page.takeUnless { it == -1 } ?: EhDB.getReadProgress(info.gid) val archive = DownloadManager.getDownloadInfo(info.gid)?.archiveFile if (archive != null) { - useArchivePageLoader(archive, info.gid, page, info.hasAds, { error("Managed Archive have password???") }, block) + useArchivePageLoader(archive, info, page, info.hasAds, { error("Managed Archive have password???") }, block) } else { useEhPageLoader(info, page, block) } diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderAppBars.kt b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderAppBars.kt index 4a28d38bd..d0d7a788e 100644 --- a/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderAppBars.kt +++ b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderAppBars.kt @@ -6,47 +6,72 @@ import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.only -import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.layout.systemBarsIgnoringVisibility import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material3.BottomAppBarDefaults +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp +import com.hippo.ehviewer.ui.main.NavigationIcon +import com.ramcosta.composedestinations.navigation.DestinationsNavigator private val animationSpec = tween(200) @Composable -fun ReaderAppBars( +context(navigator: DestinationsNavigator) +fun BoxScope.ReaderAppBars( visible: Boolean, + title: String, isRtl: Boolean, showSeekBar: Boolean, currentPage: Int, totalPages: Int, onSliderValueChange: (Int) -> Unit, onClickSettings: () -> Unit, - modifier: Modifier = Modifier, -) = AnimatedVisibility( - visible = visible, - modifier = modifier.windowInsetsPadding(WindowInsets.systemBars.only(WindowInsetsSides.Horizontal)), - enter = slideInVertically(initialOffsetY = { it }, animationSpec = animationSpec), - exit = slideOutVertically(targetOffsetY = { it }, animationSpec = animationSpec), ) { - val toolbarColor = BottomAppBarDefaults.containerColor.copy(alpha = if (isSystemInDarkTheme()) 0.9f else 0.95f) - Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { - if (showSeekBar && totalPages > 1) { - ChapterNavigator( - isRtl = isRtl, - currentPage = currentPage, - totalPages = totalPages, - onSliderValueChange = onSliderValueChange, - containerColor = toolbarColor, - ) + val backgroundColor = BottomAppBarDefaults.containerColor.copy(alpha = if (isSystemInDarkTheme()) 0.9f else 0.95f) + + AnimatedVisibility( + visible = visible, + modifier = Modifier.windowInsetsPadding(WindowInsets.systemBarsIgnoringVisibility.only(WindowInsetsSides.Horizontal)).align(Alignment.TopStart), + enter = slideInVertically(initialOffsetY = { -it }, animationSpec = animationSpec), + exit = slideOutVertically(targetOffsetY = { -it }, animationSpec = animationSpec), + ) { + TopAppBar( + title = { Text(text = title, maxLines = 2, overflow = TextOverflow.Ellipsis) }, + colors = TopAppBarDefaults.topAppBarColors(containerColor = backgroundColor), + navigationIcon = { NavigationIcon() }, + ) + } + + AnimatedVisibility( + visible = visible, + modifier = Modifier.windowInsetsPadding(WindowInsets.systemBarsIgnoringVisibility.only(WindowInsetsSides.Horizontal)).align(Alignment.BottomStart), + enter = slideInVertically(initialOffsetY = { it }, animationSpec = animationSpec), + exit = slideOutVertically(targetOffsetY = { it }, animationSpec = animationSpec), + ) { + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + if (showSeekBar && totalPages > 1) { + ChapterNavigator( + isRtl = isRtl, + currentPage = currentPage, + totalPages = totalPages, + onSliderValueChange = onSliderValueChange, + containerColor = backgroundColor, + ) + } + BottomReaderBar(onClickSettings = onClickSettings, containerColor = backgroundColor) } - BottomReaderBar(onClickSettings = onClickSettings, containerColor = toolbarColor) } }