From cbd3d439cd61114d61cddcdb0210e308c03fd15f Mon Sep 17 00:00:00 2001 From: Koitharu Date: Tue, 19 Apr 2022 13:09:44 +0300 Subject: [PATCH] Support multiple branches in saved manga --- .../kotatsu/details/ui/DetailsActivity.kt | 51 ++++++++++++------- .../kotatsu/details/ui/DetailsViewModel.kt | 24 +++++---- .../koitharu/kotatsu/local/data/MangaIndex.kt | 2 +- .../kotatsu/local/domain/CbzMangaOutput.kt | 6 +-- 4 files changed, 52 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt index 18e0e325b..b29596141 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt @@ -41,6 +41,7 @@ import org.koitharu.kotatsu.details.ui.adapter.BranchesAdapter import org.koitharu.kotatsu.download.ui.service.DownloadService import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.util.mapNotNullToSet import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.search.ui.global.GlobalSearchActivity @@ -193,23 +194,9 @@ class DetailsActivity : R.id.action_save -> { viewModel.manga.value?.let { val chaptersCount = it.chapters?.size ?: 0 - if (chaptersCount > 5) { - MaterialAlertDialogBuilder(this) - .setTitle(R.string.save_manga) - .setMessage( - getString( - R.string.large_manga_save_confirm, - resources.getQuantityString( - R.plurals.chapters, - chaptersCount, - chaptersCount - ) - ) - ) - .setNegativeButton(android.R.string.cancel, null) - .setPositiveButton(R.string.save) { _, _ -> - DownloadService.start(this, it) - }.show() + val branches = viewModel.branches.value.orEmpty() + if (chaptersCount > 5 || branches.size > 1) { + showSaveConfirmation(it, chaptersCount, branches) } else { DownloadService.start(this, it) } @@ -335,6 +322,36 @@ class DetailsActivity : } } + private fun showSaveConfirmation(manga: Manga, chaptersCount: Int, branches: List) { + val dialogBuilder = MaterialAlertDialogBuilder(this) + .setTitle(R.string.save_manga) + .setNegativeButton(android.R.string.cancel, null) + if (branches.size > 1) { + val items = Array(branches.size) { i -> branches[i].orEmpty() } + val currentBranch = viewModel.selectedBranchIndex.value ?: -1 + val checkedIndices = BooleanArray(branches.size) { i -> i == currentBranch } + dialogBuilder.setMultiChoiceItems(items, checkedIndices) { _, i, checked -> + checkedIndices[i] = checked + }.setPositiveButton(R.string.save) { _, _ -> + val selectedBranches = branches.filterIndexedTo(HashSet()) { i, _ -> checkedIndices[i] } + val chaptersIds = manga.chapters?.mapNotNullToSet { c -> + if (c.branch in selectedBranches) c.id else null + } + DownloadService.start(this, manga, chaptersIds) + } + } else { + dialogBuilder.setMessage( + getString( + R.string.large_manga_save_confirm, + resources.getQuantityString(R.plurals.chapters, chaptersCount, chaptersCount) + ) + ).setPositiveButton(R.string.save) { _, _ -> + DownloadService.start(this, manga) + } + } + dialogBuilder.show() + } + companion object { fun newIntent(context: Context, manga: Manga): Intent { diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt index d0318779b..cba0e11b6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt @@ -267,10 +267,10 @@ class DetailsViewModel( val dateFormat = settings.getDateFormat() for (i in sourceChapters.indices) { val chapter = sourceChapters[i] + val localChapter = chaptersMap.remove(chapter.id) if (chapter.branch != branch) { continue } - val localChapter = chaptersMap.remove(chapter.id) result += localChapter?.toListItem( isCurrent = i == currentIndex, isUnread = i > currentIndex, @@ -289,15 +289,19 @@ class DetailsViewModel( } if (chaptersMap.isNotEmpty()) { // some chapters on device but not online source result.ensureCapacity(result.size + chaptersMap.size) - chaptersMap.values.mapTo(result) { - it.toListItem( - isCurrent = false, - isUnread = true, - isNew = false, - isMissing = false, - isDownloaded = false, - dateFormat = dateFormat, - ) + chaptersMap.values.mapNotNullTo(result) { + if (it.branch == branch) { + it.toListItem( + isCurrent = false, + isUnread = true, + isNew = false, + isMissing = false, + isDownloaded = false, + dateFormat = dateFormat, + ) + } else { + null + } } result.sortBy { it.chapter.number } } diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/MangaIndex.kt b/app/src/main/java/org/koitharu/kotatsu/local/data/MangaIndex.kt index e0eb87865..3a585be9c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/data/MangaIndex.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/data/MangaIndex.kt @@ -87,7 +87,7 @@ class MangaIndex(source: String?) { jo.put("uploadDate", chapter.uploadDate) jo.put("scanlator", chapter.scanlator) jo.put("branch", chapter.branch) - jo.put("entries", "%03d\\d{3}".format(chapter.number)) + jo.put("entries", "%08d_%03d\\d{3}".format(chapter.branch.hashCode(), chapter.number)) chapters.put(chapter.id.toString(), jo) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/local/domain/CbzMangaOutput.kt b/app/src/main/java/org/koitharu/kotatsu/local/domain/CbzMangaOutput.kt index 9278dd83f..53e2d474a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/domain/CbzMangaOutput.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/domain/CbzMangaOutput.kt @@ -36,7 +36,7 @@ class CbzMangaOutput( suspend fun addCover(file: File, ext: String) { val name = buildString { - append(FILENAME_PATTERN.format(0, 0)) + append(FILENAME_PATTERN.format(0, 0, 0)) if (ext.isNotEmpty() && ext.length <= 4) { append('.') append(ext) @@ -50,7 +50,7 @@ class CbzMangaOutput( suspend fun addPage(chapter: MangaChapter, file: File, pageNumber: Int, ext: String) { val name = buildString { - append(FILENAME_PATTERN.format(chapter.number, pageNumber)) + append(FILENAME_PATTERN.format(chapter.branch.hashCode(), chapter.number, pageNumber)) if (ext.isNotEmpty() && ext.length <= 4) { append('.') append(ext) @@ -105,7 +105,7 @@ class CbzMangaOutput( companion object { - private const val FILENAME_PATTERN = "%03d%03d" + private const val FILENAME_PATTERN = "%08d_%03d%03d" const val ENTRY_NAME_INDEX = "index.json"