优化
This commit is contained in:
@@ -9,6 +9,7 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.legado.app.R
|
||||
import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
|
||||
import io.legado.app.ui.widget.components.settingItem.CompactDropdownSettingItem
|
||||
import io.legado.app.ui.widget.components.settingItem.DropdownListSettingItem
|
||||
|
||||
@Composable
|
||||
@@ -39,7 +40,7 @@ fun <T> HomepageLayoutSheet(
|
||||
title = stringResource(R.string.homepage_layout_settings),
|
||||
) {
|
||||
Column {
|
||||
DropdownListSettingItem(
|
||||
CompactDropdownSettingItem(
|
||||
title = stringResource(R.string.homepage_layout_mode),
|
||||
selectedValue = layoutMode.toString(),
|
||||
displayEntries = arrayOf(
|
||||
|
||||
@@ -72,7 +72,9 @@ import io.legado.app.ui.main.homepage.modules.GridRankingModule
|
||||
import io.legado.app.ui.main.homepage.modules.HomepageModuleSkeleton
|
||||
import io.legado.app.ui.main.homepage.modules.RankingModule
|
||||
import io.legado.app.ui.main.homepage.modules.WaterfallItem
|
||||
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||
import io.legado.app.ui.theme.LegadoTheme
|
||||
import io.legado.app.ui.theme.adaptiveContentPaddingBookshelf
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import io.legado.app.ui.widget.components.AppScaffold
|
||||
import io.legado.app.ui.widget.components.LoadMoreFooter
|
||||
@@ -84,6 +86,7 @@ import io.legado.app.ui.widget.components.card.GlassCard
|
||||
import io.legado.app.ui.widget.components.icon.AppIcon
|
||||
import io.legado.app.ui.widget.components.tabRow.AppTabRow
|
||||
import io.legado.app.ui.widget.components.EmptyMessage
|
||||
import io.legado.app.ui.widget.components.icon.AppIcons
|
||||
import io.legado.app.ui.widget.components.text.AppText
|
||||
import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar
|
||||
import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults
|
||||
@@ -171,12 +174,12 @@ fun HomepageScreen(
|
||||
actions = {
|
||||
TopBarActionButton(
|
||||
onClick = { viewModel.toggleConfigMode() },
|
||||
imageVector = Icons.Default.GridView,
|
||||
imageVector = AppIcons.MoreCircle,
|
||||
contentDescription = "Layout Settings",
|
||||
)
|
||||
TopBarActionButton(
|
||||
onClick = { viewModel.toggleManageMode() },
|
||||
imageVector = Icons.Default.Settings,
|
||||
imageVector = AppIcons.Settings,
|
||||
contentDescription = "Manage Modules",
|
||||
)
|
||||
},
|
||||
@@ -200,14 +203,14 @@ fun HomepageScreen(
|
||||
AppPullToRefresh(
|
||||
isRefreshing = uiState.isRefreshing,
|
||||
onRefresh = { viewModel.onRefresh() },
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
if (selectedSets.isEmpty()) {
|
||||
EmptyMessage(
|
||||
messageResId = R.string.homepage_no_source_sets_selected,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues),
|
||||
)
|
||||
} else {
|
||||
HorizontalPager(
|
||||
@@ -231,6 +234,7 @@ fun HomepageScreen(
|
||||
modules = sourceModules,
|
||||
viewModel = viewModel,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
paddingValues = paddingValues,
|
||||
onErrorClick = { errorMsg = it },
|
||||
sharedTransitionScope = sharedTransitionScope,
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
@@ -344,6 +348,7 @@ private fun ModuleList(
|
||||
modules: List<HomepageModuleUi>,
|
||||
viewModel: HomepageViewModel,
|
||||
modifier: Modifier = Modifier,
|
||||
paddingValues: PaddingValues = PaddingValues(0.dp),
|
||||
gridState: LazyStaggeredGridState = rememberLazyStaggeredGridState(),
|
||||
sharedTransitionScope: SharedTransitionScope? = null,
|
||||
animatedVisibilityScope: AnimatedVisibilityScope? = null,
|
||||
@@ -381,7 +386,11 @@ private fun ModuleList(
|
||||
modifier = modifier,
|
||||
verticalItemSpacing = 16.dp,
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
contentPadding = PaddingValues(start = 16.dp, end = 16.dp, bottom = 80.dp),
|
||||
contentPadding = adaptiveContentPaddingBookshelf(
|
||||
top = paddingValues.calculateTopPadding(),
|
||||
bottom = if (ThemeConfig.useFloatingBottomBar || ThemeConfig.enableBlur) 120.dp else 8.dp,
|
||||
horizontal = 4.dp
|
||||
),
|
||||
) {
|
||||
processedModules.forEach { moduleUi ->
|
||||
// 1. 头部 (全宽)
|
||||
|
||||
@@ -104,9 +104,6 @@ class HomepageViewModel(
|
||||
private val _layoutConfigCache = MutableStateFlow<Map<String, Map<String, String>>>(emptyMap())
|
||||
private val _pendingEnabled = MutableStateFlow<Map<String, Boolean>>(emptyMap())
|
||||
private val _pendingUserModules = MutableStateFlow<List<ModuleItem>>(emptyList())
|
||||
private val _exploreKindsCache =
|
||||
MutableStateFlow<Map<String, List<Pair<String, String>>>>(emptyMap())
|
||||
|
||||
// 2. 数据库同步流
|
||||
private val localModulesFlow = gateway.flowEnabled()
|
||||
val allModulesCache =
|
||||
@@ -228,27 +225,44 @@ class HomepageViewModel(
|
||||
rawModulesFlow,
|
||||
_bookshelf
|
||||
) { modules, bookshelf ->
|
||||
modules.map { module ->
|
||||
val state = module.state
|
||||
if (state is ModuleLoadState.Loaded) {
|
||||
module.copy(
|
||||
state = state.copy(
|
||||
if (bookshelf.isEmpty()) {
|
||||
modules.map { module ->
|
||||
val state = module.state
|
||||
if (state is ModuleLoadState.Loaded) {
|
||||
module.copy(state = state.copy(
|
||||
books = state.books.map { item ->
|
||||
item.copy(
|
||||
shelfState = resolveBookShelfStateUseCase.execute(
|
||||
name = item.book.name,
|
||||
author = item.book.author,
|
||||
url = item.book.bookUrl,
|
||||
shelf = bookshelf
|
||||
)
|
||||
)
|
||||
if (item.shelfState == BookShelfState.NOT_IN_SHELF) item
|
||||
else item.copy(shelfState = BookShelfState.NOT_IN_SHELF)
|
||||
}.toImmutableList()
|
||||
)
|
||||
)
|
||||
} else {
|
||||
module
|
||||
))
|
||||
} else module
|
||||
}.toImmutableList()
|
||||
} else {
|
||||
val exactKeys = HashSet<Triple<String, String, String?>>(bookshelf.size)
|
||||
val nameAuthorKeys = HashSet<Pair<String, String>>(bookshelf.size)
|
||||
for (key in bookshelf) {
|
||||
exactKeys.add(Triple(key.name, key.author, key.url))
|
||||
nameAuthorKeys.add(key.name to key.author)
|
||||
}
|
||||
}.toImmutableList()
|
||||
modules.map { module ->
|
||||
val state = module.state
|
||||
if (state is ModuleLoadState.Loaded) {
|
||||
module.copy(state = state.copy(
|
||||
books = state.books.map { item ->
|
||||
val bookTriple = Triple(item.book.name, item.book.author, item.book.bookUrl)
|
||||
val newShelfState = when {
|
||||
bookTriple in exactKeys -> BookShelfState.IN_SHELF
|
||||
(item.book.name to item.book.author) in nameAuthorKeys ->
|
||||
BookShelfState.SAME_NAME_AUTHOR
|
||||
else -> BookShelfState.NOT_IN_SHELF
|
||||
}
|
||||
if (item.shelfState == newShelfState) item
|
||||
else item.copy(shelfState = newShelfState)
|
||||
}.toImmutableList()
|
||||
))
|
||||
} else module
|
||||
}.toImmutableList()
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 最终 UI 状态
|
||||
@@ -308,6 +322,10 @@ class HomepageViewModel(
|
||||
allModulesCache.collect { modules ->
|
||||
val dbIds = modules.map { it.id }.toSet()
|
||||
_pendingUserModules.update { pending -> pending.filter { it.id !in dbIds } }
|
||||
_moduleContentStates.update { states ->
|
||||
if (states.keys.any { it !in dbIds }) states.filterKeys { it in dbIds }
|
||||
else states
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,8 +632,7 @@ class HomepageViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
fun getSourceExploreKinds(sourceUrl: String): List<Pair<String, String>> =
|
||||
_exploreKindsCache.value[sourceUrl].orEmpty()
|
||||
fun getSourceExploreKinds(sourceUrl: String): List<Pair<String, String>> = emptyList()
|
||||
|
||||
fun updateModule(globalId: String, def: ModuleDef) {
|
||||
viewModelScope.launch {
|
||||
|
||||
@@ -13,6 +13,7 @@ import androidx.compose.material.icons.filled.FilterList
|
||||
import androidx.compose.material.icons.filled.History
|
||||
import androidx.compose.material.icons.filled.Home
|
||||
import androidx.compose.material.icons.filled.LocationSearching
|
||||
import androidx.compose.material.icons.filled.MoreHoriz
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material.icons.filled.MyLocation
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
@@ -40,6 +41,7 @@ import top.yukonga.miuix.kmp.icon.extended.Edit
|
||||
import top.yukonga.miuix.kmp.icon.extended.Favorites
|
||||
import top.yukonga.miuix.kmp.icon.extended.Filter
|
||||
import top.yukonga.miuix.kmp.icon.extended.More
|
||||
import top.yukonga.miuix.kmp.icon.extended.MoreCircle
|
||||
import top.yukonga.miuix.kmp.icon.extended.Notes
|
||||
import top.yukonga.miuix.kmp.icon.extended.Pin
|
||||
import top.yukonga.miuix.kmp.icon.extended.Refresh
|
||||
@@ -105,6 +107,11 @@ object AppIcons {
|
||||
@Composable
|
||||
get() = if (isMiuix) MiuixIcons.Refresh else Icons.Default.Replay
|
||||
|
||||
val MoreCircle: ImageVector
|
||||
@Composable
|
||||
get() = if (isMiuix) MiuixIcons.MoreCircle else Icons.Default.MoreHoriz
|
||||
|
||||
|
||||
@Composable
|
||||
fun mainDestination(destination: MainDestination, selected: Boolean): ImageVector {
|
||||
return when (destination) {
|
||||
|
||||
Reference in New Issue
Block a user