优化
This commit is contained in:
2 files changed
+126
-100
No files matched your search
@@ -59,13 +59,11 @@ import androidx.compose.ui.graphics.lerp
|
|||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.compose.AsyncImage
|
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.constant.BookType
|
import io.legado.app.constant.BookType
|
||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
@@ -73,7 +71,6 @@ import io.legado.app.data.entities.BookChapter
|
|||||||
import io.legado.app.data.entities.SearchBook
|
import io.legado.app.data.entities.SearchBook
|
||||||
import io.legado.app.help.book.isLocal
|
import io.legado.app.help.book.isLocal
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.model.BookCover
|
|
||||||
import io.legado.app.ui.config.coverConfig.CoverConfig
|
import io.legado.app.ui.config.coverConfig.CoverConfig
|
||||||
import io.legado.app.ui.main.homepage.modules.BannerModule
|
import io.legado.app.ui.main.homepage.modules.BannerModule
|
||||||
import io.legado.app.ui.theme.LegadoTheme
|
import io.legado.app.ui.theme.LegadoTheme
|
||||||
@@ -93,8 +90,8 @@ import io.legado.app.ui.widget.components.button.series.SmallTonalButton
|
|||||||
import io.legado.app.ui.widget.components.card.GlassCard
|
import io.legado.app.ui.widget.components.card.GlassCard
|
||||||
import io.legado.app.ui.widget.components.card.TextCard
|
import io.legado.app.ui.widget.components.card.TextCard
|
||||||
import io.legado.app.ui.widget.components.icon.AppIcon
|
import io.legado.app.ui.widget.components.icon.AppIcon
|
||||||
|
import io.legado.app.ui.widget.components.image.cover.BookCoverImage
|
||||||
import io.legado.app.ui.widget.components.image.cover.CoilBookCover
|
import io.legado.app.ui.widget.components.image.cover.CoilBookCover
|
||||||
import io.legado.app.ui.widget.components.image.cover.buildCoverImageRequest
|
|
||||||
import io.legado.app.ui.widget.components.log.AppLogSheet
|
import io.legado.app.ui.widget.components.log.AppLogSheet
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
||||||
@@ -192,10 +189,7 @@ private fun BookInfoScreenContent(
|
|||||||
} else {
|
} else {
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
BookInfoBackdrop(
|
BookInfoBackdrop(
|
||||||
bookUrl = book.bookUrl,
|
book = book,
|
||||||
coverUrl = book.coverUrl,
|
|
||||||
customCoverUrl = book.customCoverUrl,
|
|
||||||
origin = book.origin,
|
|
||||||
)
|
)
|
||||||
AppPullToRefresh(
|
AppPullToRefresh(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
@@ -479,26 +473,8 @@ private fun BookInfoTopBarActions(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun BookInfoBackdrop(
|
private fun BookInfoBackdrop(
|
||||||
bookUrl: String,
|
book: Book,
|
||||||
coverUrl: String?,
|
|
||||||
customCoverUrl: String?,
|
|
||||||
origin: String,
|
|
||||||
) {
|
) {
|
||||||
val useDefaultCover = AppConfig.useDefaultCover || customCoverUrl == "use_default_cover"
|
|
||||||
val isNight = AppConfig.isNightTheme
|
|
||||||
|
|
||||||
val cover = remember(bookUrl, customCoverUrl, coverUrl, isNight) {
|
|
||||||
if (useDefaultCover) {
|
|
||||||
BookCover.getRandomDefaultPath(bookUrl, isNight)
|
|
||||||
} else {
|
|
||||||
if (customCoverUrl.isNullOrEmpty()) coverUrl else customCoverUrl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val sourceOrigin = if (!useDefaultCover) origin else null
|
|
||||||
val loadOnlyWifi = CoverConfig.loadCoverOnlyWifi
|
|
||||||
val context = LocalContext.current
|
|
||||||
val imageLoader = koinInject<ImageLoader>()
|
|
||||||
|
|
||||||
val seedOverlay = lerp(
|
val seedOverlay = lerp(
|
||||||
LegadoTheme.colorScheme.secondaryContainer,
|
LegadoTheme.colorScheme.secondaryContainer,
|
||||||
LegadoTheme.seedColor,
|
LegadoTheme.seedColor,
|
||||||
@@ -506,32 +482,22 @@ private fun BookInfoBackdrop(
|
|||||||
)
|
)
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
Crossfade(
|
Crossfade(
|
||||||
targetState = cover,
|
targetState = book,
|
||||||
animationSpec = tween(800),
|
animationSpec = tween(800),
|
||||||
label = "BackdropCrossfade"
|
label = "BackdropCrossfade"
|
||||||
) { currentCover ->
|
) { currentBook ->
|
||||||
if (!currentCover.isNullOrBlank()) {
|
BookCoverImage(
|
||||||
val backdropRequest = remember(currentCover, sourceOrigin, loadOnlyWifi, context) {
|
name = currentBook.name,
|
||||||
buildCoverImageRequest(
|
author = currentBook.author,
|
||||||
context = context,
|
path = currentBook.getDisplayCover(),
|
||||||
data = currentCover,
|
sourceOrigin = currentBook.origin,
|
||||||
sourceOrigin = sourceOrigin,
|
modifier = Modifier
|
||||||
loadOnlyWifi = loadOnlyWifi,
|
.fillMaxWidth()
|
||||||
crossfade = true,
|
.height(480.dp)
|
||||||
memoryCacheKey = currentCover,
|
.blur(24.dp),
|
||||||
)
|
contentScale = ContentScale.Crop,
|
||||||
}
|
showLoadingPlaceholder = false,
|
||||||
AsyncImage(
|
)
|
||||||
model = backdropRequest,
|
|
||||||
imageLoader = imageLoader,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(480.dp)
|
|
||||||
.blur(24.dp),
|
|
||||||
contentScale = ContentScale.Crop,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|||||||
+109
-49
@@ -52,6 +52,97 @@ import io.legado.app.model.BookCover as BookCoverModel
|
|||||||
private const val SharedCoverRadiusCacheMaxSize = 256
|
private const val SharedCoverRadiusCacheMaxSize = 256
|
||||||
private val sharedCoverRadiusCache = mutableStateMapOf<String, Dp>()
|
private val sharedCoverRadiusCache = mutableStateMapOf<String, Dp>()
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun BookCoverImage(
|
||||||
|
name: String?,
|
||||||
|
author: String?,
|
||||||
|
path: String?,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
sourceOrigin: String? = null,
|
||||||
|
ignoreUseDefaultCover: Boolean = false,
|
||||||
|
showLoadingPlaceholder: Boolean = true,
|
||||||
|
contentScale: ContentScale = ContentScale.Crop,
|
||||||
|
onLoadFinish: (() -> Unit)? = null,
|
||||||
|
onSuccess: (() -> Unit)? = null,
|
||||||
|
onError: (() -> Unit)? = null,
|
||||||
|
sharedCoverKey: String? = null,
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val isNight = isSystemInDarkTheme()
|
||||||
|
|
||||||
|
val useDefault = !ignoreUseDefaultCover && CoverConfig.useDefaultCover
|
||||||
|
val finalPath = if (useDefault) null else path
|
||||||
|
|
||||||
|
val randomPath = remember(name, author, path, isNight) {
|
||||||
|
BookCoverModel.getRandomDefaultPath(
|
||||||
|
seed = name ?: author ?: path ?: "",
|
||||||
|
isNight = isNight
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val hasCustomDefault = !randomPath.isNullOrBlank()
|
||||||
|
var isOnlineCoverLoaded by remember(finalPath) {
|
||||||
|
mutableStateOf(sharedCoverKey != null && finalPath != null)
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(finalPath) {
|
||||||
|
if (finalPath == null) {
|
||||||
|
isOnlineCoverLoaded = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(modifier = modifier) {
|
||||||
|
if (hasCustomDefault && !isOnlineCoverLoaded) {
|
||||||
|
AsyncImage(
|
||||||
|
model = buildCoverImageRequest(
|
||||||
|
context = context,
|
||||||
|
data = randomPath,
|
||||||
|
sourceOrigin = null,
|
||||||
|
loadOnlyWifi = false,
|
||||||
|
crossfade = showLoadingPlaceholder,
|
||||||
|
memoryCacheKey = randomPath,
|
||||||
|
),
|
||||||
|
contentDescription = null,
|
||||||
|
imageLoader = koinInject(),
|
||||||
|
contentScale = contentScale,
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finalPath != null) {
|
||||||
|
AsyncImage(
|
||||||
|
model = buildCoverImageRequest(
|
||||||
|
context = context,
|
||||||
|
data = finalPath,
|
||||||
|
sourceOrigin = sourceOrigin,
|
||||||
|
loadOnlyWifi = CoverConfig.loadCoverOnlyWifi,
|
||||||
|
crossfade = showLoadingPlaceholder,
|
||||||
|
memoryCacheKey = finalPath,
|
||||||
|
),
|
||||||
|
contentDescription = null,
|
||||||
|
imageLoader = koinInject(),
|
||||||
|
contentScale = contentScale,
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
onSuccess = {
|
||||||
|
isOnlineCoverLoaded = true
|
||||||
|
onSuccess?.invoke()
|
||||||
|
onLoadFinish?.invoke()
|
||||||
|
},
|
||||||
|
onError = {
|
||||||
|
isOnlineCoverLoaded = false
|
||||||
|
onError?.invoke()
|
||||||
|
onLoadFinish?.invoke()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
onLoadFinish?.invoke()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 改成BookCover
|
||||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun CoilBookCover(
|
fun CoilBookCover(
|
||||||
@@ -68,7 +159,6 @@ fun CoilBookCover(
|
|||||||
animatedVisibilityScope: AnimatedVisibilityScope? = null,
|
animatedVisibilityScope: AnimatedVisibilityScope? = null,
|
||||||
sharedCoverKey: String? = null,
|
sharedCoverKey: String? = null,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
|
||||||
val isNight = isSystemInDarkTheme()
|
val isNight = isSystemInDarkTheme()
|
||||||
|
|
||||||
val useDefault = !ignoreUseDefaultCover && CoverConfig.useDefaultCover
|
val useDefault = !ignoreUseDefaultCover && CoverConfig.useDefaultCover
|
||||||
@@ -126,54 +216,24 @@ fun CoilBookCover(
|
|||||||
)
|
)
|
||||||
.clip(shape)
|
.clip(shape)
|
||||||
) {
|
) {
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
BookCoverImage(
|
||||||
if (hasCustomDefault && !isOnlineCoverLoaded) {
|
name = name,
|
||||||
AsyncImage(
|
author = author,
|
||||||
model = buildCoverImageRequest(
|
path = path,
|
||||||
context = context,
|
modifier = Modifier.fillMaxSize(),
|
||||||
data = randomPath,
|
sourceOrigin = sourceOrigin,
|
||||||
sourceOrigin = null,
|
ignoreUseDefaultCover = ignoreUseDefaultCover,
|
||||||
loadOnlyWifi = false,
|
showLoadingPlaceholder = showLoadingPlaceholder,
|
||||||
crossfade = showLoadingPlaceholder,
|
onSuccess = {
|
||||||
memoryCacheKey = randomPath,
|
isOnlineCoverLoaded = true
|
||||||
),
|
onLoadFinish?.invoke()
|
||||||
contentDescription = null,
|
},
|
||||||
imageLoader = koinInject(),
|
onError = {
|
||||||
contentScale = ContentScale.Crop,
|
isOnlineCoverLoaded = false
|
||||||
modifier = Modifier
|
onLoadFinish?.invoke()
|
||||||
.fillMaxSize()
|
},
|
||||||
)
|
sharedCoverKey = sharedCoverKey
|
||||||
}
|
)
|
||||||
|
|
||||||
if (finalPath != null) {
|
|
||||||
AsyncImage(
|
|
||||||
model = buildCoverImageRequest(
|
|
||||||
context = context,
|
|
||||||
data = finalPath,
|
|
||||||
sourceOrigin = sourceOrigin,
|
|
||||||
loadOnlyWifi = CoverConfig.loadCoverOnlyWifi,
|
|
||||||
crossfade = showLoadingPlaceholder,
|
|
||||||
memoryCacheKey = finalPath,
|
|
||||||
),
|
|
||||||
contentDescription = null,
|
|
||||||
imageLoader = koinInject(),
|
|
||||||
contentScale = ContentScale.Crop,
|
|
||||||
modifier = Modifier.fillMaxSize(),
|
|
||||||
onSuccess = {
|
|
||||||
isOnlineCoverLoaded = true
|
|
||||||
onLoadFinish?.invoke()
|
|
||||||
},
|
|
||||||
onError = {
|
|
||||||
isOnlineCoverLoaded = false
|
|
||||||
onLoadFinish?.invoke()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
onLoadFinish?.invoke()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showLoadingPlaceholder && !isOnlineCoverLoaded) {
|
if (showLoadingPlaceholder && !isOnlineCoverLoaded) {
|
||||||
if (!hasCustomDefault) {
|
if (!hasCustomDefault) {
|
||||||
|
|||||||
Reference in new issue
Block a user