Support multiple branches in saved manga
This commit is contained in:
@@ -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<String?>) {
|
||||
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 {
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user