mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 14:27:57 +01:00 
			
		
		
		
	MangaScreen: Save selection state (#7560)
This commit is contained in:
		| @@ -38,8 +38,6 @@ import androidx.compose.runtime.derivedStateOf | ||||
| import androidx.compose.runtime.getValue | ||||
| import androidx.compose.runtime.mutableStateOf | ||||
| import androidx.compose.runtime.remember | ||||
| import androidx.compose.runtime.snapshots.SnapshotStateList | ||||
| import androidx.compose.runtime.toMutableStateList | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.hapticfeedback.HapticFeedbackType | ||||
| @@ -106,6 +104,11 @@ fun MangaScreen( | ||||
|     onMultiMarkAsReadClicked: (List<Chapter>, markAsRead: Boolean) -> Unit, | ||||
|     onMarkPreviousAsReadClicked: (Chapter) -> Unit, | ||||
|     onMultiDeleteClicked: (List<Chapter>) -> Unit, | ||||
|  | ||||
|     // Chapter selection | ||||
|     onChapterSelected: (ChapterItem, Boolean, Boolean, Boolean) -> Unit, | ||||
|     onAllChapterSelected: (Boolean) -> Unit, | ||||
|     onInvertSelection: () -> Unit, | ||||
| ) { | ||||
|     if (windowWidthSizeClass == WindowWidthSizeClass.Compact) { | ||||
|         MangaScreenSmallImpl( | ||||
| @@ -131,6 +134,9 @@ fun MangaScreen( | ||||
|             onMultiMarkAsReadClicked = onMultiMarkAsReadClicked, | ||||
|             onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked, | ||||
|             onMultiDeleteClicked = onMultiDeleteClicked, | ||||
|             onChapterSelected = onChapterSelected, | ||||
|             onAllChapterSelected = onAllChapterSelected, | ||||
|             onInvertSelection = onInvertSelection, | ||||
|         ) | ||||
|     } else { | ||||
|         MangaScreenLargeImpl( | ||||
| @@ -157,6 +163,9 @@ fun MangaScreen( | ||||
|             onMultiMarkAsReadClicked = onMultiMarkAsReadClicked, | ||||
|             onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked, | ||||
|             onMultiDeleteClicked = onMultiDeleteClicked, | ||||
|             onChapterSelected = onChapterSelected, | ||||
|             onAllChapterSelected = onAllChapterSelected, | ||||
|             onInvertSelection = onInvertSelection, | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| @@ -191,18 +200,21 @@ private fun MangaScreenSmallImpl( | ||||
|     onMultiMarkAsReadClicked: (List<Chapter>, markAsRead: Boolean) -> Unit, | ||||
|     onMarkPreviousAsReadClicked: (Chapter) -> Unit, | ||||
|     onMultiDeleteClicked: (List<Chapter>) -> Unit, | ||||
|  | ||||
|     // Chapter selection | ||||
|     onChapterSelected: (ChapterItem, Boolean, Boolean, Boolean) -> Unit, | ||||
|     onAllChapterSelected: (Boolean) -> Unit, | ||||
|     onInvertSelection: () -> Unit, | ||||
| ) { | ||||
|     val layoutDirection = LocalLayoutDirection.current | ||||
|     val chapterListState = rememberLazyListState() | ||||
|  | ||||
|     val insetPadding = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal).asPaddingValues() | ||||
|     val chapters = remember(state) { state.processedChapters.toList() } | ||||
|     val selected = remember(chapters) { emptyList<ChapterItem>().toMutableStateList() } | ||||
|     val selectedPositions = remember(chapters) { arrayOf(-1, -1) } // first and last selected index in list | ||||
|  | ||||
|     val internalOnBackPressed = { | ||||
|         if (selected.isNotEmpty()) { | ||||
|             selected.clear() | ||||
|         if (chapters.any { it.selected }) { | ||||
|             onAllChapterSelected(false) | ||||
|         } else { | ||||
|             onBackClicked() | ||||
|         } | ||||
| @@ -236,21 +248,14 @@ private fun MangaScreenSmallImpl( | ||||
|                 onDownloadClicked = onDownloadActionClicked, | ||||
|                 onEditCategoryClicked = onEditCategoryClicked, | ||||
|                 onMigrateClicked = onMigrateClicked, | ||||
|                 actionModeCounter = selected.size, | ||||
|                 onSelectAll = { | ||||
|                     selected.clear() | ||||
|                     selected.addAll(chapters) | ||||
|                 }, | ||||
|                 onInvertSelection = { | ||||
|                     val toSelect = chapters - selected | ||||
|                     selected.clear() | ||||
|                     selected.addAll(toSelect) | ||||
|                 }, | ||||
|                 actionModeCounter = chapters.count { it.selected }, | ||||
|                 onSelectAll = { onAllChapterSelected(true) }, | ||||
|                 onInvertSelection = { onInvertSelection() }, | ||||
|             ) | ||||
|         }, | ||||
|         bottomBar = { | ||||
|             SharedMangaBottomActionMenu( | ||||
|                 selected = selected, | ||||
|                 selected = chapters.filter { it.selected }, | ||||
|                 onMultiBookmarkClicked = onMultiBookmarkClicked, | ||||
|                 onMultiMarkAsReadClicked = onMultiMarkAsReadClicked, | ||||
|                 onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked, | ||||
| @@ -262,7 +267,7 @@ private fun MangaScreenSmallImpl( | ||||
|         snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, | ||||
|         floatingActionButton = { | ||||
|             AnimatedVisibility( | ||||
|                 visible = chapters.any { !it.chapter.read } && selected.isEmpty(), | ||||
|                 visible = chapters.any { !it.chapter.read } && chapters.none { it.selected }, | ||||
|                 enter = fadeIn(), | ||||
|                 exit = fadeOut(), | ||||
|             ) { | ||||
| @@ -370,10 +375,9 @@ private fun MangaScreenSmallImpl( | ||||
|  | ||||
|                     sharedChapterItems( | ||||
|                         chapters = chapters, | ||||
|                         selected = selected, | ||||
|                         selectedPositions = selectedPositions, | ||||
|                         onChapterClicked = onChapterClicked, | ||||
|                         onDownloadChapter = onDownloadChapter, | ||||
|                         onChapterSelected = onChapterSelected, | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
| @@ -412,6 +416,11 @@ fun MangaScreenLargeImpl( | ||||
|     onMultiMarkAsReadClicked: (List<Chapter>, markAsRead: Boolean) -> Unit, | ||||
|     onMarkPreviousAsReadClicked: (Chapter) -> Unit, | ||||
|     onMultiDeleteClicked: (List<Chapter>) -> Unit, | ||||
|  | ||||
|     // Chapter selection | ||||
|     onChapterSelected: (ChapterItem, Boolean, Boolean, Boolean) -> Unit, | ||||
|     onAllChapterSelected: (Boolean) -> Unit, | ||||
|     onInvertSelection: () -> Unit, | ||||
| ) { | ||||
|     val layoutDirection = LocalLayoutDirection.current | ||||
|     val density = LocalDensity.current | ||||
| @@ -436,12 +445,10 @@ fun MangaScreenLargeImpl( | ||||
|     ) { | ||||
|         val chapterListState = rememberLazyListState() | ||||
|         val chapters = remember(state) { state.processedChapters.toList() } | ||||
|         val selected = remember(chapters) { emptyList<ChapterItem>().toMutableStateList() } | ||||
|         val selectedPositions = remember(chapters) { arrayOf(-1, -1) } // first and last selected index in list | ||||
|  | ||||
|         val internalOnBackPressed = { | ||||
|             if (selected.isNotEmpty()) { | ||||
|                 selected.clear() | ||||
|             if (chapters.any { it.selected }) { | ||||
|                 onAllChapterSelected(false) | ||||
|             } else { | ||||
|                 onBackClicked() | ||||
|             } | ||||
| @@ -454,7 +461,7 @@ fun MangaScreenLargeImpl( | ||||
|                 MangaSmallAppBar( | ||||
|                     modifier = Modifier.onSizeChanged { onTopBarHeightChanged(it.height) }, | ||||
|                     title = state.manga.title, | ||||
|                     titleAlphaProvider = { if (selected.isEmpty()) 0f else 1f }, | ||||
|                     titleAlphaProvider = { if (chapters.any { it.selected }) 1f else 0f }, | ||||
|                     backgroundAlphaProvider = { 1f }, | ||||
|                     incognitoMode = state.isIncognitoMode, | ||||
|                     downloadedOnlyMode = state.isDownloadedOnlyMode, | ||||
| @@ -463,16 +470,9 @@ fun MangaScreenLargeImpl( | ||||
|                     onDownloadClicked = onDownloadActionClicked, | ||||
|                     onEditCategoryClicked = onEditCategoryClicked, | ||||
|                     onMigrateClicked = onMigrateClicked, | ||||
|                     actionModeCounter = selected.size, | ||||
|                     onSelectAll = { | ||||
|                         selected.clear() | ||||
|                         selected.addAll(chapters) | ||||
|                     }, | ||||
|                     onInvertSelection = { | ||||
|                         val toSelect = chapters - selected | ||||
|                         selected.clear() | ||||
|                         selected.addAll(toSelect) | ||||
|                     }, | ||||
|                     actionModeCounter = chapters.count { it.selected }, | ||||
|                     onSelectAll = { onAllChapterSelected(true) }, | ||||
|                     onInvertSelection = { onInvertSelection() }, | ||||
|                 ) | ||||
|             }, | ||||
|             bottomBar = { | ||||
| @@ -481,7 +481,7 @@ fun MangaScreenLargeImpl( | ||||
|                     contentAlignment = Alignment.BottomEnd, | ||||
|                 ) { | ||||
|                     SharedMangaBottomActionMenu( | ||||
|                         selected = selected, | ||||
|                         selected = chapters.filter { it.selected }, | ||||
|                         onMultiBookmarkClicked = onMultiBookmarkClicked, | ||||
|                         onMultiMarkAsReadClicked = onMultiMarkAsReadClicked, | ||||
|                         onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked, | ||||
| @@ -494,7 +494,7 @@ fun MangaScreenLargeImpl( | ||||
|             snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, | ||||
|             floatingActionButton = { | ||||
|                 AnimatedVisibility( | ||||
|                     visible = chapters.any { !it.chapter.read } && selected.isEmpty(), | ||||
|                     visible = chapters.any { !it.chapter.read } && chapters.none { it.selected }, | ||||
|                     enter = fadeIn(), | ||||
|                     exit = fadeOut(), | ||||
|                 ) { | ||||
| @@ -578,10 +578,9 @@ fun MangaScreenLargeImpl( | ||||
|  | ||||
|                         sharedChapterItems( | ||||
|                             chapters = chapters, | ||||
|                             selected = selected, | ||||
|                             selectedPositions = selectedPositions, | ||||
|                             onChapterClicked = onChapterClicked, | ||||
|                             onDownloadChapter = onDownloadChapter, | ||||
|                             onChapterSelected = onChapterSelected, | ||||
|                         ) | ||||
|                     } | ||||
|                 } | ||||
| @@ -592,7 +591,7 @@ fun MangaScreenLargeImpl( | ||||
|  | ||||
| @Composable | ||||
| private fun SharedMangaBottomActionMenu( | ||||
|     selected: SnapshotStateList<ChapterItem>, | ||||
|     selected: List<ChapterItem>, | ||||
|     onMultiBookmarkClicked: (List<Chapter>, bookmarked: Boolean) -> Unit, | ||||
|     onMultiMarkAsReadClicked: (List<Chapter>, markAsRead: Boolean) -> Unit, | ||||
|     onMarkPreviousAsReadClicked: (Chapter) -> Unit, | ||||
| @@ -605,33 +604,26 @@ private fun SharedMangaBottomActionMenu( | ||||
|         modifier = Modifier.fillMaxWidth(fillFraction), | ||||
|         onBookmarkClicked = { | ||||
|             onMultiBookmarkClicked.invoke(selected.map { it.chapter }, true) | ||||
|             selected.clear() | ||||
|         }.takeIf { selected.any { !it.chapter.bookmark } }, | ||||
|         onRemoveBookmarkClicked = { | ||||
|             onMultiBookmarkClicked.invoke(selected.map { it.chapter }, false) | ||||
|             selected.clear() | ||||
|         }.takeIf { selected.all { it.chapter.bookmark } }, | ||||
|         onMarkAsReadClicked = { | ||||
|             onMultiMarkAsReadClicked(selected.map { it.chapter }, true) | ||||
|             selected.clear() | ||||
|         }.takeIf { selected.any { !it.chapter.read } }, | ||||
|         onMarkAsUnreadClicked = { | ||||
|             onMultiMarkAsReadClicked(selected.map { it.chapter }, false) | ||||
|             selected.clear() | ||||
|         }.takeIf { selected.any { it.chapter.read } }, | ||||
|         onMarkPreviousAsReadClicked = { | ||||
|             onMarkPreviousAsReadClicked(selected[0].chapter) | ||||
|             selected.clear() | ||||
|         }.takeIf { selected.size == 1 }, | ||||
|         onDownloadClicked = { | ||||
|             onDownloadChapter!!(selected.toList(), ChapterDownloadAction.START) | ||||
|             selected.clear() | ||||
|         }.takeIf { | ||||
|             onDownloadChapter != null && selected.any { it.downloadState != Download.State.DOWNLOADED } | ||||
|         }, | ||||
|         onDeleteClicked = { | ||||
|             onMultiDeleteClicked(selected.map { it.chapter }) | ||||
|             selected.clear() | ||||
|         }.takeIf { | ||||
|             onDownloadChapter != null && selected.any { it.downloadState == Download.State.DOWNLOADED } | ||||
|         }, | ||||
| @@ -640,10 +632,9 @@ private fun SharedMangaBottomActionMenu( | ||||
|  | ||||
| private fun LazyListScope.sharedChapterItems( | ||||
|     chapters: List<ChapterItem>, | ||||
|     selected: SnapshotStateList<ChapterItem>, | ||||
|     selectedPositions: Array<Int>, | ||||
|     onChapterClicked: (Chapter) -> Unit, | ||||
|     onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?, | ||||
|     onChapterSelected: (ChapterItem, Boolean, Boolean, Boolean) -> Unit, | ||||
| ) { | ||||
|     items( | ||||
|         items = chapters, | ||||
| @@ -658,24 +649,18 @@ private fun LazyListScope.sharedChapterItems( | ||||
|             scanlator = chapterItem.chapter.scanlator.takeIf { !it.isNullOrBlank() }, | ||||
|             read = chapterItem.chapter.read, | ||||
|             bookmark = chapterItem.chapter.bookmark, | ||||
|             selected = selected.contains(chapterItem), | ||||
|             selected = chapterItem.selected, | ||||
|             downloadStateProvider = { chapterItem.downloadState }, | ||||
|             downloadProgressProvider = { chapterItem.downloadProgress }, | ||||
|             onLongClick = { | ||||
|                 val dispatched = onChapterItemLongClick( | ||||
|                     chapterItem = chapterItem, | ||||
|                     selected = selected, | ||||
|                     chapters = chapters, | ||||
|                     selectedPositions = selectedPositions, | ||||
|                 ) | ||||
|                 if (dispatched) haptic.performHapticFeedback(HapticFeedbackType.LongPress) | ||||
|                 onChapterSelected(chapterItem, !chapterItem.selected, true, true) | ||||
|                 haptic.performHapticFeedback(HapticFeedbackType.LongPress) | ||||
|             }, | ||||
|             onClick = { | ||||
|                 onChapterItemClick( | ||||
|                     chapterItem = chapterItem, | ||||
|                     selected = selected, | ||||
|                     chapters = chapters, | ||||
|                     selectedPositions = selectedPositions, | ||||
|                     onToggleSelection = { onChapterSelected(chapterItem, !chapterItem.selected, true, false) }, | ||||
|                     onChapterClicked = onChapterClicked, | ||||
|                 ) | ||||
|             }, | ||||
| @@ -686,72 +671,15 @@ private fun LazyListScope.sharedChapterItems( | ||||
|     } | ||||
| } | ||||
|  | ||||
| private fun onChapterItemLongClick( | ||||
|     chapterItem: ChapterItem, | ||||
|     selected: MutableList<ChapterItem>, | ||||
|     chapters: List<ChapterItem>, | ||||
|     selectedPositions: Array<Int>, | ||||
| ): Boolean { | ||||
|     if (!selected.contains(chapterItem)) { | ||||
|         val selectedIndex = chapters.indexOf(chapterItem) | ||||
|         if (selected.isEmpty()) { | ||||
|             selected.add(chapterItem) | ||||
|             selectedPositions[0] = selectedIndex | ||||
|             selectedPositions[1] = selectedIndex | ||||
|             return true | ||||
|         } | ||||
|  | ||||
|         // Try to select the items in-between when possible | ||||
|         val range: IntRange | ||||
|         if (selectedIndex < selectedPositions[0]) { | ||||
|             range = selectedIndex until selectedPositions[0] | ||||
|             selectedPositions[0] = selectedIndex | ||||
|         } else if (selectedIndex > selectedPositions[1]) { | ||||
|             range = (selectedPositions[1] + 1)..selectedIndex | ||||
|             selectedPositions[1] = selectedIndex | ||||
|         } else { | ||||
|             // Just select itself | ||||
|             range = selectedIndex..selectedIndex | ||||
|         } | ||||
|  | ||||
|         range.forEach { | ||||
|             val toAdd = chapters[it] | ||||
|             if (!selected.contains(toAdd)) { | ||||
|                 selected.add(toAdd) | ||||
|             } | ||||
|         } | ||||
|         return true | ||||
|     } | ||||
|     return false | ||||
| } | ||||
|  | ||||
| private fun onChapterItemClick( | ||||
|     chapterItem: ChapterItem, | ||||
|     selected: MutableList<ChapterItem>, | ||||
|     chapters: List<ChapterItem>, | ||||
|     selectedPositions: Array<Int>, | ||||
|     onToggleSelection: (Boolean) -> Unit, | ||||
|     onChapterClicked: (Chapter) -> Unit, | ||||
| ) { | ||||
|     val selectedIndex = chapters.indexOf(chapterItem) | ||||
|     when { | ||||
|         selected.contains(chapterItem) -> { | ||||
|             val removedIndex = chapters.indexOf(chapterItem) | ||||
|             selected.remove(chapterItem) | ||||
|  | ||||
|             if (removedIndex == selectedPositions[0]) { | ||||
|                 selectedPositions[0] = chapters.indexOfFirst { selected.contains(it) } | ||||
|             } else if (removedIndex == selectedPositions[1]) { | ||||
|                 selectedPositions[1] = chapters.indexOfLast { selected.contains(it) } | ||||
|             } | ||||
|         } | ||||
|         selected.isNotEmpty() -> { | ||||
|             if (selectedIndex < selectedPositions[0]) { | ||||
|                 selectedPositions[0] = selectedIndex | ||||
|             } else if (selectedIndex > selectedPositions[1]) { | ||||
|                 selectedPositions[1] = selectedIndex | ||||
|             } | ||||
|             selected.add(chapterItem) | ||||
|         } | ||||
|         chapterItem.selected -> onToggleSelection(false) | ||||
|         chapters.any { it.selected } -> onToggleSelection(true) | ||||
|         else -> onChapterClicked(chapterItem.chapter) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -142,6 +142,9 @@ class MangaController : | ||||
|                 onMultiMarkAsReadClicked = presenter::markChaptersRead, | ||||
|                 onMarkPreviousAsReadClicked = presenter::markPreviousChapterRead, | ||||
|                 onMultiDeleteClicked = this::deleteChaptersWithConfirmation, | ||||
|                 onChapterSelected = presenter::toggleSelection, | ||||
|                 onAllChapterSelected = presenter::toggleAllSelection, | ||||
|                 onInvertSelection = presenter::invertSelection, | ||||
|             ) | ||||
|         } else { | ||||
|             Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { | ||||
|   | ||||
| @@ -140,6 +140,8 @@ class MangaPresenter( | ||||
|     val processedChapters: Sequence<ChapterItem>? | ||||
|         get() = successState?.processedChapters | ||||
|  | ||||
|     private val selectedPositions: Array<Int> = arrayOf(-1, -1) // first and last selected index in list | ||||
|  | ||||
|     /** | ||||
|      * Helper function to update the UI state only if it's currently in success state | ||||
|      */ | ||||
| @@ -583,6 +585,7 @@ class MangaPresenter( | ||||
|                 values = chapters.toTypedArray(), | ||||
|             ) | ||||
|         } | ||||
|         toggleAllSelection(false) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -592,6 +595,7 @@ class MangaPresenter( | ||||
|     fun downloadChapters(chapters: List<DomainChapter>) { | ||||
|         val manga = successState?.manga ?: return | ||||
|         downloadManager.downloadChapters(manga, chapters.map { it.toDbChapter() }) | ||||
|         toggleAllSelection(false) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -605,6 +609,7 @@ class MangaPresenter( | ||||
|                 .map { ChapterUpdate(id = it.id, bookmark = bookmarked) } | ||||
|                 .let { updateChapter.awaitAll(it) } | ||||
|         } | ||||
|         toggleAllSelection(false) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -627,12 +632,16 @@ class MangaPresenter( | ||||
|                         deletedChapters.forEach { | ||||
|                             val index = indexOf(it) | ||||
|                             val toAdd = removeAt(index) | ||||
|                                 .copy(downloadState = Download.State.NOT_DOWNLOADED, downloadProgress = 0) | ||||
|                                 .copy( | ||||
|                                     downloadState = Download.State.NOT_DOWNLOADED, | ||||
|                                     downloadProgress = 0, | ||||
|                                 ) | ||||
|                             add(index, toAdd) | ||||
|                         } | ||||
|                     } | ||||
|                     successState.copy(chapters = newChapters) | ||||
|                 } | ||||
|                 toggleAllSelection(false) | ||||
|             } catch (e: Throwable) { | ||||
|                 logcat(LogPriority.ERROR, e) | ||||
|             } | ||||
| @@ -725,6 +734,89 @@ class MangaPresenter( | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun toggleSelection( | ||||
|         item: ChapterItem, | ||||
|         selected: Boolean, | ||||
|         userSelected: Boolean = false, | ||||
|         fromLongPress: Boolean = false, | ||||
|     ) { | ||||
|         updateSuccessState { successState -> | ||||
|             val modifiedIndex = successState.chapters.indexOfFirst { it.chapter.id == item.chapter.id } | ||||
|             if (modifiedIndex < 0) return@updateSuccessState successState | ||||
|  | ||||
|             val oldItem = successState.chapters[modifiedIndex] | ||||
|             if ((oldItem.selected && selected) || (!oldItem.selected && !selected)) return@updateSuccessState successState | ||||
|  | ||||
|             val newChapters = successState.chapters.toMutableList().apply { | ||||
|                 val firstSelection = none { it.selected } | ||||
|                 var newItem = removeAt(modifiedIndex) | ||||
|                 add(modifiedIndex, newItem.copy(selected = selected)) | ||||
|  | ||||
|                 if (selected && userSelected && fromLongPress) { | ||||
|                     if (firstSelection) { | ||||
|                         selectedPositions[0] = modifiedIndex | ||||
|                         selectedPositions[1] = modifiedIndex | ||||
|                     } else { | ||||
|                         // Try to select the items in-between when possible | ||||
|                         val range: IntRange | ||||
|                         if (modifiedIndex < selectedPositions[0]) { | ||||
|                             range = modifiedIndex + 1 until selectedPositions[0] | ||||
|                             selectedPositions[0] = modifiedIndex | ||||
|                         } else if (modifiedIndex > selectedPositions[1]) { | ||||
|                             range = (selectedPositions[1] + 1) until modifiedIndex | ||||
|                             selectedPositions[1] = modifiedIndex | ||||
|                         } else { | ||||
|                             // Just select itself | ||||
|                             range = IntRange.EMPTY | ||||
|                         } | ||||
|  | ||||
|                         range.forEach { | ||||
|                             newItem = removeAt(it) | ||||
|                             add(it, newItem.copy(selected = true)) | ||||
|                         } | ||||
|                     } | ||||
|                 } else if (userSelected && !fromLongPress) { | ||||
|                     if (!selected) { | ||||
|                         if (modifiedIndex == selectedPositions[0]) { | ||||
|                             selectedPositions[0] = indexOfFirst { it.selected } | ||||
|                         } else if (modifiedIndex == selectedPositions[1]) { | ||||
|                             selectedPositions[1] = indexOfLast { it.selected } | ||||
|                         } | ||||
|                     } else { | ||||
|                         if (modifiedIndex < selectedPositions[0]) { | ||||
|                             selectedPositions[0] = modifiedIndex | ||||
|                         } else if (modifiedIndex > selectedPositions[1]) { | ||||
|                             selectedPositions[1] = modifiedIndex | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             successState.copy(chapters = newChapters) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun toggleAllSelection(selected: Boolean) { | ||||
|         updateSuccessState { successState -> | ||||
|             val newChapters = successState.chapters.map { | ||||
|                 it.copy(selected = selected) | ||||
|             } | ||||
|             selectedPositions[0] = -1 | ||||
|             selectedPositions[1] = -1 | ||||
|             successState.copy(chapters = newChapters) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun invertSelection() { | ||||
|         updateSuccessState { successState -> | ||||
|             val newChapters = successState.chapters.map { | ||||
|                 it.copy(selected = !it.selected) | ||||
|             } | ||||
|             selectedPositions[0] = -1 | ||||
|             selectedPositions[1] = -1 | ||||
|             successState.copy(chapters = newChapters) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Chapters list - end | ||||
|  | ||||
|     // Track sheet - start | ||||
| @@ -962,6 +1054,8 @@ data class ChapterItem( | ||||
|     val chapterTitleString: String, | ||||
|     val dateUploadString: String?, | ||||
|     val readProgressString: String?, | ||||
|  | ||||
|     val selected: Boolean = false, | ||||
| ) { | ||||
|     val isDownloaded = downloadState == Download.State.DOWNLOADED | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user