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

refactor: 迁移 Bookshelf 设置网关

5151561 3 месяцев назад
Родитель
Сommit
1fd358012f

+ 56 - 58
app/src/main/java/io/legado/app/data/repository/BookshelfSettingsRepository.kt

@@ -3,10 +3,7 @@ package io.legado.app.data.repository
 import androidx.datastore.preferences.core.Preferences
 import androidx.datastore.preferences.core.Preferences
 import io.legado.app.constant.PreferKey
 import io.legado.app.constant.PreferKey
 import io.legado.app.data.entities.BookGroup
 import io.legado.app.data.entities.BookGroup
-import io.legado.app.domain.gateway.BookshelfBooleanSetting
-import io.legado.app.domain.gateway.BookshelfIntSetting
 import io.legado.app.domain.gateway.BookshelfSettingsGateway
 import io.legado.app.domain.gateway.BookshelfSettingsGateway
-import io.legado.app.domain.gateway.BookshelfSettingsUpdate
 import io.legado.app.domain.model.settings.BookshelfSettings
 import io.legado.app.domain.model.settings.BookshelfSettings
 import io.legado.app.help.config.AppConfigStore
 import io.legado.app.help.config.AppConfigStore
 import io.legado.app.help.config.compatDsBoolean
 import io.legado.app.help.config.compatDsBoolean
@@ -24,64 +21,16 @@ class BookshelfSettingsRepository : BookshelfSettingsGateway {
         .map(Preferences::toBookshelfSettings)
         .map(Preferences::toBookshelfSettings)
         .distinctUntilChanged()
         .distinctUntilChanged()
 
 
-    override suspend fun update(update: BookshelfSettingsUpdate) {
-        val (key, value) = when (update) {
-            is BookshelfSettingsUpdate.SaveTabPosition -> PreferKey.saveTabPosition to update.value
-            is BookshelfSettingsUpdate.BooleanValue -> when (update.setting) {
-                BookshelfBooleanSetting.ShowUnread -> PreferKey.showUnread
-                BookshelfBooleanSetting.ShowUnreadNew -> PreferKey.showUnreadNew
-                BookshelfBooleanSetting.ShowTip -> PreferKey.showTip
-                BookshelfBooleanSetting.ShowBookCount -> PreferKey.showBookCount
-                BookshelfBooleanSetting.ShowLastUpdateTime -> PreferKey.showLastUpdateTime
-                BookshelfBooleanSetting.ShowBookIntro -> PreferKey.showBookIntro
-                BookshelfBooleanSetting.ShowIntro -> PreferKey.bookshelfShowIntro
-                BookshelfBooleanSetting.ShowTag -> PreferKey.bookshelfShowTag
-                BookshelfBooleanSetting.ShowLatestChapter -> PreferKey.bookshelfShowLatestChapter
-                BookshelfBooleanSetting.ShowWaitUpCount -> PreferKey.showWaitUpCount
-                BookshelfBooleanSetting.ShowFastScroller -> PreferKey.showBookshelfFastScroller
-                BookshelfBooleanSetting.ShowExpandButton -> PreferKey.shouldShowExpandButton
-                BookshelfBooleanSetting.LayoutCompact -> PreferKey.bookshelfLayoutCompact
-                BookshelfBooleanSetting.ShowDivider -> PreferKey.bookshelfShowDivider
-                BookshelfBooleanSetting.TitleSmallFont -> PreferKey.bookshelfTitleSmallFont
-                BookshelfBooleanSetting.TitleCenter -> PreferKey.bookshelfTitleCenter
-                BookshelfBooleanSetting.CoverShadow -> PreferKey.bookshelfCoverShadow
-                BookshelfBooleanSetting.SearchActionDirectToSearch -> PreferKey.bookshelfSearchActionDirectToSearch
-                BookshelfBooleanSetting.AutoRefresh -> PreferKey.autoRefresh
-                BookshelfBooleanSetting.HideEmptyGroups -> PreferKey.hideEmptyGroups
-            } to update.value
-            is BookshelfSettingsUpdate.IntValue -> when (update.setting) {
-                BookshelfIntSetting.BookGroupStyle -> PreferKey.bookGroupStyle
-                BookshelfIntSetting.Sort -> PreferKey.bookshelfSort
-                BookshelfIntSetting.SortOrder -> PreferKey.bookshelfSortOrder
-                BookshelfIntSetting.IntroMaxLines -> PreferKey.bookshelfIntroMaxLines
-                BookshelfIntSetting.RefreshingLimit -> PreferKey.bookshelfRefreshingLimit
-                BookshelfIntSetting.LayoutModePortrait -> PreferKey.bookshelfLayoutModePortrait
-                BookshelfIntSetting.LayoutGridPortrait -> PreferKey.bookshelfLayoutGridPortrait
-                BookshelfIntSetting.LayoutModeLandscape -> PreferKey.bookshelfLayoutModeLandscape
-                BookshelfIntSetting.LayoutGridLandscape -> PreferKey.bookshelfLayoutGridLandscape
-                BookshelfIntSetting.LayoutListPortrait -> PreferKey.bookshelfLayoutListPortrait
-                BookshelfIntSetting.LayoutListLandscape -> PreferKey.bookshelfLayoutListLandscape
-                BookshelfIntSetting.FolderLayoutModePortrait -> PreferKey.bookshelfFolderLayoutModePortrait
-                BookshelfIntSetting.FolderLayoutGridPortrait -> PreferKey.bookshelfFolderLayoutGridPortrait
-                BookshelfIntSetting.FolderLayoutModeLandscape -> PreferKey.bookshelfFolderLayoutModeLandscape
-                BookshelfIntSetting.FolderLayoutGridLandscape -> PreferKey.bookshelfFolderLayoutGridLandscape
-                BookshelfIntSetting.FolderLayoutListPortrait -> PreferKey.bookshelfFolderLayoutListPortrait
-                BookshelfIntSetting.FolderLayoutListLandscape -> PreferKey.bookshelfFolderLayoutListLandscape
-                BookshelfIntSetting.GridLayout -> PreferKey.bookshelfGridLayout
-                BookshelfIntSetting.TitleMaxLines -> PreferKey.bookshelfTitleMaxLines
-                BookshelfIntSetting.CardColor -> PreferKey.bookshelfCardColor
-                BookshelfIntSetting.CardColorDark -> PreferKey.bookshelfCardColorDark
-                BookshelfIntSetting.GroupListStyle -> PreferKey.bookshelfGroupListStyle
-                BookshelfIntSetting.GroupCoverCount -> PreferKey.bookshelfGroupCoverCount
-                BookshelfIntSetting.ListCoverWidth -> PreferKey.bookshelfListCoverWidth
-                BookshelfIntSetting.GridCoverWidth -> PreferKey.bookshelfGridCoverWidth
-            } to update.value
-        }
-        AppConfigStore.putAll(mapOf(key to value))
+    override suspend fun update(transform: (BookshelfSettings) -> BookshelfSettings) {
+        AppConfigStore.atomicUpdate(
+            read = Preferences::toBookshelfSettings,
+            toPrefMap = BookshelfSettings::toPrefMap,
+            transform = transform,
+        )
     }
     }
 }
 }
 
 
-private fun Preferences.toBookshelfSettings() = BookshelfSettings(
+internal fun Preferences.toBookshelfSettings() = BookshelfSettings(
     bookGroupStyle = compatDsInt(PreferKey.bookGroupStyle) ?: 0,
     bookGroupStyle = compatDsInt(PreferKey.bookGroupStyle) ?: 0,
     hideEmptyGroups = compatDsBoolean(PreferKey.hideEmptyGroups) ?: true,
     hideEmptyGroups = compatDsBoolean(PreferKey.hideEmptyGroups) ?: true,
     bookshelfSort = compatDsInt(PreferKey.bookshelfSort) ?: 0,
     bookshelfSort = compatDsInt(PreferKey.bookshelfSort) ?: 0,
@@ -129,3 +78,52 @@ private fun Preferences.toBookshelfSettings() = BookshelfSettings(
     autoRefreshBook = compatDsBoolean(PreferKey.autoRefresh) ?: false,
     autoRefreshBook = compatDsBoolean(PreferKey.autoRefresh) ?: false,
     saveTabPosition = compatDsLong(PreferKey.saveTabPosition) ?: BookGroup.IdAll,
     saveTabPosition = compatDsLong(PreferKey.saveTabPosition) ?: BookGroup.IdAll,
 )
 )
+
+internal fun BookshelfSettings.toPrefMap(): Map<String, Any?> = mapOf(
+    PreferKey.bookGroupStyle to bookGroupStyle,
+    PreferKey.hideEmptyGroups to hideEmptyGroups,
+    PreferKey.bookshelfSort to bookshelfSort,
+    PreferKey.bookshelfSortOrder to bookshelfSortOrder,
+    PreferKey.showUnread to showUnread,
+    PreferKey.showUnreadNew to showUnreadNew,
+    PreferKey.showTip to showTip,
+    PreferKey.showBookCount to showBookCount,
+    PreferKey.showLastUpdateTime to showLastUpdateTime,
+    PreferKey.showBookIntro to showBookIntro,
+    PreferKey.bookshelfShowIntro to bookshelfShowIntro,
+    PreferKey.bookshelfShowTag to bookshelfShowTag,
+    PreferKey.bookshelfShowLatestChapter to bookshelfShowLatestChapter,
+    PreferKey.bookshelfIntroMaxLines to bookshelfIntroMaxLines,
+    PreferKey.showWaitUpCount to showWaitUpCount,
+    PreferKey.showBookshelfFastScroller to showBookshelfFastScroller,
+    PreferKey.shouldShowExpandButton to shouldShowExpandButton,
+    PreferKey.bookshelfRefreshingLimit to bookshelfRefreshingLimit,
+    PreferKey.bookshelfLayoutModePortrait to bookshelfLayoutModePortrait,
+    PreferKey.bookshelfLayoutGridPortrait to bookshelfLayoutGridPortrait,
+    PreferKey.bookshelfLayoutModeLandscape to bookshelfLayoutModeLandscape,
+    PreferKey.bookshelfLayoutGridLandscape to bookshelfLayoutGridLandscape,
+    PreferKey.bookshelfLayoutListPortrait to bookshelfLayoutListPortrait,
+    PreferKey.bookshelfLayoutListLandscape to bookshelfLayoutListLandscape,
+    PreferKey.bookshelfFolderLayoutModePortrait to bookshelfFolderLayoutModePortrait,
+    PreferKey.bookshelfFolderLayoutGridPortrait to bookshelfFolderLayoutGridPortrait,
+    PreferKey.bookshelfFolderLayoutModeLandscape to bookshelfFolderLayoutModeLandscape,
+    PreferKey.bookshelfFolderLayoutGridLandscape to bookshelfFolderLayoutGridLandscape,
+    PreferKey.bookshelfFolderLayoutListPortrait to bookshelfFolderLayoutListPortrait,
+    PreferKey.bookshelfFolderLayoutListLandscape to bookshelfFolderLayoutListLandscape,
+    PreferKey.bookshelfGridLayout to bookshelfGridLayout,
+    PreferKey.bookshelfLayoutCompact to bookshelfLayoutCompact,
+    PreferKey.bookshelfShowDivider to bookshelfShowDivider,
+    PreferKey.bookshelfTitleSmallFont to bookshelfTitleSmallFont,
+    PreferKey.bookshelfTitleCenter to bookshelfTitleCenter,
+    PreferKey.bookshelfTitleMaxLines to bookshelfTitleMaxLines,
+    PreferKey.bookshelfCoverShadow to bookshelfCoverShadow,
+    PreferKey.bookshelfCardColor to bookshelfCardColor,
+    PreferKey.bookshelfCardColorDark to bookshelfCardColorDark,
+    PreferKey.bookshelfGroupListStyle to bookshelfGroupListStyle,
+    PreferKey.bookshelfGroupCoverCount to bookshelfGroupCoverCount,
+    PreferKey.bookshelfListCoverWidth to bookshelfListCoverWidth,
+    PreferKey.bookshelfGridCoverWidth to bookshelfGridCoverWidth,
+    PreferKey.bookshelfSearchActionDirectToSearch to bookshelfSearchActionDirectToSearch,
+    PreferKey.autoRefresh to autoRefreshBook,
+    PreferKey.saveTabPosition to saveTabPosition,
+)

+ 1 - 58
app/src/main/java/io/legado/app/domain/gateway/BookshelfSettingsGateway.kt

@@ -6,62 +6,5 @@ import kotlinx.coroutines.flow.Flow
 interface BookshelfSettingsGateway {
 interface BookshelfSettingsGateway {
     val currentSettings: BookshelfSettings
     val currentSettings: BookshelfSettings
     val settings: Flow<BookshelfSettings>
     val settings: Flow<BookshelfSettings>
-    suspend fun update(update: BookshelfSettingsUpdate)
-}
-
-sealed interface BookshelfSettingsUpdate {
-    data class BooleanValue(val setting: BookshelfBooleanSetting, val value: Boolean) : BookshelfSettingsUpdate
-    data class IntValue(val setting: BookshelfIntSetting, val value: Int) : BookshelfSettingsUpdate
-    data class SaveTabPosition(val value: Long) : BookshelfSettingsUpdate
-}
-
-enum class BookshelfBooleanSetting {
-    ShowUnread,
-    ShowUnreadNew,
-    ShowTip,
-    ShowBookCount,
-    ShowLastUpdateTime,
-    ShowBookIntro,
-    ShowIntro,
-    ShowTag,
-    ShowLatestChapter,
-    ShowWaitUpCount,
-    ShowFastScroller,
-    ShowExpandButton,
-    LayoutCompact,
-    ShowDivider,
-    TitleSmallFont,
-    TitleCenter,
-    CoverShadow,
-    SearchActionDirectToSearch,
-    AutoRefresh,
-    HideEmptyGroups,
-}
-
-enum class BookshelfIntSetting {
-    BookGroupStyle,
-    Sort,
-    SortOrder,
-    IntroMaxLines,
-    RefreshingLimit,
-    LayoutModePortrait,
-    LayoutGridPortrait,
-    LayoutModeLandscape,
-    LayoutGridLandscape,
-    LayoutListPortrait,
-    LayoutListLandscape,
-    FolderLayoutModePortrait,
-    FolderLayoutGridPortrait,
-    FolderLayoutModeLandscape,
-    FolderLayoutGridLandscape,
-    FolderLayoutListPortrait,
-    FolderLayoutListLandscape,
-    GridLayout,
-    TitleMaxLines,
-    CardColor,
-    CardColorDark,
-    GroupListStyle,
-    GroupCoverCount,
-    ListCoverWidth,
-    GridCoverWidth,
+    suspend fun update(transform: (BookshelfSettings) -> BookshelfSettings)
 }
 }

+ 144 - 91
app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfConfigSheet.kt

@@ -31,12 +31,9 @@ import androidx.compose.ui.res.stringArrayResource
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.dp
 import io.legado.app.R
 import io.legado.app.R
-import io.legado.app.domain.gateway.BookshelfBooleanSetting
-import io.legado.app.domain.gateway.BookshelfIntSetting
-import io.legado.app.domain.gateway.BookshelfSettingsUpdate
-import io.legado.app.domain.model.settings.BookshelfSettings
 import io.legado.app.domain.gateway.ThemeBooleanSetting
 import io.legado.app.domain.gateway.ThemeBooleanSetting
 import io.legado.app.domain.gateway.ThemeSettingsUpdate
 import io.legado.app.domain.gateway.ThemeSettingsUpdate
+import io.legado.app.domain.model.settings.BookshelfSettings
 import io.legado.app.ui.config.themeConfig.LabelColorManageSheet
 import io.legado.app.ui.config.themeConfig.LabelColorManageSheet
 import io.legado.app.ui.config.themeConfig.TagColorPair
 import io.legado.app.ui.config.themeConfig.TagColorPair
 import io.legado.app.ui.theme.LegadoTheme
 import io.legado.app.ui.theme.LegadoTheme
@@ -54,7 +51,7 @@ import io.legado.app.ui.widget.components.settingItem.CompactSwitchSettingItem
 fun BookshelfConfigSheet(
 fun BookshelfConfigSheet(
     show: Boolean,
     show: Boolean,
     settings: BookshelfSettings,
     settings: BookshelfSettings,
-    onUpdate: (BookshelfSettingsUpdate) -> Unit,
+    onUpdate: ((BookshelfSettings) -> BookshelfSettings) -> Unit,
     enableCustomTagColors: Boolean,
     enableCustomTagColors: Boolean,
     customTagColors: List<TagColorPair>,
     customTagColors: List<TagColorPair>,
     themeColor: Int,
     themeColor: Int,
@@ -87,14 +84,18 @@ fun BookshelfConfigSheet(
                 selectedValue = settings.bookGroupStyle.toString(),
                 selectedValue = settings.bookGroupStyle.toString(),
                 displayEntries = stringArrayResource(R.array.group_style),
                 displayEntries = stringArrayResource(R.array.group_style),
                 entryValues = Array(stringArrayResource(R.array.group_style).size) { it.toString() },
                 entryValues = Array(stringArrayResource(R.array.group_style).size) { it.toString() },
-                onValueChange = { onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.BookGroupStyle, it.toInt())) }
+                onValueChange = { value ->
+                    onUpdate { it.copy(bookGroupStyle = value.toInt()) }
+                }
             )
             )
 
 
             CompactSwitchSettingItem(
             CompactSwitchSettingItem(
                 title = stringResource(R.string.hide_empty_groups),
                 title = stringResource(R.string.hide_empty_groups),
                 checked = settings.hideEmptyGroups,
                 checked = settings.hideEmptyGroups,
                 color = LegadoTheme.colorScheme.surface,
                 color = LegadoTheme.colorScheme.surface,
-                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.HideEmptyGroups, it)) }
+                onCheckedChange = { value ->
+                    onUpdate { it.copy(hideEmptyGroups = value) }
+                }
             )
             )
 
 
             PillHeaderDivider(title = stringResource(R.string.sort))
             PillHeaderDivider(title = stringResource(R.string.sort))
@@ -104,7 +105,9 @@ fun BookshelfConfigSheet(
                 selectedValue = settings.bookshelfSort.toString(),
                 selectedValue = settings.bookshelfSort.toString(),
                 displayEntries = stringArrayResource(R.array.bookshelf_px_array),
                 displayEntries = stringArrayResource(R.array.bookshelf_px_array),
                 entryValues = Array(stringArrayResource(R.array.bookshelf_px_array).size) { it.toString() },
                 entryValues = Array(stringArrayResource(R.array.bookshelf_px_array).size) { it.toString() },
-                onValueChange = { onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.Sort, it.toInt())) }
+                onValueChange = { value ->
+                    onUpdate { it.copy(bookshelfSort = value.toInt()) }
+                }
             )
             )
 
 
             // Sort Order
             // Sort Order
@@ -116,7 +119,9 @@ fun BookshelfConfigSheet(
                     stringResource(R.string.descending_order)
                     stringResource(R.string.descending_order)
                 ),
                 ),
                 entryValues = arrayOf("0", "1"),
                 entryValues = arrayOf("0", "1"),
-                onValueChange = { onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.SortOrder, it.toInt())) }
+                onValueChange = { value ->
+                    onUpdate { it.copy(bookshelfSortOrder = value.toInt()) }
+                }
             )
             )
 
 
             PillHeaderDivider(title = stringResource(R.string.bookshelf_section_layout))
             PillHeaderDivider(title = stringResource(R.string.bookshelf_section_layout))
@@ -139,14 +144,14 @@ fun BookshelfConfigSheet(
                         selectedValue = folderLayoutMode.toString(),
                         selectedValue = folderLayoutMode.toString(),
                         displayEntries = arrayOf(stringResource(R.string.layout_mode_list), stringResource(R.string.layout_mode_grid)),
                         displayEntries = arrayOf(stringResource(R.string.layout_mode_list), stringResource(R.string.layout_mode_grid)),
                         entryValues = arrayOf("0", "1"),
                         entryValues = arrayOf("0", "1"),
-                        onValueChange = {
-                            onUpdate(
-                                BookshelfSettingsUpdate.IntValue(
-                                    if (isLandscape) BookshelfIntSetting.FolderLayoutModeLandscape
-                                    else BookshelfIntSetting.FolderLayoutModePortrait,
-                                    it.toInt(),
-                                )
-                            )
+                        onValueChange = { value ->
+                            onUpdate {
+                                if (isLandscape) {
+                                    it.copy(bookshelfFolderLayoutModeLandscape = value.toInt())
+                                } else {
+                                    it.copy(bookshelfFolderLayoutModePortrait = value.toInt())
+                                }
+                            }
                         }
                         }
                     )
                     )
 
 
@@ -159,14 +164,14 @@ fun BookshelfConfigSheet(
                             value = folderGridCount.toFloat(),
                             value = folderGridCount.toFloat(),
                             valueRange = 1f..15f,
                             valueRange = 1f..15f,
                             steps = 14,
                             steps = 14,
-                            onValueChange = {
-                                onUpdate(
-                                    BookshelfSettingsUpdate.IntValue(
-                                        if (isLandscape) BookshelfIntSetting.FolderLayoutGridLandscape
-                                        else BookshelfIntSetting.FolderLayoutGridPortrait,
-                                        it.toInt(),
-                                    )
-                                )
+                            onValueChange = { value ->
+                                onUpdate {
+                                    if (isLandscape) {
+                                        it.copy(bookshelfFolderLayoutGridLandscape = value.toInt())
+                                    } else {
+                                        it.copy(bookshelfFolderLayoutGridPortrait = value.toInt())
+                                    }
+                                }
                             }
                             }
                         )
                         )
                     }
                     }
@@ -181,14 +186,14 @@ fun BookshelfConfigSheet(
                                 value = folderListCount.toFloat(),
                                 value = folderListCount.toFloat(),
                                 valueRange = 1f..5f,
                                 valueRange = 1f..5f,
                                 steps = 4,
                                 steps = 4,
-                                onValueChange = {
-                                    onUpdate(
-                                        BookshelfSettingsUpdate.IntValue(
-                                            if (isLandscape) BookshelfIntSetting.FolderLayoutListLandscape
-                                            else BookshelfIntSetting.FolderLayoutListPortrait,
-                                            it.toInt(),
-                                        )
-                                    )
+                                onValueChange = { value ->
+                                    onUpdate {
+                                        if (isLandscape) {
+                                            it.copy(bookshelfFolderLayoutListLandscape = value.toInt())
+                                        } else {
+                                            it.copy(bookshelfFolderLayoutListPortrait = value.toInt())
+                                        }
+                                    }
                                 }
                                 }
                             )
                             )
 
 
@@ -197,8 +202,8 @@ fun BookshelfConfigSheet(
                                 value = settings.bookshelfListCoverWidth.toFloat(),
                                 value = settings.bookshelfListCoverWidth.toFloat(),
                                 valueRange = 40f..120f,
                                 valueRange = 40f..120f,
                                 steps = 80,
                                 steps = 80,
-                                onValueChange = {
-                                    onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.ListCoverWidth, it.toInt()))
+                                onValueChange = { value ->
+                                    onUpdate { it.copy(bookshelfListCoverWidth = value.toInt()) }
                                 }
                                 }
                             )
                             )
                         }
                         }
@@ -215,8 +220,8 @@ fun BookshelfConfigSheet(
                                 selectedValue = settings.bookshelfGroupListStyle.toString(),
                                 selectedValue = settings.bookshelfGroupListStyle.toString(),
                                 displayEntries = arrayOf(stringResource(R.string.group), stringResource(R.string.compact_list), stringResource(R.string.horizontal_cover_count)),
                                 displayEntries = arrayOf(stringResource(R.string.group), stringResource(R.string.compact_list), stringResource(R.string.horizontal_cover_count)),
                                 entryValues = arrayOf("0", "1", "2"),
                                 entryValues = arrayOf("0", "1", "2"),
-                                onValueChange = {
-                                    onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.GroupListStyle, it.toInt()))
+                                onValueChange = { value ->
+                                    onUpdate { it.copy(bookshelfGroupListStyle = value.toInt()) }
                                 }
                                 }
                             )
                             )
                             AnimatedVisibility(visible = settings.bookshelfGroupListStyle == 2) {
                             AnimatedVisibility(visible = settings.bookshelfGroupListStyle == 2) {
@@ -225,8 +230,8 @@ fun BookshelfConfigSheet(
                                     value = settings.bookshelfGroupCoverCount.toFloat(),
                                     value = settings.bookshelfGroupCoverCount.toFloat(),
                                     valueRange = 1f..10f,
                                     valueRange = 1f..10f,
                                     steps = 9,
                                     steps = 9,
-                                    onValueChange = {
-                                        onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.GroupCoverCount, it.toInt()))
+                                    onValueChange = { value ->
+                                        onUpdate { it.copy(bookshelfGroupCoverCount = value.toInt()) }
                                     }
                                     }
                                 )
                                 )
                             }
                             }
@@ -246,14 +251,14 @@ fun BookshelfConfigSheet(
                     stringResource(R.string.layout_mode_grid)
                     stringResource(R.string.layout_mode_grid)
                 ),
                 ),
                 entryValues = arrayOf("0", "1"),
                 entryValues = arrayOf("0", "1"),
-                onValueChange = {
-                    onUpdate(
-                        BookshelfSettingsUpdate.IntValue(
-                            if (isLandscape) BookshelfIntSetting.LayoutModeLandscape
-                            else BookshelfIntSetting.LayoutModePortrait,
-                            it.toInt(),
-                        )
-                    )
+                onValueChange = { value ->
+                    onUpdate {
+                        if (isLandscape) {
+                            it.copy(bookshelfLayoutModeLandscape = value.toInt())
+                        } else {
+                            it.copy(bookshelfLayoutModePortrait = value.toInt())
+                        }
+                    }
                 }
                 }
             )
             )
 
 
@@ -268,7 +273,9 @@ fun BookshelfConfigSheet(
                         selectedValue = settings.bookshelfGridLayout.toString(),
                         selectedValue = settings.bookshelfGridLayout.toString(),
                         displayEntries = stringArrayResource(R.array.bookshelf_grid_layout),
                         displayEntries = stringArrayResource(R.array.bookshelf_grid_layout),
                         entryValues = Array(stringArrayResource(R.array.bookshelf_grid_layout).size) { it.toString() },
                         entryValues = Array(stringArrayResource(R.array.bookshelf_grid_layout).size) { it.toString() },
-                        onValueChange = { onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.GridLayout, it.toInt())) }
+                        onValueChange = { value ->
+                            onUpdate { it.copy(bookshelfGridLayout = value.toInt()) }
+                        }
                     )
                     )
 
 
                     val gridCount =
                     val gridCount =
@@ -278,14 +285,14 @@ fun BookshelfConfigSheet(
                         value = gridCount.toFloat(),
                         value = gridCount.toFloat(),
                         valueRange = 1f..15f,
                         valueRange = 1f..15f,
                         steps = 14,
                         steps = 14,
-                        onValueChange = {
-                            onUpdate(
-                                BookshelfSettingsUpdate.IntValue(
-                                    if (isLandscape) BookshelfIntSetting.LayoutGridLandscape
-                                    else BookshelfIntSetting.LayoutGridPortrait,
-                                    it.toInt(),
-                                )
-                            )
+                        onValueChange = { value ->
+                            onUpdate {
+                                if (isLandscape) {
+                                    it.copy(bookshelfLayoutGridLandscape = value.toInt())
+                                } else {
+                                    it.copy(bookshelfLayoutGridPortrait = value.toInt())
+                                }
+                            }
                         }
                         }
                     )
                     )
 
 
@@ -293,14 +300,18 @@ fun BookshelfConfigSheet(
                         title = stringResource(R.string.compact_title_font),
                         title = stringResource(R.string.compact_title_font),
                         checked = settings.bookshelfTitleSmallFont,
                         checked = settings.bookshelfTitleSmallFont,
                         color = LegadoTheme.colorScheme.surface,
                         color = LegadoTheme.colorScheme.surface,
-                        onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.TitleSmallFont, it)) }
+                        onCheckedChange = { value ->
+                            onUpdate { it.copy(bookshelfTitleSmallFont = value) }
+                        }
                     )
                     )
 
 
                     CompactSwitchSettingItem(
                     CompactSwitchSettingItem(
                         title = stringResource(R.string.center_aligned_title),
                         title = stringResource(R.string.center_aligned_title),
                         checked = settings.bookshelfTitleCenter,
                         checked = settings.bookshelfTitleCenter,
                         color = LegadoTheme.colorScheme.surface,
                         color = LegadoTheme.colorScheme.surface,
-                        onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.TitleCenter, it)) }
+                        onCheckedChange = { value ->
+                            onUpdate { it.copy(bookshelfTitleCenter = value) }
+                        }
                     )
                     )
 
 
                     CompactSliderSettingItem(
                     CompactSliderSettingItem(
@@ -308,7 +319,9 @@ fun BookshelfConfigSheet(
                         value = settings.bookshelfGridCoverWidth.toFloat(),
                         value = settings.bookshelfGridCoverWidth.toFloat(),
                         valueRange = 40f..150f,
                         valueRange = 40f..150f,
                         steps = 110,
                         steps = 110,
-                        onValueChange = { onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.GridCoverWidth, it.toInt())) }
+                        onValueChange = { value ->
+                            onUpdate { it.copy(bookshelfGridCoverWidth = value.toInt()) }
+                        }
                     )
                     )
                 }
                 }
             }
             }
@@ -323,7 +336,9 @@ fun BookshelfConfigSheet(
                         title = stringResource(R.string.show_divider_line),
                         title = stringResource(R.string.show_divider_line),
                         checked = settings.bookshelfShowDivider,
                         checked = settings.bookshelfShowDivider,
                         color = LegadoTheme.colorScheme.surface,
                         color = LegadoTheme.colorScheme.surface,
-                        onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowDivider, it)) }
+                        onCheckedChange = { value ->
+                            onUpdate { it.copy(bookshelfShowDivider = value) }
+                        }
                     )
                     )
 
 
                     CompactClickableSettingItem(
                     CompactClickableSettingItem(
@@ -372,7 +387,9 @@ fun BookshelfConfigSheet(
                         title = stringResource(R.string.compact_details),
                         title = stringResource(R.string.compact_details),
                         checked = settings.bookshelfLayoutCompact,
                         checked = settings.bookshelfLayoutCompact,
                         color = LegadoTheme.colorScheme.surface,
                         color = LegadoTheme.colorScheme.surface,
-                        onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.LayoutCompact, it)) }
+                        onCheckedChange = { value ->
+                            onUpdate { it.copy(bookshelfLayoutCompact = value) }
+                        }
                     )
                     )
 
 
                     val listColCount =
                     val listColCount =
@@ -382,7 +399,9 @@ fun BookshelfConfigSheet(
                         value = settings.bookshelfListCoverWidth.toFloat(),
                         value = settings.bookshelfListCoverWidth.toFloat(),
                         valueRange = 40f..120f,
                         valueRange = 40f..120f,
                         steps = 80,
                         steps = 80,
-                        onValueChange = { onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.ListCoverWidth, it.toInt())) }
+                        onValueChange = { value ->
+                            onUpdate { it.copy(bookshelfListCoverWidth = value.toInt()) }
+                        }
                     )
                     )
 
 
                     CompactSliderSettingItem(
                     CompactSliderSettingItem(
@@ -390,14 +409,14 @@ fun BookshelfConfigSheet(
                         value = listColCount.toFloat(),
                         value = listColCount.toFloat(),
                         valueRange = 1f..5f,
                         valueRange = 1f..5f,
                         steps = 4,
                         steps = 4,
-                        onValueChange = {
-                            onUpdate(
-                                BookshelfSettingsUpdate.IntValue(
-                                    if (isLandscape) BookshelfIntSetting.LayoutListLandscape
-                                    else BookshelfIntSetting.LayoutListPortrait,
-                                    it.toInt(),
-                                )
-                            )
+                        onValueChange = { value ->
+                            onUpdate {
+                                if (isLandscape) {
+                                    it.copy(bookshelfLayoutListLandscape = value.toInt())
+                                } else {
+                                    it.copy(bookshelfLayoutListPortrait = value.toInt())
+                                }
+                            }
                         }
                         }
                     )
                     )
 
 
@@ -405,7 +424,9 @@ fun BookshelfConfigSheet(
                         title = stringResource(R.string.show_more_info),
                         title = stringResource(R.string.show_more_info),
                         checked = settings.showBookIntro,
                         checked = settings.showBookIntro,
                         color = LegadoTheme.colorScheme.surface,
                         color = LegadoTheme.colorScheme.surface,
-                        onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowBookIntro, it)) }
+                        onCheckedChange = { value ->
+                            onUpdate { it.copy(showBookIntro = value) }
+                        }
                     )
                     )
 
 
                     AnimatedVisibility(visible = settings.showBookIntro) {
                     AnimatedVisibility(visible = settings.showBookIntro) {
@@ -416,8 +437,8 @@ fun BookshelfConfigSheet(
                                 title = stringResource(R.string.show_latest_chapter),
                                 title = stringResource(R.string.show_latest_chapter),
                                 checked = settings.bookshelfShowLatestChapter,
                                 checked = settings.bookshelfShowLatestChapter,
                                 color = LegadoTheme.colorScheme.surface,
                                 color = LegadoTheme.colorScheme.surface,
-                                onCheckedChange = {
-                                    onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowLatestChapter, it))
+                                onCheckedChange = { value ->
+                                    onUpdate { it.copy(bookshelfShowLatestChapter = value) }
                                 }
                                 }
                             )
                             )
 
 
@@ -425,7 +446,9 @@ fun BookshelfConfigSheet(
                                 title = stringResource(R.string.show_synopsis),
                                 title = stringResource(R.string.show_synopsis),
                                 checked = settings.bookshelfShowIntro,
                                 checked = settings.bookshelfShowIntro,
                                 color = LegadoTheme.colorScheme.surface,
                                 color = LegadoTheme.colorScheme.surface,
-                                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowIntro, it)) }
+                                onCheckedChange = { value ->
+                                    onUpdate { it.copy(bookshelfShowIntro = value) }
+                                }
                             )
                             )
                             AnimatedVisibility(
                             AnimatedVisibility(
                                 visible = settings.bookshelfShowIntro
                                 visible = settings.bookshelfShowIntro
@@ -436,8 +459,8 @@ fun BookshelfConfigSheet(
                                     value = settings.bookshelfIntroMaxLines.toFloat(),
                                     value = settings.bookshelfIntroMaxLines.toFloat(),
                                     valueRange = 0f..10f,
                                     valueRange = 0f..10f,
                                     steps = 10,
                                     steps = 10,
-                                    onValueChange = {
-                                        onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.IntroMaxLines, it.toInt()))
+                                    onValueChange = { value ->
+                                        onUpdate { it.copy(bookshelfIntroMaxLines = value.toInt()) }
                                     }
                                     }
                                 )
                                 )
                             }
                             }
@@ -445,7 +468,9 @@ fun BookshelfConfigSheet(
                                 title = stringResource(R.string.show_tags),
                                 title = stringResource(R.string.show_tags),
                                 checked = settings.bookshelfShowTag,
                                 checked = settings.bookshelfShowTag,
                                 color = LegadoTheme.colorScheme.surface,
                                 color = LegadoTheme.colorScheme.surface,
-                                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowTag, it)) }
+                                onCheckedChange = { value ->
+                                    onUpdate { it.copy(bookshelfShowTag = value) }
+                                }
                             )
                             )
                             AnimatedVisibility(
                             AnimatedVisibility(
                                 visible = settings.bookshelfShowTag
                                 visible = settings.bookshelfShowTag
@@ -487,14 +512,18 @@ fun BookshelfConfigSheet(
                 value = settings.bookshelfTitleMaxLines.toFloat(),
                 value = settings.bookshelfTitleMaxLines.toFloat(),
                 valueRange = 1f..5f,
                 valueRange = 1f..5f,
                 steps = 4,
                 steps = 4,
-                onValueChange = { onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.TitleMaxLines, it.toInt())) }
+                onValueChange = { value ->
+                    onUpdate { it.copy(bookshelfTitleMaxLines = value.toInt()) }
+                }
             )
             )
 
 
             CompactSwitchSettingItem(
             CompactSwitchSettingItem(
                 title = stringResource(R.string.cover_shadow),
                 title = stringResource(R.string.cover_shadow),
                 checked = settings.bookshelfCoverShadow,
                 checked = settings.bookshelfCoverShadow,
                 color = LegadoTheme.colorScheme.surface,
                 color = LegadoTheme.colorScheme.surface,
-                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.CoverShadow, it)) }
+                onCheckedChange = { value ->
+                    onUpdate { it.copy(bookshelfCoverShadow = value) }
+                }
             )
             )
 
 
             PillHeaderDivider(title = stringResource(R.string.bookshelf_section_badge))
             PillHeaderDivider(title = stringResource(R.string.bookshelf_section_badge))
@@ -503,42 +532,54 @@ fun BookshelfConfigSheet(
                 title = stringResource(R.string.show_unread),
                 title = stringResource(R.string.show_unread),
                 checked = settings.showUnread,
                 checked = settings.showUnread,
                 color = LegadoTheme.colorScheme.surface,
                 color = LegadoTheme.colorScheme.surface,
-                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowUnread, it)) }
+                onCheckedChange = { value ->
+                    onUpdate { it.copy(showUnread = value) }
+                }
             )
             )
 
 
             CompactSwitchSettingItem(
             CompactSwitchSettingItem(
                 title = stringResource(R.string.show_unread_new),
                 title = stringResource(R.string.show_unread_new),
                 checked = settings.showUnreadNew,
                 checked = settings.showUnreadNew,
                 color = LegadoTheme.colorScheme.surface,
                 color = LegadoTheme.colorScheme.surface,
-                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowUnreadNew, it)) }
+                onCheckedChange = { value ->
+                    onUpdate { it.copy(showUnreadNew = value) }
+                }
             )
             )
 
 
             CompactSwitchSettingItem(
             CompactSwitchSettingItem(
                 title = stringResource(R.string.show_wait_up_count),
                 title = stringResource(R.string.show_wait_up_count),
                 checked = settings.showWaitUpCount,
                 checked = settings.showWaitUpCount,
                 color = LegadoTheme.colorScheme.surface,
                 color = LegadoTheme.colorScheme.surface,
-                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowWaitUpCount, it)) }
+                onCheckedChange = { value ->
+                    onUpdate { it.copy(showWaitUpCount = value) }
+                }
             )
             )
 
 
             CompactSwitchSettingItem(
             CompactSwitchSettingItem(
                 title = stringResource(R.string.show_book_count),
                 title = stringResource(R.string.show_book_count),
                 checked = settings.showBookCount,
                 checked = settings.showBookCount,
                 color = LegadoTheme.colorScheme.surface,
                 color = LegadoTheme.colorScheme.surface,
-                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowBookCount, it)) }
+                onCheckedChange = { value ->
+                    onUpdate { it.copy(showBookCount = value) }
+                }
             )
             )
 
 
             CompactSwitchSettingItem(
             CompactSwitchSettingItem(
                 title = stringResource(R.string.show_last_update_time),
                 title = stringResource(R.string.show_last_update_time),
                 checked = settings.showLastUpdateTime,
                 checked = settings.showLastUpdateTime,
                 color = LegadoTheme.colorScheme.surface,
                 color = LegadoTheme.colorScheme.surface,
-                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowLastUpdateTime, it)) }
+                onCheckedChange = { value ->
+                    onUpdate { it.copy(showLastUpdateTime = value) }
+                }
             )
             )
 
 
             CompactSwitchSettingItem(
             CompactSwitchSettingItem(
                 title = stringResource(R.string.show_tip),
                 title = stringResource(R.string.show_tip),
                 checked = settings.showTip,
                 checked = settings.showTip,
                 color = LegadoTheme.colorScheme.surface,
                 color = LegadoTheme.colorScheme.surface,
-                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowTip, it)) }
+                onCheckedChange = { value ->
+                    onUpdate { it.copy(showTip = value) }
+                }
             )
             )
 
 
             PillHeaderDivider(title = stringResource(R.string.other))
             PillHeaderDivider(title = stringResource(R.string.other))
@@ -547,21 +588,27 @@ fun BookshelfConfigSheet(
                 title = stringResource(R.string.search_filter_first),
                 title = stringResource(R.string.search_filter_first),
                 checked = settings.bookshelfSearchActionDirectToSearch,
                 checked = settings.bookshelfSearchActionDirectToSearch,
                 color = LegadoTheme.colorScheme.surface,
                 color = LegadoTheme.colorScheme.surface,
-                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.SearchActionDirectToSearch, it)) }
+                onCheckedChange = { value ->
+                    onUpdate { it.copy(bookshelfSearchActionDirectToSearch = value) }
+                }
             )
             )
 
 
             CompactSwitchSettingItem(
             CompactSwitchSettingItem(
                 title = stringResource(R.string.show_bookshelf_fast_scroller),
                 title = stringResource(R.string.show_bookshelf_fast_scroller),
                 checked = settings.showBookshelfFastScroller,
                 checked = settings.showBookshelfFastScroller,
                 color = LegadoTheme.colorScheme.surface,
                 color = LegadoTheme.colorScheme.surface,
-                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowFastScroller, it)) }
+                onCheckedChange = { value ->
+                    onUpdate { it.copy(showBookshelfFastScroller = value) }
+                }
             )
             )
 
 
             CompactSwitchSettingItem(
             CompactSwitchSettingItem(
                 title = stringResource(R.string.show_bookshelf_tab_menu),
                 title = stringResource(R.string.show_bookshelf_tab_menu),
                 checked = settings.shouldShowExpandButton,
                 checked = settings.shouldShowExpandButton,
                 color = LegadoTheme.colorScheme.surface,
                 color = LegadoTheme.colorScheme.surface,
-                onCheckedChange = { onUpdate(BookshelfSettingsUpdate.BooleanValue(BookshelfBooleanSetting.ShowExpandButton, it)) }
+                onCheckedChange = { value ->
+                    onUpdate { it.copy(shouldShowExpandButton = value) }
+                }
             )
             )
 
 
             CompactSliderSettingItem(
             CompactSliderSettingItem(
@@ -570,7 +617,9 @@ fun BookshelfConfigSheet(
                 value = settings.bookshelfRefreshingLimit.toFloat(),
                 value = settings.bookshelfRefreshingLimit.toFloat(),
                 valueRange = 0f..100f,
                 valueRange = 0f..100f,
                 steps = 100,
                 steps = 100,
-                onValueChange = { onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.RefreshingLimit, it.toInt())) }
+                onValueChange = { value ->
+                    onUpdate { it.copy(bookshelfRefreshingLimit = value.toInt()) }
+                }
             )
             )
 
 
             Spacer(modifier = Modifier.height(32.dp))
             Spacer(modifier = Modifier.height(32.dp))
@@ -589,14 +638,18 @@ fun BookshelfConfigSheet(
             show = showColorPicker,
             show = showColorPicker,
             initialColor = if (settings.bookshelfCardColor != 0) settings.bookshelfCardColor else LegadoTheme.colorScheme.surfaceVariant.toArgb(),
             initialColor = if (settings.bookshelfCardColor != 0) settings.bookshelfCardColor else LegadoTheme.colorScheme.surfaceVariant.toArgb(),
             onDismissRequest = { showColorPicker = false },
             onDismissRequest = { showColorPicker = false },
-            onColorSelected = { onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.CardColor, it)) }
+            onColorSelected = { value ->
+                onUpdate { it.copy(bookshelfCardColor = value) }
+            }
         )
         )
 
 
         ColorPickerSheet(
         ColorPickerSheet(
             show = showColorPickerDark,
             show = showColorPickerDark,
             initialColor = if (settings.bookshelfCardColorDark != 0) settings.bookshelfCardColorDark else LegadoTheme.colorScheme.surfaceVariant.toArgb(),
             initialColor = if (settings.bookshelfCardColorDark != 0) settings.bookshelfCardColorDark else LegadoTheme.colorScheme.surfaceVariant.toArgb(),
             onDismissRequest = { showColorPickerDark = false },
             onDismissRequest = { showColorPickerDark = false },
-            onColorSelected = { onUpdate(BookshelfSettingsUpdate.IntValue(BookshelfIntSetting.CardColorDark, it)) }
+            onColorSelected = { value ->
+                onUpdate { it.copy(bookshelfCardColorDark = value) }
+            }
         )
         )
     }
     }
 }
 }

+ 4 - 3
app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfUiState.kt

@@ -3,9 +3,8 @@ package io.legado.app.ui.main.bookshelf
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.Stable
 import android.net.Uri
 import android.net.Uri
 import io.legado.app.data.entities.BookGroup
 import io.legado.app.data.entities.BookGroup
-import io.legado.app.domain.model.settings.BookshelfSettings
-import io.legado.app.domain.gateway.BookshelfSettingsUpdate
 import io.legado.app.domain.gateway.ThemeSettingsUpdate
 import io.legado.app.domain.gateway.ThemeSettingsUpdate
+import io.legado.app.domain.model.settings.BookshelfSettings
 import io.legado.app.ui.config.themeConfig.TagColorPair
 import io.legado.app.ui.config.themeConfig.TagColorPair
 import io.legado.app.ui.widget.components.list.ListUiState
 import io.legado.app.ui.widget.components.list.ListUiState
 import kotlinx.collections.immutable.ImmutableList
 import kotlinx.collections.immutable.ImmutableList
@@ -62,7 +61,9 @@ sealed interface BookshelfIntent {
     data class ExportToUri(val uri: Uri, val books: List<BookUiItem>) : BookshelfIntent
     data class ExportToUri(val uri: Uri, val books: List<BookUiItem>) : BookshelfIntent
     data class UploadBookshelf(val books: List<BookUiItem>) : BookshelfIntent
     data class UploadBookshelf(val books: List<BookUiItem>) : BookshelfIntent
     data class ImportFromUri(val uri: Uri, val groupId: Long) : BookshelfIntent
     data class ImportFromUri(val uri: Uri, val groupId: Long) : BookshelfIntent
-    data class UpdateSetting(val update: BookshelfSettingsUpdate) : BookshelfIntent
+    data class UpdateSetting(
+        val transform: (BookshelfSettings) -> BookshelfSettings,
+    ) : BookshelfIntent
     data class UpdateThemeSetting(val update: ThemeSettingsUpdate) : BookshelfIntent
     data class UpdateThemeSetting(val update: ThemeSettingsUpdate) : BookshelfIntent
     data class SetCustomTagColors(val colors: List<TagColorPair>) : BookshelfIntent
     data class SetCustomTagColors(val colors: List<TagColorPair>) : BookshelfIntent
     data object UploadResultConsumed : BookshelfIntent
     data object UploadResultConsumed : BookshelfIntent

+ 2 - 3
app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt

@@ -23,7 +23,6 @@ import io.legado.app.domain.usecase.ImportBookshelfUseCase
 import io.legado.app.domain.usecase.RefreshTocUseCase
 import io.legado.app.domain.usecase.RefreshTocUseCase
 import io.legado.app.domain.usecase.UpdateBooksGroupUseCase
 import io.legado.app.domain.usecase.UpdateBooksGroupUseCase
 import io.legado.app.domain.gateway.BookshelfSettingsGateway
 import io.legado.app.domain.gateway.BookshelfSettingsGateway
-import io.legado.app.domain.gateway.BookshelfSettingsUpdate
 import io.legado.app.domain.gateway.AppShellSettingsGateway
 import io.legado.app.domain.gateway.AppShellSettingsGateway
 import io.legado.app.domain.gateway.ThemeSettingsGateway
 import io.legado.app.domain.gateway.ThemeSettingsGateway
 import io.legado.app.exception.NoStackTraceException
 import io.legado.app.exception.NoStackTraceException
@@ -696,7 +695,7 @@ class BookshelfViewModel(
             is BookshelfIntent.UploadBookshelf -> uploadBookshelf(intent.books)
             is BookshelfIntent.UploadBookshelf -> uploadBookshelf(intent.books)
             is BookshelfIntent.ImportFromUri -> importBookshelf(intent.uri, intent.groupId)
             is BookshelfIntent.ImportFromUri -> importBookshelf(intent.uri, intent.groupId)
             is BookshelfIntent.UpdateSetting -> viewModelScope.launch {
             is BookshelfIntent.UpdateSetting -> viewModelScope.launch {
-                bookshelfSettingsGateway.update(intent.update)
+                bookshelfSettingsGateway.update(intent.transform)
             }
             }
             is BookshelfIntent.UpdateThemeSetting -> viewModelScope.launch {
             is BookshelfIntent.UpdateThemeSetting -> viewModelScope.launch {
                 themeSettingsGateway.update(intent.update)
                 themeSettingsGateway.update(intent.update)
@@ -757,7 +756,7 @@ class BookshelfViewModel(
         if (groupIdFlow.value != groupId) {
         if (groupIdFlow.value != groupId) {
             groupIdFlow.value = groupId
             groupIdFlow.value = groupId
             viewModelScope.launch {
             viewModelScope.launch {
-                bookshelfSettingsGateway.update(BookshelfSettingsUpdate.SaveTabPosition(groupId))
+                bookshelfSettingsGateway.update { it.copy(saveTabPosition = groupId) }
             }
             }
             clearSelection()
             clearSelection()
             clearDragState()
             clearDragState()

+ 156 - 0
app/src/test/java/io/legado/app/data/repository/BookshelfSettingsMappingTest.kt

@@ -0,0 +1,156 @@
+package io.legado.app.data.repository
+
+import io.legado.app.constant.PreferKey
+import io.legado.app.domain.model.settings.BookshelfSettings
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class BookshelfSettingsMappingTest {
+
+    @Test
+    fun `Bookshelf 46 键写读映射逐字段对应`() {
+        assertEquals(46, BookshelfSettings().toPrefMap().size)
+        bookshelfMappingSamples().forEach { expected ->
+            assertEquals(expected.expectedPrefMap(), expected.toPrefMap())
+            assertEquals(
+                expected,
+                expected.expectedPrefMap().toTestPreferences().toBookshelfSettings(),
+            )
+        }
+    }
+
+    @Test
+    fun `隐藏空分组通过真实原子路径只写对应键`() {
+        val values = captureAtomicUpdateValues(
+            current = BookshelfSettings(hideEmptyGroups = false),
+            read = { it.toBookshelfSettings() },
+            toPrefMap = BookshelfSettings::toPrefMap,
+            transform = { it.copy(hideEmptyGroups = true) },
+        )
+
+        assertEquals(mapOf(PreferKey.hideEmptyGroups to true), values)
+    }
+}
+
+private fun bookshelfMappingSamples(): List<BookshelfSettings> {
+    val base = BookshelfSettings(
+        bookGroupStyle = 101,
+        hideEmptyGroups = false,
+        bookshelfSort = 102,
+        bookshelfSortOrder = 103,
+        showUnread = false,
+        showUnreadNew = false,
+        showTip = false,
+        showBookCount = false,
+        showLastUpdateTime = false,
+        showBookIntro = false,
+        bookshelfShowIntro = false,
+        bookshelfShowTag = false,
+        bookshelfShowLatestChapter = false,
+        bookshelfIntroMaxLines = 104,
+        showWaitUpCount = false,
+        showBookshelfFastScroller = false,
+        shouldShowExpandButton = false,
+        bookshelfRefreshingLimit = 105,
+        bookshelfLayoutModePortrait = 106,
+        bookshelfLayoutGridPortrait = 107,
+        bookshelfLayoutModeLandscape = 108,
+        bookshelfLayoutGridLandscape = 109,
+        bookshelfLayoutListPortrait = 110,
+        bookshelfLayoutListLandscape = 111,
+        bookshelfFolderLayoutModePortrait = 112,
+        bookshelfFolderLayoutGridPortrait = 113,
+        bookshelfFolderLayoutModeLandscape = 114,
+        bookshelfFolderLayoutGridLandscape = 115,
+        bookshelfFolderLayoutListPortrait = 116,
+        bookshelfFolderLayoutListLandscape = 117,
+        bookshelfGridLayout = 118,
+        bookshelfLayoutCompact = false,
+        bookshelfShowDivider = false,
+        bookshelfTitleSmallFont = false,
+        bookshelfTitleCenter = false,
+        bookshelfTitleMaxLines = 119,
+        bookshelfCoverShadow = false,
+        bookshelfCardColor = 120,
+        bookshelfCardColorDark = 121,
+        bookshelfGroupListStyle = 122,
+        bookshelfGroupCoverCount = 123,
+        bookshelfListCoverWidth = 124,
+        bookshelfGridCoverWidth = 125,
+        bookshelfSearchActionDirectToSearch = false,
+        autoRefreshBook = false,
+        saveTabPosition = 987654321L,
+    )
+    return listOf(
+        base,
+        base.copy(hideEmptyGroups = true),
+        base.copy(showUnread = true),
+        base.copy(showUnreadNew = true),
+        base.copy(showTip = true),
+        base.copy(showBookCount = true),
+        base.copy(showLastUpdateTime = true),
+        base.copy(showBookIntro = true),
+        base.copy(bookshelfShowIntro = true),
+        base.copy(bookshelfShowTag = true),
+        base.copy(bookshelfShowLatestChapter = true),
+        base.copy(showWaitUpCount = true),
+        base.copy(showBookshelfFastScroller = true),
+        base.copy(shouldShowExpandButton = true),
+        base.copy(bookshelfLayoutCompact = true),
+        base.copy(bookshelfShowDivider = true),
+        base.copy(bookshelfTitleSmallFont = true),
+        base.copy(bookshelfTitleCenter = true),
+        base.copy(bookshelfCoverShadow = true),
+        base.copy(bookshelfSearchActionDirectToSearch = true),
+        base.copy(autoRefreshBook = true),
+    )
+}
+
+private fun BookshelfSettings.expectedPrefMap(): Map<String, Any?> = mapOf(
+    PreferKey.bookGroupStyle to bookGroupStyle,
+    PreferKey.hideEmptyGroups to hideEmptyGroups,
+    PreferKey.bookshelfSort to bookshelfSort,
+    PreferKey.bookshelfSortOrder to bookshelfSortOrder,
+    PreferKey.showUnread to showUnread,
+    PreferKey.showUnreadNew to showUnreadNew,
+    PreferKey.showTip to showTip,
+    PreferKey.showBookCount to showBookCount,
+    PreferKey.showLastUpdateTime to showLastUpdateTime,
+    PreferKey.showBookIntro to showBookIntro,
+    PreferKey.bookshelfShowIntro to bookshelfShowIntro,
+    PreferKey.bookshelfShowTag to bookshelfShowTag,
+    PreferKey.bookshelfShowLatestChapter to bookshelfShowLatestChapter,
+    PreferKey.bookshelfIntroMaxLines to bookshelfIntroMaxLines,
+    PreferKey.showWaitUpCount to showWaitUpCount,
+    PreferKey.showBookshelfFastScroller to showBookshelfFastScroller,
+    PreferKey.shouldShowExpandButton to shouldShowExpandButton,
+    PreferKey.bookshelfRefreshingLimit to bookshelfRefreshingLimit,
+    PreferKey.bookshelfLayoutModePortrait to bookshelfLayoutModePortrait,
+    PreferKey.bookshelfLayoutGridPortrait to bookshelfLayoutGridPortrait,
+    PreferKey.bookshelfLayoutModeLandscape to bookshelfLayoutModeLandscape,
+    PreferKey.bookshelfLayoutGridLandscape to bookshelfLayoutGridLandscape,
+    PreferKey.bookshelfLayoutListPortrait to bookshelfLayoutListPortrait,
+    PreferKey.bookshelfLayoutListLandscape to bookshelfLayoutListLandscape,
+    PreferKey.bookshelfFolderLayoutModePortrait to bookshelfFolderLayoutModePortrait,
+    PreferKey.bookshelfFolderLayoutGridPortrait to bookshelfFolderLayoutGridPortrait,
+    PreferKey.bookshelfFolderLayoutModeLandscape to bookshelfFolderLayoutModeLandscape,
+    PreferKey.bookshelfFolderLayoutGridLandscape to bookshelfFolderLayoutGridLandscape,
+    PreferKey.bookshelfFolderLayoutListPortrait to bookshelfFolderLayoutListPortrait,
+    PreferKey.bookshelfFolderLayoutListLandscape to bookshelfFolderLayoutListLandscape,
+    PreferKey.bookshelfGridLayout to bookshelfGridLayout,
+    PreferKey.bookshelfLayoutCompact to bookshelfLayoutCompact,
+    PreferKey.bookshelfShowDivider to bookshelfShowDivider,
+    PreferKey.bookshelfTitleSmallFont to bookshelfTitleSmallFont,
+    PreferKey.bookshelfTitleCenter to bookshelfTitleCenter,
+    PreferKey.bookshelfTitleMaxLines to bookshelfTitleMaxLines,
+    PreferKey.bookshelfCoverShadow to bookshelfCoverShadow,
+    PreferKey.bookshelfCardColor to bookshelfCardColor,
+    PreferKey.bookshelfCardColorDark to bookshelfCardColorDark,
+    PreferKey.bookshelfGroupListStyle to bookshelfGroupListStyle,
+    PreferKey.bookshelfGroupCoverCount to bookshelfGroupCoverCount,
+    PreferKey.bookshelfListCoverWidth to bookshelfListCoverWidth,
+    PreferKey.bookshelfGridCoverWidth to bookshelfGridCoverWidth,
+    PreferKey.bookshelfSearchActionDirectToSearch to bookshelfSearchActionDirectToSearch,
+    PreferKey.autoRefresh to autoRefreshBook,
+    PreferKey.saveTabPosition to saveTabPosition,
+)