[Reader] Show gallery title & fix status bar color
This commit is contained in:
1 parent
371103908b
commit
c1ac592855
5 files changed
+71
-50
No files matched your search
@@ -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 <T> 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 <T> 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 <T> 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)
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ suspend inline fun <T> 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)
|
||||
|
||||
@@ -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<Job>()
|
||||
@@ -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?
|
||||
|
||||
|
||||
@@ -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 <T> 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)
|
||||
}
|
||||
|
||||
@@ -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<IntOffset>(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)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user