Просмотр исходного кода

feat: 导航栏可以调整未选中已选中

HapeLee 3 месяцев назад
Родитель
Сommit
84062d9443

+ 5 - 0
app/src/main/java/io/legado/app/constant/PreferKey.kt

@@ -397,6 +397,11 @@ object PreferKey {
     const val navIconExplore = "navIconExplore"
     const val navIconRss = "navIconRss"
     const val navIconMy = "navIconMy"
+    const val navIconHomeSelected = "navIconHomeSelected"
+    const val navIconBookshelfSelected = "navIconBookshelfSelected"
+    const val navIconExploreSelected = "navIconExploreSelected"
+    const val navIconRssSelected = "navIconRssSelected"
+    const val navIconMySelected = "navIconMySelected"
 
     // Translation
     const val llmTranslateEnabled = "llmTranslateEnabled"

+ 10 - 0
app/src/main/java/io/legado/app/data/repository/FeatureSettingsRepositories.kt

@@ -302,6 +302,11 @@ internal fun Preferences.toAppShellSettings(): AppShellSettings = AppShellSettin
     navIconExplore = compatDsString(PreferKey.navIconExplore) ?: "",
     navIconRss = compatDsString(PreferKey.navIconRss) ?: "",
     navIconMy = compatDsString(PreferKey.navIconMy) ?: "",
+    navIconHomeSelected = compatDsString(PreferKey.navIconHomeSelected) ?: "",
+    navIconBookshelfSelected = compatDsString(PreferKey.navIconBookshelfSelected) ?: "",
+    navIconExploreSelected = compatDsString(PreferKey.navIconExploreSelected) ?: "",
+    navIconRssSelected = compatDsString(PreferKey.navIconRssSelected) ?: "",
+    navIconMySelected = compatDsString(PreferKey.navIconMySelected) ?: "",
     launcherIcon = compatDsString(PreferKey.launcherIcon) ?: "ic_launcher",
 )
 
@@ -328,6 +333,11 @@ internal fun AppShellSettings.toPrefMap(): Map<String, Any?> = mapOf(
     PreferKey.navIconExplore to navIconExplore,
     PreferKey.navIconRss to navIconRss,
     PreferKey.navIconMy to navIconMy,
+    PreferKey.navIconHomeSelected to navIconHomeSelected,
+    PreferKey.navIconBookshelfSelected to navIconBookshelfSelected,
+    PreferKey.navIconExploreSelected to navIconExploreSelected,
+    PreferKey.navIconRssSelected to navIconRssSelected,
+    PreferKey.navIconMySelected to navIconMySelected,
     PreferKey.launcherIcon to launcherIcon,
 )
 

+ 5 - 0
app/src/main/java/io/legado/app/domain/model/settings/AppShellSettings.kt

@@ -23,5 +23,10 @@ data class AppShellSettings(
     val navIconExplore: String = "",
     val navIconRss: String = "",
     val navIconMy: String = "",
+    val navIconHomeSelected: String = "",
+    val navIconBookshelfSelected: String = "",
+    val navIconExploreSelected: String = "",
+    val navIconRssSelected: String = "",
+    val navIconMySelected: String = "",
     val launcherIcon: String = "ic_launcher",
 )

+ 14 - 0
app/src/main/java/io/legado/app/ui/config/themeConfig/MainNavigationSettingsSheet.kt

@@ -16,6 +16,7 @@ import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringArrayResource
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
 import io.legado.app.R
@@ -39,6 +40,7 @@ fun MainNavigationSettingsSheet(
     onSetDefault: (String) -> Unit,
     onRequestNavigationIcon: (String) -> Unit,
     onClearNavigationIcon: (String) -> Unit,
+    onSetLabelVisibilityMode: (String) -> Unit,
 ) {
     var showNavigationIcons by remember(show) { mutableStateOf(false) }
     var navigationItems by remember(show) {
@@ -99,6 +101,13 @@ fun MainNavigationSettingsSheet(
                 entryValues = visibleItems.map { it.route }.toTypedArray(),
                 onValueChange = onSetDefault,
             )
+            CompactDropdownSettingItem(
+                title = stringResource(R.string.nav_label_mode),
+                selectedValue = settings.labelVisibilityMode,
+                displayEntries = stringArrayResource(R.array.label_vis_mode),
+                entryValues = stringArrayResource(R.array.label_vis_mode_value),
+                onValueChange = onSetLabelVisibilityMode,
+            )
             Spacer(modifier = Modifier.padding(bottom = 4.dp))
             val customIconCount = listOf(
                 settings.navIconHome,
@@ -106,6 +115,11 @@ fun MainNavigationSettingsSheet(
                 settings.navIconExplore,
                 settings.navIconRss,
                 settings.navIconMy,
+                settings.navIconHomeSelected,
+                settings.navIconBookshelfSelected,
+                settings.navIconExploreSelected,
+                settings.navIconRssSelected,
+                settings.navIconMySelected,
             ).count { it.isNotEmpty() }
             CompactClickableSettingItem(
                 title = stringResource(R.string.theme_config_nav_icons),

+ 135 - 64
app/src/main/java/io/legado/app/ui/config/themeConfig/NavIconManageSheet.kt

@@ -5,11 +5,11 @@ import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.aspectRatio
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Add
 import androidx.compose.material.icons.filled.Close
@@ -22,18 +22,21 @@ import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
 import coil.compose.AsyncImage
 import io.legado.app.R
+import io.legado.app.domain.model.settings.AppShellSettings
+import io.legado.app.ui.main.MainDestination
 import io.legado.app.ui.theme.LegadoTheme
 import io.legado.app.ui.widget.components.button.series.SmallTonalButton
 import io.legado.app.ui.widget.components.card.NormalCard
 import io.legado.app.ui.widget.components.icon.AppIcon
+import io.legado.app.ui.widget.components.icon.AppIcons
 import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
 import io.legado.app.ui.widget.components.text.AppText
-import io.legado.app.domain.model.settings.AppShellSettings
 
 private data class NavIconDestination(
     val key: String,
     @param:StringRes val labelRes: Int,
-    val path: String,
+    val unselectedPath: String,
+    val selectedPath: String,
 )
 
 @OptIn(ExperimentalMaterial3Api::class)
@@ -49,12 +52,23 @@ fun NavIconManageSheet(
         NavIconDestination(
             "home",
             R.string.home,
-            settings.navIconHome
+            settings.navIconHome,
+            settings.navIconHomeSelected,
+        ),
+        NavIconDestination(
+            "bookshelf",
+            R.string.bookshelf,
+            settings.navIconBookshelf,
+            settings.navIconBookshelfSelected,
         ),
-        NavIconDestination("bookshelf", R.string.bookshelf, settings.navIconBookshelf),
-        NavIconDestination("explore", R.string.discovery, settings.navIconExplore),
-        NavIconDestination("rss", R.string.rss, settings.navIconRss),
-        NavIconDestination("my", R.string.my, settings.navIconMy),
+        NavIconDestination(
+            "explore",
+            R.string.discovery,
+            settings.navIconExplore,
+            settings.navIconExploreSelected,
+        ),
+        NavIconDestination("rss", R.string.rss, settings.navIconRss, settings.navIconRssSelected),
+        NavIconDestination("my", R.string.my, settings.navIconMy, settings.navIconMySelected),
     )
 
     AppModalBottomSheet(
@@ -62,69 +76,60 @@ fun NavIconManageSheet(
         onDismissRequest = onDismissRequest,
         title = stringResource(R.string.theme_config_nav_icons),
     ) {
-        Column(modifier = Modifier
-            .fillMaxWidth()
-            .padding(bottom = 24.dp)) {
+        Column(
+            modifier = Modifier
+                .fillMaxWidth(),
+            verticalArrangement = Arrangement.spacedBy(12.dp),
+        ) {
             Row(
                 modifier = Modifier
                     .fillMaxWidth()
-                    .padding(horizontal = 16.dp),
-                horizontalArrangement = Arrangement.spacedBy(12.dp)
+                    .padding(horizontal = 12.dp),
+                horizontalArrangement = Arrangement.spacedBy(12.dp),
+                verticalAlignment = Alignment.CenterVertically,
             ) {
-                destinations.forEach { dest ->
-                    val label = stringResource(dest.labelRes)
-                    Column(
-                        modifier = Modifier.weight(1f),
-                        horizontalAlignment = Alignment.CenterHorizontally
+                Box(modifier = Modifier.weight(1f))
+                NavigationIconColumnHeader(stringResource(R.string.theme_config_nav_icon_unselected))
+                NavigationIconColumnHeader(stringResource(R.string.theme_config_nav_icon_selected))
+            }
+            destinations.forEach { destination ->
+                NormalCard(
+                    modifier = Modifier
+                        .fillMaxWidth(),
+                    cornerRadius = 16.dp,
+                    containerColor = LegadoTheme.colorScheme.onSheetContent,
+                ) {
+                    Row(
+                        modifier = Modifier.padding(all = 12.dp),
+                        horizontalArrangement = Arrangement.spacedBy(12.dp),
+                        verticalAlignment = Alignment.CenterVertically,
                     ) {
-                        NormalCard(
-                            onClick = {
-                                onSelectIcon(dest.key)
-                            },
-                            cornerRadius = 12.dp,
-                            containerColor = LegadoTheme.colorScheme.surfaceContainerHigh,
+                        AppIcon(
+                            imageVector = AppIcons.mainDestination(
+                                destination.mainDestination,
+                                selected = false,
+                            ),
+                            contentDescription = null,
                             modifier = Modifier
-                                .fillMaxWidth()
-                                .aspectRatio(1f)
-                        ) {
-                            if (dest.path.isNotEmpty()) {
-                                Box(modifier = Modifier.fillMaxSize()) {
-                                    AsyncImage(
-                                        model = dest.path,
-                                        contentDescription = label,
-                                        modifier = Modifier.fillMaxSize(),
-                                        contentScale = ContentScale.Fit
-                                    )
-                                    SmallTonalButton(
-                                        onClick = { onClearIcon(dest.key) },
-                                        modifier = Modifier
-                                            .align(Alignment.TopEnd)
-                                            .padding(4.dp)
-                                            .size(24.dp),
-                                        icon = Icons.Default.Close,
-                                        contentDescription = stringResource(R.string.close)
-                                    )
-                                }
-                            } else {
-                                Box(
-                                    modifier = Modifier.fillMaxSize(),
-                                    contentAlignment = Alignment.Center
-                                ) {
-                                    AppIcon(
-                                        imageVector = Icons.Default.Add,
-                                        contentDescription = stringResource(
-                                            R.string.theme_config_add_nav_icon,
-                                            label
-                                        ),
-                                        modifier = Modifier.size(32.dp),
-                                        tint = LegadoTheme.colorScheme.primary
-                                    )
-                                }
-                            }
-                        }
+                                .padding(start = 4.dp)
+                                .size(24.dp),
+                        )
                         AppText(
-                            text = label,
-                            modifier = Modifier.padding(top = 8.dp),
+                            text = stringResource(destination.labelRes),
+                            style = LegadoTheme.typography.labelMediumEmphasized,
+                            modifier = Modifier.weight(1f),
+                        )
+                        NavigationIconSlot(
+                            label = stringResource(R.string.theme_config_nav_icon_unselected),
+                            path = destination.unselectedPath,
+                            onSelect = { onSelectIcon(destination.key) },
+                            onClear = { onClearIcon(destination.key) },
+                        )
+                        NavigationIconSlot(
+                            label = stringResource(R.string.theme_config_nav_icon_selected),
+                            path = destination.selectedPath,
+                            onSelect = { onSelectIcon("${destination.key}:selected") },
+                            onClear = { onClearIcon("${destination.key}:selected") },
                         )
                     }
                 }
@@ -132,3 +137,69 @@ fun NavIconManageSheet(
         }
     }
 }
+
+@Composable
+private fun NavigationIconSlot(
+    label: String,
+    path: String,
+    onSelect: () -> Unit,
+    onClear: () -> Unit,
+) {
+    NormalCard(
+        onClick = onSelect,
+        cornerRadius = 12.dp,
+        containerColor = LegadoTheme.colorScheme.surfaceContainer,
+        modifier = Modifier.size(40.dp),
+    ) {
+        if (path.isNotEmpty()) {
+            Box(modifier = Modifier.fillMaxSize()) {
+                AsyncImage(
+                    model = path,
+                    contentDescription = label,
+                    modifier = Modifier.fillMaxSize(),
+                    contentScale = ContentScale.Fit,
+                )
+                SmallTonalButton(
+                    onClick = onClear,
+                    modifier = Modifier
+                        .align(Alignment.TopEnd)
+                        .padding(4.dp)
+                        .size(24.dp),
+                    icon = Icons.Default.Close,
+                    contentDescription = stringResource(R.string.close),
+                )
+            }
+        } else {
+            Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
+                AppIcon(
+                    imageVector = Icons.Default.Add,
+                    contentDescription = stringResource(R.string.theme_config_add_nav_icon, label),
+                    modifier = Modifier.size(24.dp),
+                    tint = LegadoTheme.colorScheme.primary,
+                )
+            }
+        }
+    }
+}
+
+@Composable
+private fun NavigationIconColumnHeader(label: String) {
+    Box(
+        modifier = Modifier.width(40.dp),
+        contentAlignment = Alignment.Center,
+    ) {
+        AppText(
+            text = label,
+            style = LegadoTheme.typography.labelSmallEmphasized
+        )
+    }
+}
+
+private val NavIconDestination.mainDestination: MainDestination
+    get() = when (key) {
+        MainDestination.Home.route -> MainDestination.Home
+        MainDestination.Bookshelf.route -> MainDestination.Bookshelf
+        MainDestination.Explore.route -> MainDestination.Explore
+        MainDestination.Rss.route -> MainDestination.Rss
+        else -> MainDestination.My
+    }

+ 1 - 1
app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeConfigRouteScreen.kt

@@ -50,7 +50,7 @@ fun ThemeConfigRouteScreen(
         if (uri != null && destination != null) {
             runCatching {
                 val iconDir = File(context.filesDir, "nav_icons").apply { mkdirs() }
-                val destinationFile = File(iconDir, "$destination.png")
+                val destinationFile = File(iconDir, "${destination.replace(':', '-')}.png")
                 context.contentResolver.openInputStream(uri)?.use { input ->
                     destinationFile.outputStream().use(input::copyTo)
                 }

+ 3 - 11
app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeConfigScreen.kt

@@ -396,17 +396,6 @@ fun ThemeConfigScreen(
                             )
                         }
                     )
-                    DropdownListSettingItem(
-                        title = stringResource(R.string.nav_label_mode),
-                        selectedValue = appShell.labelVisibilityMode,
-                        displayEntries = stringArrayResource(R.array.label_vis_mode),
-                        entryValues = stringArrayResource(R.array.label_vis_mode_value),
-                        onValueChange = {
-                            onIntent(
-                                ThemeConfigIntent.SetLabelVisibilityMode(it)
-                            )
-                        }
-                    )
                 }
 
                 SplicedColumnGroup(title = stringResource(R.string.book_info_page)) {
@@ -964,6 +953,9 @@ fun ThemeConfigScreen(
         onSetDefault = { onIntent(ThemeConfigIntent.SetDefaultHomePage(it)) },
         onRequestNavigationIcon = { onIntent(ThemeConfigIntent.RequestNavigationIcon(it)) },
         onClearNavigationIcon = { onIntent(ThemeConfigIntent.SelectNavigationIcon(it, "")) },
+        onSetLabelVisibilityMode = {
+            onIntent(ThemeConfigIntent.SetLabelVisibilityMode(it))
+        },
     )
 
 

+ 24 - 5
app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeConfigViewModel.kt

@@ -7,9 +7,9 @@ import io.legado.app.R
 import io.legado.app.constant.PreferKey
 import io.legado.app.domain.gateway.AppShellSettingsGateway
 import io.legado.app.domain.gateway.CoverSettingsGateway
+import io.legado.app.domain.gateway.LabSettingsGateway
 import io.legado.app.domain.gateway.ReadSettingsGateway
 import io.legado.app.domain.gateway.ThemeSettingsGateway
-import io.legado.app.domain.gateway.LabSettingsGateway
 import io.legado.app.domain.model.settings.AppShellSettings
 import io.legado.app.domain.model.settings.CoverSettings
 import io.legado.app.domain.model.settings.ThemeSettings
@@ -20,10 +20,6 @@ import io.legado.app.utils.MD5Utils
 import io.legado.app.utils.externalFiles
 import io.legado.app.utils.inputStream
 import io.legado.app.utils.openInputStream
-import java.io.File
-import java.io.FileOutputStream
-import java.util.UUID
-import kotlin.coroutines.cancellation.CancellationException
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Job
@@ -36,6 +32,10 @@ import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.update
 import kotlinx.coroutines.launch
 import splitties.init.appCtx
+import java.io.File
+import java.io.FileOutputStream
+import java.util.UUID
+import kotlin.coroutines.cancellation.CancellationException
 
 class ThemeConfigViewModel(
     private val appShellSettingsGateway: AppShellSettingsGateway,
@@ -345,6 +345,25 @@ class ThemeConfigViewModel(
             MainDestination.My.route -> { settings ->
                 settings.copy(navIconMy = intent.path)
             }
+            "${MainDestination.Home.route}:selected" -> { settings ->
+                settings.copy(navIconHomeSelected = intent.path)
+            }
+
+            "${MainDestination.Bookshelf.route}:selected" -> { settings ->
+                settings.copy(navIconBookshelfSelected = intent.path)
+            }
+
+            "${MainDestination.Explore.route}:selected" -> { settings ->
+                settings.copy(navIconExploreSelected = intent.path)
+            }
+
+            "${MainDestination.Rss.route}:selected" -> { settings ->
+                settings.copy(navIconRssSelected = intent.path)
+            }
+
+            "${MainDestination.My.route}:selected" -> { settings ->
+                settings.copy(navIconMySelected = intent.path)
+            }
             else -> return
         }
         updateAppShell(transform = transform)

+ 13 - 0
app/src/main/java/io/legado/app/ui/main/MainContract.kt

@@ -18,6 +18,11 @@ data class MainUiState(
     val navIconExplore: String = "",
     val navIconRss: String = "",
     val navIconMy: String = "",
+    val navIconHomeSelected: String = "",
+    val navIconBookshelfSelected: String = "",
+    val navIconExploreSelected: String = "",
+    val navIconRssSelected: String = "",
+    val navIconMySelected: String = "",
     val deepPersonalizationActive: Boolean = false,
     val secondaryThemeColor: Int = 0,
     val secondaryThemeColorNight: Int = 0,
@@ -29,6 +34,14 @@ data class MainUiState(
         MainDestination.Rss -> navIconRss
         MainDestination.My -> navIconMy
     }
+
+    fun selectedCustomIconPath(destination: MainDestination): String = when (destination) {
+        MainDestination.Home -> navIconHomeSelected
+        MainDestination.Bookshelf -> navIconBookshelfSelected
+        MainDestination.Explore -> navIconExploreSelected
+        MainDestination.Rss -> navIconRssSelected
+        MainDestination.My -> navIconMySelected
+    }
 }
 
 sealed interface MainUiIntent {

+ 16 - 8
app/src/main/java/io/legado/app/ui/main/MainScreen.kt

@@ -436,8 +436,7 @@ fun MainScreen(
                             }
                         },
                         label = if (labelVisibilityMode != "unlabeled") {
-                            val hasCustomIcon = mainUiState.customIconPath(destination).isNotEmpty()
-                            if (hasCustomIcon) null else {{ AppText(stringResource(destination.labelId)) }}
+                            { AppText(stringResource(destination.labelId)) }
                         } else null
                     )
                 }
@@ -455,6 +454,8 @@ fun MainScreen(
                         destinations.forEachIndexed { index, destination ->
                             val selected = pagerState.targetPage == index
                             val customIconPath = mainUiState.customIconPath(destination)
+                            val selectedCustomIconPath =
+                                mainUiState.selectedCustomIconPath(destination)
                             val destinationLabel = stringResource(destination.labelId)
                             AppNavigationBarItem(
                                 modifier = Modifier.semantics(mergeDescendants = true) {
@@ -470,14 +471,16 @@ fun MainScreen(
                                     NavigationIcon(
                                         destination = destination,
                                         selected = selected,
-                                        customIconPath = mainUiState.customIconPath(destination),
+                                        customIconPath = if (selected) {
+                                            selectedCustomIconPath.ifEmpty { customIconPath }
+                                        } else customIconPath,
                                     )
                                 },
                                 m3IndicatorColor = GlassDefaults.glassColor(
                                     noBlurColor = LegadoTheme.colorScheme.secondaryContainer,
                                     blurAlpha = GlassDefaults.ThickBlurAlpha
                                 ),
-                                m3ShowLabel = showLabel && !customIconPath.isNotEmpty(),
+                                m3ShowLabel = showLabel,
                                 m3AlwaysShowLabel = alwaysShowLabel,
                                 useCustomIcon = customIconPath.isNotEmpty()
                             )
@@ -651,12 +654,15 @@ fun MainScreen(
                             tabsCount = destinations.size,
                             isBlurEnabled = useLiquidGlass,
                             hasCustomIcons = destinations.any { dest ->
-                                mainUiState.customIconPath(dest).isNotEmpty()
+                                mainUiState.customIconPath(dest).isNotEmpty() ||
+                                        mainUiState.selectedCustomIconPath(dest).isNotEmpty()
                             }
                         ) {
                             destinations.forEachIndexed { index, destination ->
                                 val selected = pagerState.targetPage == index
-                                val hasCustomIcon = mainUiState.customIconPath(destination).isNotEmpty()
+                                val customIconPath = mainUiState.customIconPath(destination)
+                                val selectedCustomIconPath =
+                                    mainUiState.selectedCustomIconPath(destination)
                                 val destinationLabel = stringResource(destination.labelId)
                                 FloatingBottomBarItem(
                                     onClick = {
@@ -670,10 +676,12 @@ fun MainScreen(
                                 ) {
                                     NavigationIcon(
                                         destination = destination,
-                                        customIconPath = mainUiState.customIconPath(destination),
+                                        customIconPath = if (selected) {
+                                            selectedCustomIconPath.ifEmpty { customIconPath }
+                                        } else customIconPath,
                                         selected = selected
                                     )
-                                    if (!hasCustomIcon && showLabel && (alwaysShowLabel || selected)) {
+                                    if (showLabel && (alwaysShowLabel || selected)) {
                                         AppText(
                                             text = stringResource(destination.labelId),
                                             style = MaterialTheme.typography.labelSmall,

+ 5 - 0
app/src/main/java/io/legado/app/ui/main/MainViewModel.kt

@@ -120,6 +120,11 @@ private fun buildMainUiState(
         navIconExplore = appShell.navIconExplore,
         navIconRss = appShell.navIconRss,
         navIconMy = appShell.navIconMy,
+        navIconHomeSelected = appShell.navIconHomeSelected,
+        navIconBookshelfSelected = appShell.navIconBookshelfSelected,
+        navIconExploreSelected = appShell.navIconExploreSelected,
+        navIconRssSelected = appShell.navIconRssSelected,
+        navIconMySelected = appShell.navIconMySelected,
         deepPersonalizationActive = theme.appTheme == "12" && theme.enableDeepPersonalization,
         secondaryThemeColor = theme.secondaryThemeColor,
         secondaryThemeColorNight = theme.secondaryThemeColorNight,

+ 5 - 3
app/src/main/java/io/legado/app/ui/main/bookshelf/BookItem.kt

@@ -757,10 +757,12 @@ fun BookItem(
                                 text = label,
                                 backgroundColor = if (colorPair != null && colorPair.bgColor != 0) Color(
                                     colorPair.bgColor
-                                ) else LegadoTheme.colorScheme.cardPrimaryContainer,
-                                contentColor = if (colorPair != null && colorPair.textColor != 0) Color(colorPair.textColor) else LegadoTheme.colorScheme.primary.copy(alpha = 0.8f),
+                                ) else LegadoTheme.colorScheme.secondaryContainer,
+                                contentColor = if (colorPair != null && colorPair.textColor != 0) Color(
+                                    colorPair.textColor
+                                ) else LegadoTheme.colorScheme.primary,
                                 cornerRadius = 4.dp,
-                                horizontalPadding = 4.dp,
+                                horizontalPadding = 6.dp,
                                 verticalPadding = 2.dp,
                                 textStyle = LegadoTheme.typography.labelSmallEmphasized
                             )

+ 2 - 0
app/src/main/res/values-zh-rCN/strings.xml

@@ -1554,6 +1554,8 @@
     <string name="theme_config_nav_icons_custom_count">已设置 %1$d 个自定义图标</string>
     <string name="theme_config_nav_icons_default">使用默认图标</string>
     <string name="theme_config_add_nav_icon">添加%1$s图标</string>
+    <string name="theme_config_nav_icon_unselected">未选中</string>
+    <string name="theme_config_nav_icon_selected">已选中</string>
     <string name="theme_config_no_font_files">没有字体文件</string>
     <string name="theme_config_reset_defaults">恢复默认主题配置</string>
     <string name="theme_config_reset_defaults_summary">恢复外观页设置,不影响已保存主题和封面</string>

+ 2 - 0
app/src/main/res/values/strings.xml

@@ -1613,6 +1613,8 @@
     <string name="theme_config_nav_icons_custom_count">%1$d custom icons set</string>
     <string name="theme_config_nav_icons_default">Using default icons</string>
     <string name="theme_config_add_nav_icon">Add %1$s icon</string>
+    <string name="theme_config_nav_icon_unselected">Unselected</string>
+    <string name="theme_config_nav_icon_selected">Selected</string>
     <string name="theme_config_no_font_files">No font files</string>
     <string name="input_value_range">Enter value (%1$d-%2$d)</string>
     <string name="change_icon_success">Icon Updated</string>

+ 11 - 1
app/src/test/java/io/legado/app/data/repository/AppShellSettingsMappingTest.kt

@@ -8,7 +8,7 @@ import org.junit.Test
 class AppShellSettingsMappingTest {
 
     @Test
-    fun `AppShell 23 键写读映射逐字段对应`() {
+    fun `AppShell 28 键写读映射逐字段对应`() {
         appShellMappingSamples().forEach { expected ->
             assertEquals(expected.expectedPrefMap(), expected.toPrefMap())
             assertEquals(
@@ -56,6 +56,11 @@ private fun appShellMappingSamples(): List<AppShellSettings> {
         navIconExplore = "icon-explore",
         navIconRss = "icon-rss",
         navIconMy = "icon-my",
+        navIconHomeSelected = "icon-home-selected",
+        navIconBookshelfSelected = "icon-bookshelf-selected",
+        navIconExploreSelected = "icon-explore-selected",
+        navIconRssSelected = "icon-rss-selected",
+        navIconMySelected = "icon-my-selected",
         launcherIcon = "launcher-icon",
     )
     return listOf(
@@ -96,5 +101,10 @@ private fun AppShellSettings.expectedPrefMap(): Map<String, Any?> = mapOf(
     PreferKey.navIconExplore to navIconExplore,
     PreferKey.navIconRss to navIconRss,
     PreferKey.navIconMy to navIconMy,
+    PreferKey.navIconHomeSelected to navIconHomeSelected,
+    PreferKey.navIconBookshelfSelected to navIconBookshelfSelected,
+    PreferKey.navIconExploreSelected to navIconExploreSelected,
+    PreferKey.navIconRssSelected to navIconRssSelected,
+    PreferKey.navIconMySelected to navIconMySelected,
     PreferKey.launcherIcon to launcherIcon,
 )

+ 1 - 0
app/src/test/java/io/legado/app/service/TTSReadAloudProgressTest.kt

@@ -86,4 +86,5 @@ class TTSReadAloudProgressTest {
             findReadAloudPageIndex(0, 101, pageStarts.size, pageStarts::get)
         )
     }
+
 }