书架排序支持#426
Conversation
There was a problem hiding this comment.
书架的排序包括
- 默认:按照添加顺序的逆序
- 字数
- 名称排序:首字母(A-Z),汉语字符使用
tinypinyin获取拼音后按照字母顺序排序
除了默认排序之外都支持反转顺序
There was a problem hiding this comment.
编辑书架页的改动主要包括使用LazyColumn列表,使用应用内置的设置项控件,移除书架页自定义的设置项控件
There was a problem hiding this comment.
单独提取 BookshelfHomeActions 因为传参过多
There was a problem hiding this comment.
对书架主页进行了拆分,因为原有文件过长
There was a problem hiding this comment.
重新排序reorder包括 排序书架 和 排序书架的书本
排序书架可以调整所有书架的顺序,排序书架书本是排序书架内书本的顺序。
There was a problem hiding this comment.
对探索主页的修改主要包括:
- 保存状态
- 更新了应用内统一
PrimaryTabRow样式
There was a problem hiding this comment.
Pull request overview
This PR adds bookshelf sorting/reordering capabilities (for both books and bookshelves) and improves state persistence on the Explore home page, addressing #309 and #393.
Changes:
- Add new bookshelf sort modes (default/latest/name/word count) with optional reverse, and new reorder screens for manual ordering.
- Persist and restore Explore home page UI state (titles + loaded content) to avoid unnecessary reloads.
- Introduce new dependencies/resources and a DB migration to support the new sorting fields and UI.
Reviewed changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| settings.gradle.kts | Adds an additional Maven repository for dependency resolution. |
| gradle/libs.versions.toml | Adds reorderable dependency version/catalog entry (and is used for new deps). |
| app/src/main/res/values/strings.xml | Adds strings for sort/reorder UI and exit confirmation prompts. |
| app/src/main/res/drawable/sort_24px.xml | Adds sort icon resource. |
| app/src/main/res/drawable/edit_square_24px.xml | Adds edit icon resource. |
| app/src/main/res/drawable/drag_indicator_24px.xml | Adds drag-handle icon resource. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/settings/data/MenuOptions.kt | Adds sort-type menu options mapping to BookshelfSortType. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/explore/home/ExploreHomeViewModel.kt | Updates Explore init/page-loading logic to better preserve state. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/explore/home/ExploreHomeScreen.kt | Uses saveable list state and adjusts tab indicator/top app bar colors. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/reorder/BookshelfReorderScreen.kt | New UI for reordering books and bookshelves via drag-and-drop. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/reorder/BookshelfReorderNavigation.kt | Adds navigation destinations for reorder screens. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/home/BookshelfUIComponents.kt | Minor formatting cleanup. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/home/BookshelfHomeViewModel.kt | Adds sort/reverse/reorder behaviors and persists bookshelf order. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/home/BookshelfHomeUiState.kt | Extends UI state to include reorder-mode flags and reorder lists. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/home/BookshelfHomeTopBar.kt | New top bar with sort controls and entrypoints to reorder flows. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/home/BookshelfHomeScreen.kt | Refactors screen into actions/data sources and delegates UI to new components. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/home/BookshelfHomeNavigation.kt | Refactors navigation wiring to use a shared parent ViewModel + new actions/routes. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/home/BookshelfHomeContent.kt | New content composable implementing sorting logic (incl. Pinyin key for CN titles). |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/home/BookShelfHomeActions.kt | Introduces action bundle used by the refactored bookshelf UI. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/edit/EditBookshelfViewModel.kt | Adds sortReversed support and sort-type change handler. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/edit/EditBookshelfScreen.kt | Updates edit UI to use shared settings components and adds sort-type selection. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/edit/BookshelfEditNavigation.kt | Wires sort-type change callback into edit screen. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/BookshelNavigation.kt | Registers reorder navigation graph under bookshelf navigation. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/MainActivity.kt | Initializes default bookshelf with sortReversed. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/local/room/LightNovelReaderDatabase.kt | Bumps DB version and adds migration for sort_reversed column. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/local/room/entity/BookshelfEntity.kt | Adds sortReversed field to Room entity mapping. |
| app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/bookshelf/BookshelfRepository.kt | Maps sortReversed through repository and updates create/update persistence. |
| app/build.gradle.kts | Adds new UI deps (reorderable + tinypinyin) and bumps versionCode. |
| api/src/main/kotlin/io/nightfish/lightnovelreader/api/userdata/UserDataPath.kt | Adds BookshelfOrder user-data path. |
| api/src/main/kotlin/io/nightfish/lightnovelreader/api/Route.kt | Adds routes for reorder screens. |
| api/src/main/kotlin/io/nightfish/lightnovelreader/api/bookshelf/BookshelfSortType.kt | Adds new sort types and makes map() resilient (fallback to Default). |
| api/src/main/kotlin/io/nightfish/lightnovelreader/api/bookshelf/BookshelfRepositoryApi.kt | Extends bookshelf creation API with sortReversed. |
| api/src/main/kotlin/io/nightfish/lightnovelreader/api/bookshelf/Bookshelf.kt | Adds sortReversed to bookshelf model interfaces. |
| api/src/main/kotlin/io/nightfish/lightnovelreader/api/ApiCompat.kt | Updates API compatibility grouping to include API v4. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| google() | ||
| mavenCentral() | ||
| maven { setUrl("https://maven.aliyun.com/repository/public") } | ||
| maven { setUrl("https://jitpack.io") } |
| [versions] | ||
| androidGradlePlugin = "9.0.1" | ||
| apksig = "9.1.0" | ||
| cxhttp = "1.2.5" | ||
| dom4j = "2.2.0" | ||
| jaxen = "2.0.0" | ||
| javet = "5.0.4" | ||
| kotlin = "2.3.10" | ||
| kotlinComposeCompilerPlugin = "2.1.20" | ||
| kotlinResult = "2.3.1" | ||
| ksp = "2.3.5" | ||
| loggingInterceptor = "5.3.2" | ||
| materialIconsCore = "1.7.8" | ||
| matomoSdkAndroid = "4.4" | ||
| okhttp = "5.3.2" | ||
| profileinstaller = "1.4.1" | ||
| re2j = "1.8" | ||
| reorderable = "3.1.0" | ||
| runtime = "1.10.6" | ||
| vico = "3.0.3" |
| // Reorderable | ||
| implementation(libs.reorderable) | ||
| // Source: https://mvnrepository.com/artifact/com.github.promeg/tinypinyin | ||
| implementation("com.github.promeg:tinypinyin:2.0.3")} |
| oldMutableBookshelf.updatedBookIds.forEach { bookId -> | ||
| viewModelScope.launch(Dispatchers.IO) { | ||
| bookRepository.getBookVolumesFlow(bookId).collect { | ||
| if (it.volumes.isNotEmpty()) { | ||
| viewModelScope.launch(Dispatchers.Main) { | ||
| _uiState.bookLastChapterTitleMap[bookId] = | ||
| "${it.volumes.last().volumeTitle} ${it.volumes.last().chapters.last().title}" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
| onClick = { | ||
| actions.changeSortType(BookshelfSortTypeOptions.getOptionWithValue(item.key).value) | ||
| } | ||
| ) | ||
| } | ||
| DropdownMenuItem( | ||
| enabled = uiState.selectedBookshelf.sortType != BookshelfSortType.Default, | ||
| text = { | ||
| Text( | ||
| text = stringResource(R.string.bookshelf_sort_reverse), | ||
| style = MaterialTheme.typography.bodyLarge | ||
| ) | ||
| }, | ||
| leadingIcon = { | ||
| Checkbox( | ||
| checked = uiState.selectedBookshelf.sortType != BookshelfSortType.Default && | ||
| uiState.selectedBookshelf.sortReversed, | ||
| enabled = uiState.selectedBookshelf.sortType != BookshelfSortType.Default, | ||
| onCheckedChange = null | ||
| ) | ||
| }, | ||
| onClick = { | ||
| if (uiState.selectedBookshelf.sortType == BookshelfSortType.Default) return@DropdownMenuItem | ||
| actions.changeSortReversed(!uiState.selectedBookshelf.sortReversed) | ||
| } | ||
| ) |
| DropdownMenuItem( | ||
| text = { | ||
| Text( | ||
| text = stringResource(R.string.share_bookshelf), | ||
| style = MaterialTheme.typography.bodyLarge | ||
| ) | ||
| }, | ||
| onClick = onShareBookshelf | ||
| ) |
| val stableIndexMap = allBookIds.withIndex().associate { it.value to it.index } | ||
| val locale = Locale.getDefault() | ||
| val collator = Collator.getInstance(locale) | ||
| val sortedIds = when (sortType) { | ||
| BookshelfSortType.Default -> allBookIds.filter(sourceIds::contains) |
| val allBookIds = remember(uiState.selectedBookshelf.allBookIds) { | ||
| uiState.selectedBookshelf.allBookIds.toList() | ||
| } | ||
| val bookInfoMap = linkedMapOf<String, BookInformation>() | ||
| allBookIds.forEach { id -> | ||
| val infoFlow = remember(id) { dataSources.getBookInfoFlow(id) } | ||
| val info by infoFlow.collectAsStateWithLifecycle() | ||
| bookInfoMap[id] = info | ||
| } | ||
| val bookMetadataMap = linkedMapOf<String, BookshelfBookMetadata?>() | ||
| allBookIds.forEach { id -> | ||
| val metadataFlow = remember(id) { dataSources.getBookMetadataFlow(id) } | ||
| val metadata by metadataFlow.collectAsStateWithLifecycle() | ||
| bookMetadataMap[id] = metadata | ||
| } |
| kotlin-result = { module = "com.michael-bull.kotlin-result:kotlin-result", version.ref = "kotlinResult" } | ||
| kotlin-result-coroutines = { module = "com.michael-bull.kotlin-result:kotlin-result-coroutines", version.ref = "kotlinResult" } | ||
| matomo-sdk-android = { module = "com.github.matomo-org:matomo-sdk-android", version.ref = "matomoSdkAndroid" } | ||
| okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } | ||
| okhttp3-logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "loggingInterceptor" } | ||
| re2j = { module = "com.google.re2j:re2j", version.ref = "re2j" } | ||
| reorderable = { module = "sh.calvin.reorderable:reorderable", version.ref = "reorderable" } | ||
| vico-compose-m3 = { group = "com.patrykandpatrick.vico", name = "compose-m3", version.ref = "vico" } | ||
| hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" } |
|
你倒是把构建错误修了啊。。。 |
| /** 当前正在阅读的书籍列表路径 @since Api 2 */ | ||
| data object ReadingBooks : UserDataPath("reading_books") | ||
| /** 书架排序路径 @since Api 4 */ | ||
| data object BookshelfOrder : UserDataPath("bookshelf_order") |
| private val groups: List<Set<Int>> = listOf( | ||
| setOf(1), | ||
| setOf(2, 3) | ||
| setOf(2, 3, 4) |
这个 PR 为书架新增(书架顺序/书本顺序)排序功能 (resolve #309 )
修复探索页面的状态保存 (resolve #393 )
提示:还包含API版本4的预改动