[修复] 修复无法打开除文本之外的问题、修复在有在线封面时依旧显示文字的问题、修复主页面底部间距等界面问题
This commit is contained in:
9 files changed
+134
-77
No files matched your search
@@ -8,12 +8,16 @@ import io.legado.app.help.glide.progress.ProgressResponseBody
|
|||||||
import io.legado.app.help.http.CookieManager.cookieJarHeader
|
import io.legado.app.help.http.CookieManager.cookieJarHeader
|
||||||
import io.legado.app.model.ReadManga
|
import io.legado.app.model.ReadManga
|
||||||
import io.legado.app.utils.NetworkUtils
|
import io.legado.app.utils.NetworkUtils
|
||||||
|
import okhttp3.Cache
|
||||||
import okhttp3.ConnectionSpec
|
import okhttp3.ConnectionSpec
|
||||||
import okhttp3.Cookie
|
import okhttp3.Cookie
|
||||||
import okhttp3.CookieJar
|
import okhttp3.CookieJar
|
||||||
import okhttp3.Credentials
|
import okhttp3.Credentials
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.Interceptor
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import splitties.init.appCtx
|
||||||
|
import java.io.File
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
import java.net.Proxy
|
import java.net.Proxy
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
@@ -47,6 +51,26 @@ val cookieJar by lazy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强制缓存拦截器,对于图片资源,如果没有缓存头,则强制缓存30天
|
||||||
|
*/
|
||||||
|
private val cacheControlInterceptor = Interceptor { chain ->
|
||||||
|
val request = chain.request()
|
||||||
|
val response = chain.proceed(request)
|
||||||
|
val url = request.url.toString()
|
||||||
|
if (url.contains("image", true) || url.endsWith(".jpg") || url.endsWith(".png") || url.endsWith(
|
||||||
|
".webp"
|
||||||
|
) || url.endsWith(".jpeg")
|
||||||
|
) {
|
||||||
|
response.newBuilder()
|
||||||
|
.header("Cache-Control", "public, max-age=2592000")
|
||||||
|
.removeHeader("Pragma")
|
||||||
|
.build()
|
||||||
|
} else {
|
||||||
|
response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val okHttpClient: OkHttpClient by lazy {
|
val okHttpClient: OkHttpClient by lazy {
|
||||||
val specs = arrayListOf(
|
val specs = arrayListOf(
|
||||||
ConnectionSpec.MODERN_TLS,
|
ConnectionSpec.MODERN_TLS,
|
||||||
@@ -54,7 +78,11 @@ val okHttpClient: OkHttpClient by lazy {
|
|||||||
ConnectionSpec.CLEARTEXT
|
ConnectionSpec.CLEARTEXT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//TODO:自定义缓存大小
|
||||||
|
val cache = Cache(File(appCtx.cacheDir, "http_cache"), 100L * 1024L * 1024L)
|
||||||
|
|
||||||
val builder = OkHttpClient.Builder()
|
val builder = OkHttpClient.Builder()
|
||||||
|
.cache(cache)
|
||||||
.connectTimeout(15, TimeUnit.SECONDS)
|
.connectTimeout(15, TimeUnit.SECONDS)
|
||||||
.writeTimeout(15, TimeUnit.SECONDS)
|
.writeTimeout(15, TimeUnit.SECONDS)
|
||||||
.readTimeout(60, TimeUnit.SECONDS)
|
.readTimeout(60, TimeUnit.SECONDS)
|
||||||
@@ -77,9 +105,9 @@ val okHttpClient: OkHttpClient by lazy {
|
|||||||
}
|
}
|
||||||
builder.addHeader("Keep-Alive", "300")
|
builder.addHeader("Keep-Alive", "300")
|
||||||
builder.addHeader("Connection", "Keep-Alive")
|
builder.addHeader("Connection", "Keep-Alive")
|
||||||
builder.addHeader("Cache-Control", "no-cache")
|
|
||||||
chain.proceed(builder.build())
|
chain.proceed(builder.build())
|
||||||
}
|
}
|
||||||
|
.addNetworkInterceptor(cacheControlInterceptor) // 添加强制缓存拦截器
|
||||||
.addNetworkInterceptor { chain ->
|
.addNetworkInterceptor { chain ->
|
||||||
var request = chain.request()
|
var request = chain.request()
|
||||||
val enableCookieJar = request.header(cookieJarHeader) != null
|
val enableCookieJar = request.header(cookieJarHeader) != null
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package io.legado.app.ui.main
|
package io.legado.app.ui.main
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
@@ -22,23 +26,26 @@ import androidx.compose.material3.IconButton
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.NavigationBarItem
|
import androidx.compose.material3.NavigationBarItem
|
||||||
import androidx.compose.material3.NavigationBarItemDefaults
|
import androidx.compose.material3.NavigationBarItemDefaults
|
||||||
import androidx.compose.material3.NavigationRail
|
|
||||||
import androidx.compose.material3.NavigationRailItem
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.WideNavigationRail
|
||||||
|
import androidx.compose.material3.WideNavigationRailItem
|
||||||
|
import androidx.compose.material3.WideNavigationRailValue
|
||||||
|
import androidx.compose.material3.rememberWideNavigationRailState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import dev.chrisbanes.haze.HazeState
|
import dev.chrisbanes.haze.HazeState
|
||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.ui.book.info.BookInfoActivity
|
import io.legado.app.ui.book.info.BookInfoActivity
|
||||||
import io.legado.app.ui.book.read.ReadBookActivity
|
|
||||||
import io.legado.app.ui.book.search.SearchActivity
|
import io.legado.app.ui.book.search.SearchActivity
|
||||||
import io.legado.app.ui.config.mainConfig.MainConfig
|
import io.legado.app.ui.config.mainConfig.MainConfig
|
||||||
import io.legado.app.ui.main.bookshelf.BookshelfScreen
|
import io.legado.app.ui.main.bookshelf.BookshelfScreen
|
||||||
@@ -48,6 +55,7 @@ import io.legado.app.ui.main.rss.RssScreen
|
|||||||
import io.legado.app.ui.theme.regularHazeEffect
|
import io.legado.app.ui.theme.regularHazeEffect
|
||||||
import io.legado.app.ui.widget.components.GlassDefaults
|
import io.legado.app.ui.widget.components.GlassDefaults
|
||||||
import io.legado.app.utils.startActivity
|
import io.legado.app.utils.startActivity
|
||||||
|
import io.legado.app.utils.startActivityForBook
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
|
||||||
@@ -78,27 +86,60 @@ fun MainScreen(
|
|||||||
}
|
}
|
||||||
val pagerState = rememberPagerState(initialPage = initialPage) { destinations.size }
|
val pagerState = rememberPagerState(initialPage = initialPage) { destinations.size }
|
||||||
|
|
||||||
|
val navState = rememberWideNavigationRailState(
|
||||||
|
initialValue = if (MainConfig.navExtended)
|
||||||
|
WideNavigationRailValue.Expanded
|
||||||
|
else
|
||||||
|
WideNavigationRailValue.Collapsed
|
||||||
|
)
|
||||||
|
|
||||||
|
LaunchedEffect(navState.currentValue) {
|
||||||
|
MainConfig.navExtended =
|
||||||
|
navState.currentValue == WideNavigationRailValue.Expanded
|
||||||
|
}
|
||||||
|
|
||||||
Row(modifier = Modifier.fillMaxSize()) {
|
Row(modifier = Modifier.fillMaxSize()) {
|
||||||
if (useRail && MainConfig.showBottomView) {
|
if (useRail && MainConfig.showBottomView) {
|
||||||
NavigationRail(
|
WideNavigationRail(
|
||||||
|
state = navState,
|
||||||
header = {
|
header = {
|
||||||
IconButton(onClick = { MainConfig.navExtended = !MainConfig.navExtended }) {
|
val expanded = navState.targetValue == WideNavigationRailValue.Expanded
|
||||||
|
|
||||||
|
Column {
|
||||||
|
IconButton(
|
||||||
|
modifier = Modifier.padding(start = 24.dp),
|
||||||
|
onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
if (expanded) navState.collapse()
|
||||||
|
else navState.expand()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
if (MainConfig.navExtended) Icons.AutoMirrored.Filled.MenuOpen else Icons.Default.Menu,
|
if (expanded)
|
||||||
|
Icons.AutoMirrored.Filled.MenuOpen
|
||||||
|
else
|
||||||
|
Icons.Default.Menu,
|
||||||
contentDescription = null
|
contentDescription = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
ExtendedFloatingActionButton(
|
ExtendedFloatingActionButton(
|
||||||
|
modifier = Modifier.padding(start = 20.dp),
|
||||||
onClick = { context.startActivity<SearchActivity>() },
|
onClick = { context.startActivity<SearchActivity>() },
|
||||||
expanded = MainConfig.navExtended,
|
expanded = expanded,
|
||||||
icon = { Icon(Icons.Default.Search, contentDescription = null) },
|
icon = { Icon(Icons.Default.Search, contentDescription = null) },
|
||||||
text = { Text(text = stringResource(R.string.search)) }
|
text = { Text(stringResource(R.string.search)) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
destinations.forEachIndexed { index, destination ->
|
destinations.forEachIndexed { index, destination ->
|
||||||
val selected = pagerState.currentPage == index
|
val selected = pagerState.currentPage == index
|
||||||
NavigationRailItem(
|
WideNavigationRailItem(
|
||||||
|
railExpanded = navState.targetValue == WideNavigationRailValue.Expanded,
|
||||||
selected = selected,
|
selected = selected,
|
||||||
onClick = {
|
onClick = {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
@@ -157,14 +198,12 @@ fun MainScreen(
|
|||||||
state = pagerState,
|
state = pagerState,
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
userScrollEnabled = true,
|
userScrollEnabled = true,
|
||||||
beyondViewportPageCount = 1
|
beyondViewportPageCount = 3
|
||||||
) { page ->
|
) { page ->
|
||||||
when (destinations[page]) {
|
when (destinations[page]) {
|
||||||
MainDestination.Bookshelf -> BookshelfScreen(
|
MainDestination.Bookshelf -> BookshelfScreen(
|
||||||
onBookClick = { book ->
|
onBookClick = { book ->
|
||||||
context.startActivity<ReadBookActivity> {
|
context.startActivityForBook(book)
|
||||||
putExtra("bookUrl", book.bookUrl)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onBookLongClick = { book ->
|
onBookLongClick = { book ->
|
||||||
context.startActivity<BookInfoActivity> {
|
context.startActivity<BookInfoActivity> {
|
||||||
|
|||||||
@@ -71,12 +71,14 @@ fun BookshelfItem(
|
|||||||
val coverModifier = if (coverShadow) {
|
val coverModifier = if (coverShadow) {
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.shadow(4.dp, RoundedCornerShape(4.dp))
|
.shadow(4.dp, MaterialTheme.shapes.extraSmall)
|
||||||
} else {
|
} else {
|
||||||
Modifier.fillMaxWidth()
|
Modifier.fillMaxWidth()
|
||||||
}
|
}
|
||||||
|
|
||||||
Box {
|
Box(
|
||||||
|
modifier = Modifier.clip(MaterialTheme.shapes.extraSmall)
|
||||||
|
) {
|
||||||
cover(coverModifier)
|
cover(coverModifier)
|
||||||
if (isCompact) {
|
if (isCompact) {
|
||||||
Text(
|
Text(
|
||||||
@@ -135,7 +137,7 @@ fun BookshelfItem(
|
|||||||
) {
|
) {
|
||||||
cover(
|
cover(
|
||||||
Modifier
|
Modifier
|
||||||
.width(if (!isCompact) 70.dp else 55.dp)
|
.width(if (!isCompact) 80.dp else 56.dp)
|
||||||
.padding(end = 12.dp)
|
.padding(end = 12.dp)
|
||||||
)
|
)
|
||||||
Column(
|
Column(
|
||||||
|
|||||||
@@ -8,11 +8,9 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
import androidx.compose.foundation.lazy.grid.items
|
import androidx.compose.foundation.lazy.grid.items
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
@@ -254,7 +252,7 @@ fun BookshelfScreen(
|
|||||||
text = group.groupName,
|
text = group.groupName,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
modifier = Modifier.padding(horizontal = 4.dp),
|
modifier = Modifier.padding(horizontal = 8.dp),
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -291,16 +289,20 @@ fun BookshelfScreen(
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
if (bookGroupStyle == 2 && isInFolderRoot) {
|
if (bookGroupStyle == 2 && isInFolderRoot) {
|
||||||
|
LazyVerticalGrid(
|
||||||
if (uiState.bookshelfLayoutMode == 0) {
|
columns = GridCells.Fixed(uiState.bookshelfLayoutGrid.coerceAtLeast(1)),
|
||||||
LazyColumn(
|
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentPadding = PaddingValues(
|
contentPadding = PaddingValues(
|
||||||
top = paddingValues.calculateTopPadding(),
|
top = paddingValues.calculateTopPadding(),
|
||||||
bottom = 56.dp
|
bottom = 120.dp,
|
||||||
)
|
start = if (uiState.bookshelfLayoutMode != 0) 12.dp else 0.dp,
|
||||||
|
end = if (uiState.bookshelfLayoutMode != 0) 12.dp else 0.dp
|
||||||
|
),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(if (uiState.bookshelfLayoutMode != 0) 8.dp else 0.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(if (uiState.bookshelfLayoutMode != 0) 8.dp else 0.dp)
|
||||||
) {
|
) {
|
||||||
items(uiState.groups) { group ->
|
items(uiState.groups) { group ->
|
||||||
|
if (uiState.bookshelfLayoutMode == 0) {
|
||||||
BookGroupItemList(
|
BookGroupItemList(
|
||||||
group = group,
|
group = group,
|
||||||
previewBooks = uiState.groupPreviews[group.groupId] ?: emptyList(),
|
previewBooks = uiState.groupPreviews[group.groupId] ?: emptyList(),
|
||||||
@@ -317,23 +319,7 @@ fun BookshelfScreen(
|
|||||||
},
|
},
|
||||||
onLongClick = { showGroupManageSheet = true }
|
onLongClick = { showGroupManageSheet = true }
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
LazyVerticalGrid(
|
|
||||||
columns = GridCells.Fixed(uiState.bookshelfLayoutGrid),
|
|
||||||
modifier = Modifier.fillMaxSize(),
|
|
||||||
contentPadding = PaddingValues(
|
|
||||||
top = paddingValues.calculateTopPadding(),
|
|
||||||
bottom = paddingValues.calculateBottomPadding() + 16.dp,
|
|
||||||
start = 12.dp,
|
|
||||||
end = 12.dp
|
|
||||||
),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
items(uiState.groups) { group ->
|
|
||||||
|
|
||||||
BookGroupItemGrid(
|
BookGroupItemGrid(
|
||||||
group = group,
|
group = group,
|
||||||
previewBooks = uiState.groupPreviews[group.groupId] ?: emptyList(),
|
previewBooks = uiState.groupPreviews[group.groupId] ?: emptyList(),
|
||||||
@@ -358,7 +344,7 @@ fun BookshelfScreen(
|
|||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
beyondViewportPageCount = 1,
|
beyondViewportPageCount = 3,
|
||||||
key = { if (it < uiState.groups.size) uiState.groups[it].groupId else it }
|
key = { if (it < uiState.groups.size) uiState.groups[it].groupId else it }
|
||||||
) { pageIndex ->
|
) { pageIndex ->
|
||||||
val group = uiState.groups.getOrNull(pageIndex)
|
val group = uiState.groups.getOrNull(pageIndex)
|
||||||
@@ -447,37 +433,17 @@ fun BookshelfPage(
|
|||||||
onBookClick: (Book) -> Unit,
|
onBookClick: (Book) -> Unit,
|
||||||
onBookLongClick: (Book) -> Unit
|
onBookLongClick: (Book) -> Unit
|
||||||
) {
|
) {
|
||||||
if (uiState.bookshelfLayoutMode == 0) {
|
|
||||||
LazyColumn(
|
|
||||||
modifier = Modifier.fillMaxSize(),
|
|
||||||
contentPadding = PaddingValues(
|
|
||||||
top = paddingValues.calculateTopPadding(),
|
|
||||||
bottom = 56.dp
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
items(books, key = { it.bookUrl }) { book ->
|
|
||||||
BookItem(
|
|
||||||
book = book,
|
|
||||||
layoutMode = uiState.bookshelfLayoutMode,
|
|
||||||
isCompact = uiState.bookshelfLayoutCompact,
|
|
||||||
isUpdating = uiState.updatingBooks.contains(book.bookUrl),
|
|
||||||
onClick = { onBookClick(book) },
|
|
||||||
onLongClick = { onBookLongClick(book) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(uiState.bookshelfLayoutGrid),
|
columns = GridCells.Fixed(uiState.bookshelfLayoutGrid.coerceAtLeast(1)),
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentPadding = PaddingValues(
|
contentPadding = PaddingValues(
|
||||||
top = paddingValues.calculateTopPadding(),
|
top = paddingValues.calculateTopPadding(),
|
||||||
bottom = paddingValues.calculateBottomPadding() + 16.dp,
|
bottom = 120.dp,
|
||||||
start = 12.dp,
|
start = if (uiState.bookshelfLayoutMode != 0) 12.dp else 0.dp,
|
||||||
end = 12.dp
|
end = if (uiState.bookshelfLayoutMode != 0) 12.dp else 0.dp
|
||||||
),
|
),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
verticalArrangement = Arrangement.spacedBy(if (uiState.bookshelfLayoutMode != 0) 8.dp else 0.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
horizontalArrangement = Arrangement.spacedBy(if (uiState.bookshelfLayoutMode != 0) 8.dp else 0.dp)
|
||||||
) {
|
) {
|
||||||
items(books, key = { it.bookUrl }) { book ->
|
items(books, key = { it.bookUrl }) { book ->
|
||||||
BookItem(
|
BookItem(
|
||||||
@@ -494,7 +460,6 @@ fun BookshelfPage(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
|
|||||||
val scrollTrigger = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
|
val scrollTrigger = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
|
||||||
|
|
||||||
val groupsFlow: StateFlow<List<BookGroup>> = appDb.bookGroupDao.show.asFlow()
|
val groupsFlow: StateFlow<List<BookGroup>> = appDb.bookGroupDao.show.asFlow()
|
||||||
.map { it ?: emptyList() }
|
.map { it }
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
|
||||||
|
|
||||||
private val allBooksFlow = appDb.bookDao.flowAll().flowOn(Dispatchers.Default)
|
private val allBooksFlow = appDb.bookDao.flowAll().flowOn(Dispatchers.Default)
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ fun ExploreScreen(
|
|||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentPadding = PaddingValues(
|
contentPadding = PaddingValues(
|
||||||
top = paddingValues.calculateTopPadding(),
|
top = paddingValues.calculateTopPadding(),
|
||||||
bottom = paddingValues.calculateBottomPadding() + 16.dp
|
bottom = 120.dp
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
uiState.items.forEach { item ->
|
uiState.items.forEach { item ->
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package io.legado.app.ui.main.my
|
package io.legado.app.ui.main.my
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.only
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.systemBars
|
import androidx.compose.foundation.layout.systemBars
|
||||||
@@ -90,9 +92,13 @@ fun MyScreen(
|
|||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(padding)
|
.padding(
|
||||||
.verticalScroll(rememberScrollState())
|
top = padding.calculateTopPadding()
|
||||||
|
)
|
||||||
|
.verticalScroll(rememberScrollState()),
|
||||||
|
//TODO:暂时这样解决,改天加模糊
|
||||||
) {
|
) {
|
||||||
|
|
||||||
SplicedColumnGroup(
|
SplicedColumnGroup(
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
title = ""
|
title = ""
|
||||||
@@ -271,6 +277,8 @@ fun MyScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(Modifier.height(120.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ fun RssScreen(
|
|||||||
start = 12.dp,
|
start = 12.dp,
|
||||||
end = 12.dp,
|
end = 12.dp,
|
||||||
top = paddingValues.calculateTopPadding() + 8.dp,
|
top = paddingValues.calculateTopPadding() + 8.dp,
|
||||||
bottom = paddingValues.calculateBottomPadding() + 12.dp
|
bottom = 120.dp
|
||||||
),
|
),
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
|||||||
@@ -22,7 +22,10 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
@@ -64,6 +67,8 @@ fun BookCover(
|
|||||||
BookCover.getRandomDefaultDrawable(seed = name ?: author ?: path ?: "")
|
BookCover.getRandomDefaultDrawable(seed = name ?: author ?: path ?: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isOnlineCoverLoaded by remember(path) { mutableStateOf(false) }
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.aspectRatio(5f / 7f)
|
.aspectRatio(5f / 7f)
|
||||||
@@ -98,16 +103,26 @@ fun BookCover(
|
|||||||
imageLoader = koinInject(),
|
imageLoader = koinInject(),
|
||||||
contentScale = ContentScale.Crop,
|
contentScale = ContentScale.Crop,
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
onSuccess = { onLoadFinish?.invoke() },
|
onSuccess = {
|
||||||
onError = { onLoadFinish?.invoke() }
|
if (finalPath != null) {
|
||||||
|
isOnlineCoverLoaded = true
|
||||||
|
}
|
||||||
|
onLoadFinish?.invoke()
|
||||||
|
},
|
||||||
|
onError = {
|
||||||
|
isOnlineCoverLoaded = false
|
||||||
|
onLoadFinish?.invoke()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 2. 文字叠加层(始终尝试渲染,由 CoverConfig 内部控制具体显示逻辑)
|
// 2. 文字叠加层(当没有在线封面或者加载失败时显示)
|
||||||
|
if (!isOnlineCoverLoaded) {
|
||||||
CoverTextOverlay(
|
CoverTextOverlay(
|
||||||
name = name,
|
name = name,
|
||||||
author = author,
|
author = author,
|
||||||
isNight = isNight
|
isNight = isNight
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// 3. 角标 (Badge)
|
// 3. 角标 (Badge)
|
||||||
if (badgeContent != null) {
|
if (badgeContent != null) {
|
||||||
|
|||||||
Reference in new issue
Block a user