diff --git a/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt b/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt index 771684db..34c78db3 100644 --- a/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt +++ b/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt @@ -60,7 +60,7 @@ class DownloadsManager(private val context: Context) { onFinished: () -> Unit ) { removeDownloadCompat(context, downloadedType, toast) - downloadsList.remove(downloadedType) + downloadsList.removeAll { it.titleName == downloadedType.titleName && it.chapterName == downloadedType.chapterName } CoroutineScope(Dispatchers.IO).launch { removeDirectory(downloadedType, toast) withContext(Dispatchers.Main) { @@ -234,7 +234,7 @@ class DownloadsManager(private val context: Context) { val directory = baseDirectory?.findFolder(downloadedType.titleName) ?.findFolder(downloadedType.chapterName) - downloadsList.remove(downloadedType) + downloadsList.removeAll { it.titleName == downloadedType.titleName && it.chapterName == downloadedType.chapterName } // Check if the directory exists and delete it recursively if (directory?.exists() == true) { val deleted = directory.deleteRecursively(context, false) @@ -401,10 +401,13 @@ data class DownloadedType( @Deprecated("use pTitle instead") private val title: String? = null, @Deprecated("use pChapter instead") - private val chapter: String? = null + private val chapter: String? = null, + val scanlator: String = "Unknown" ) : Serializable { val titleName: String get() = title ?: pTitle.findValidName() val chapterName: String get() = chapter ?: pChapter.findValidName() + val uniqueName: String + get() = "$chapterName-${scanlator}" } diff --git a/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt b/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt index ed3cb02c..58e7de38 100644 --- a/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt +++ b/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt @@ -243,7 +243,7 @@ class MangaDownloaderService : Service() { builder.setProgress(task.imageData.size, farthest, false) broadcastDownloadProgress( - task.chapter, + task.uniqueName, farthest * 100 / task.imageData.size ) if (notifi) { @@ -270,17 +270,18 @@ class MangaDownloaderService : Service() { DownloadedType( task.title, task.chapter, - MediaType.MANGA + MediaType.MANGA, + scanlator = task.scanlator, ) ) - broadcastDownloadFinished(task.chapter) + broadcastDownloadFinished(task.uniqueName) snackString("${task.title} - ${task.chapter} Download finished") } } catch (e: Exception) { Logger.log("Exception while downloading file: ${e.message}") snackString("Exception while downloading file: ${e.message}") Injekt.get().logException(e) - broadcastDownloadFailed(task.chapter) + broadcastDownloadFailed(task.uniqueName) } } @@ -423,11 +424,15 @@ class MangaDownloaderService : Service() { data class DownloadTask( val title: String, val chapter: String, + val scanlator: String, val imageData: List, val sourceMedia: Media? = null, val retries: Int = 2, val simultaneousDownloads: Int = 2, - ) + ) { + val uniqueName: String + get() = "$chapter-$scanlator" + } companion object { private const val NOTIFICATION_ID = 1103 diff --git a/app/src/main/java/ani/dantotsu/media/manga/Manga.kt b/app/src/main/java/ani/dantotsu/media/manga/Manga.kt index 24275add..636e9da5 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/Manga.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/Manga.kt @@ -5,7 +5,7 @@ import java.io.Serializable data class Manga( var totalChapters: Int? = null, - var selectedChapter: String? = null, + var selectedChapter: MangaChapter? = null, var chapters: MutableMap? = null, var slug: String? = null, var author: Author? = null, diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaChapter.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaChapter.kt index d8944b66..96cc4379 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaChapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaChapter.kt @@ -40,4 +40,6 @@ data class MangaChapter( private val dualPages = mutableListOf>() fun dualPages(): List> = dualPages + fun uniqueNumber(): String = "${number}-${scanlator ?: "Unknown"}" + } diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt index 933928e0..77f20b20 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt @@ -63,7 +63,7 @@ class MangaChapterAdapter( init { itemView.setOnClickListener { if (0 <= bindingAdapterPosition && bindingAdapterPosition < arr.size) - fragment.onMangaChapterClick(arr[bindingAdapterPosition].number) + fragment.onMangaChapterClick(arr[bindingAdapterPosition]) } } } @@ -74,7 +74,7 @@ class MangaChapterAdapter( fun startDownload(chapterNumber: String) { activeDownloads.add(chapterNumber) // Find the position of the chapter and notify only that item - val position = arr.indexOfFirst { it.number == chapterNumber } + val position = arr.indexOfFirst { it.uniqueNumber() == chapterNumber } if (position != -1) { notifyItemChanged(position) } @@ -84,17 +84,17 @@ class MangaChapterAdapter( activeDownloads.remove(chapterNumber) downloadedChapters.add(chapterNumber) // Find the position of the chapter and notify only that item - val position = arr.indexOfFirst { it.number == chapterNumber } + val position = arr.indexOfFirst { it.uniqueNumber() == chapterNumber } if (position != -1) { arr[position].progress = "Downloaded" notifyItemChanged(position) } } - fun deleteDownload(chapterNumber: String) { - downloadedChapters.remove(chapterNumber) + fun deleteDownload(chapterNumber: MangaChapter) { + downloadedChapters.remove(chapterNumber.uniqueNumber()) // Find the position of the chapter and notify only that item - val position = arr.indexOfFirst { it.number == chapterNumber } + val position = arr.indexOfFirst { it.uniqueNumber() == chapterNumber.uniqueNumber() } if (position != -1) { arr[position].progress = "" notifyItemChanged(position) @@ -105,7 +105,7 @@ class MangaChapterAdapter( activeDownloads.remove(chapterNumber) downloadedChapters.remove(chapterNumber) // Find the position of the chapter and notify only that item - val position = arr.indexOfFirst { it.number == chapterNumber } + val position = arr.indexOfFirst { it.uniqueNumber() == chapterNumber } if (position != -1) { arr[position].progress = "" notifyItemChanged(position) @@ -114,7 +114,7 @@ class MangaChapterAdapter( fun updateDownloadProgress(chapterNumber: String, progress: Int) { // Find the position of the chapter and notify only that item - val position = arr.indexOfFirst { it.number == chapterNumber } + val position = arr.indexOfFirst { it.uniqueNumber() == chapterNumber } if (position != -1) { arr[position].progress = "Downloading: ${progress}%" @@ -127,7 +127,8 @@ class MangaChapterAdapter( if (position < 0 || position >= arr.size) return for (i in 0.. { val binding = holder.binding val ep = arr[position] - holder.bind(ep.number, ep.progress) + holder.bind(ep.uniqueNumber(), ep.progress) setAnimation(fragment.requireContext(), holder.binding.root) binding.itemChapterNumber.text = ep.number diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt index 39aef576..9cebc4a6 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt @@ -422,12 +422,12 @@ class MangaReadAdapter( val startChapter = MediaNameAdapter.findChapterNumber(names[limit * (position)]) val endChapter = MediaNameAdapter.findChapterNumber(names[last - 1]) val startChapterString = if (startChapter != null) { - "Ch.$startChapter" + "Ch.%.1f".format(startChapter) } else { names[limit * (position)] } val endChapterString = if (endChapter != null) { - "Ch.$endChapter" + "Ch.%.1f".format(endChapter) } else { names[last - 1] } @@ -472,7 +472,6 @@ class MangaReadAdapter( val binding = _binding if (binding != null) { if (media.manga?.chapters != null) { - val chapters = media.manga.chapters!!.keys.toTypedArray() val anilistEp = (media.userProgress ?: 0).plus(1) val appEp = PrefManager.getNullableCustomVal( "${media.id}_current_chp", @@ -480,37 +479,39 @@ class MangaReadAdapter( String::class.java ) ?.toIntOrNull() ?: 1 - var continueEp = (if (anilistEp > appEp) anilistEp else appEp).toString() - val filteredChapters = chapters.filter { chapterKey -> - val chapter = media.manga.chapters!![chapterKey]!! - chapter.scanlator !in hiddenScanlators + val continueNumber = (if (anilistEp > appEp) anilistEp else appEp).toString() + val filteredChapters = media.manga.chapters!!.filter { chapter -> + if (mangaReadSources[media.selected!!.sourceIndex] is OfflineMangaParser) { + true + } else { + chapter.value.scanlator !in hiddenScanlators + } } val formattedChapters = filteredChapters.map { - MediaNameAdapter.findChapterNumber(it)?.toInt()?.toString() + MediaNameAdapter.findChapterNumber(it.value.number)?.toInt()?.toString() to it.key } - if (formattedChapters.contains(continueEp)) { - continueEp = chapters[formattedChapters.indexOf(continueEp)] + if (formattedChapters.any { it.first == continueNumber }) { + var continueEp = media.manga.chapters!![formattedChapters.first { it.first == continueNumber }.second] binding.sourceContinue.visibility = View.VISIBLE handleProgress( binding.itemMediaProgressCont, binding.itemMediaProgress, binding.itemMediaProgressEmpty, media.id, - continueEp + continueEp!!.number ) if ((binding.itemMediaProgress.layoutParams as LinearLayout.LayoutParams).weight > 0.8f) { - val e = chapters.indexOf(continueEp) - if (e != -1 && e + 1 < chapters.size) { - continueEp = chapters[e + 1] + val numberPlusOne = formattedChapters.indexOfFirst { it.first?.toIntOrNull() == continueNumber.toInt() + 1 } + if (numberPlusOne != -1) { + continueEp = media.manga.chapters!![formattedChapters[numberPlusOne].second] } } - val ep = media.manga.chapters!![continueEp]!! binding.itemMediaImage.loadImage(media.banner ?: media.cover) binding.mediaSourceContinueText.text = currActivity()!!.getString( R.string.continue_chapter, - ep.number, - if (!ep.title.isNullOrEmpty()) ep.title else "" + continueEp!!.number, + if (!continueEp.title.isNullOrEmpty()) continueEp.title else "" ) binding.sourceContinue.setOnClickListener { fragment.onMangaChapterClick(continueEp) diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt index be836ad5..b83da78e 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt @@ -52,6 +52,7 @@ import ani.dantotsu.parsers.DynamicMangaParser import ani.dantotsu.parsers.HMangaSources import ani.dantotsu.parsers.MangaParser import ani.dantotsu.parsers.MangaSources +import ani.dantotsu.parsers.OfflineMangaParser import ani.dantotsu.setNavigationTheme import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment import ani.dantotsu.settings.saving.PrefManager @@ -195,7 +196,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { for (download in downloadManager.mangaDownloadedTypes) { if (media.compareName(download.titleName)) { - chapterAdapter.stopDownload(download.chapterName) + chapterAdapter.stopDownload(download.uniqueName) } } @@ -249,7 +250,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { for (chapter in chaptersToDownload) { - onMangaChapterDownloadClick(chapter.title!!) + onMangaChapterDownloadClick(chapter) } } @@ -260,8 +261,12 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { val chapters = loadedChapters[media.selected!!.sourceIndex] if (chapters != null) { headerAdapter.options = getScanlators(chapters) - val filteredChapters = chapters.filterNot { (_, chapter) -> - chapter.scanlator in headerAdapter.hiddenScanlators + val filteredChapters = if (model.mangaReadSources?.get(media.selected!!.sourceIndex) is OfflineMangaParser) { + chapters + } else { + chapters.filterNot { (_, chapter) -> + chapter.scanlator in headerAdapter.hiddenScanlators + } } media.manga?.chapters = filteredChapters.toMutableMap() @@ -430,9 +435,9 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { } } - fun onMangaChapterClick(i: String) { + fun onMangaChapterClick(i: MangaChapter) { model.continueMedia = false - media.manga?.chapters?.get(i)?.let { + media.manga?.chapters?.get(i.uniqueNumber())?.let { media.manga?.selectedChapter = i model.saveSelected(media.id, media.selected!!) ChapterLoaderDialog.newInstance(it, true) @@ -440,7 +445,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { } } - fun onMangaChapterDownloadClick(i: String) { + fun onMangaChapterDownloadClick(i: MangaChapter) { activity?.let { if (!isNotificationPermissionGranted()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { @@ -453,7 +458,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { } fun continueDownload() { model.continueMedia = false - media.manga?.chapters?.get(i)?.let { chapter -> + media.manga?.chapters?.get(i.uniqueNumber())?.let { chapter -> val parser = model.mangaReadSources?.get(media.selected!!.sourceIndex) as? DynamicMangaParser parser?.let { @@ -464,6 +469,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { val downloadTask = MangaDownloaderService.DownloadTask( title = media.mainName(), chapter = chapter.title!!, + scanlator = chapter.scanlator ?: "Unknown", imageData = images, sourceMedia = media, retries = 2, @@ -483,7 +489,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { // Inform the adapter that the download has started withContext(Dispatchers.Main) { - chapterAdapter.startDownload(i) + chapterAdapter.startDownload(i.uniqueNumber()) } } } @@ -514,11 +520,11 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { } - fun onMangaChapterRemoveDownloadClick(i: String) { + fun onMangaChapterRemoveDownloadClick(i: MangaChapter) { downloadManager.removeDownload( DownloadedType( media.mainName(), - i, + i.number, MediaType.MANGA ) ) { @@ -526,7 +532,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { } } - fun onMangaChapterStopDownloadClick(i: String) { + fun onMangaChapterStopDownloadClick(i: MangaChapter) { val cancelIntent = Intent().apply { action = MangaDownloaderService.ACTION_CANCEL_DOWNLOAD putExtra(MangaDownloaderService.EXTRA_CHAPTER, i) @@ -537,11 +543,11 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { downloadManager.removeDownload( DownloadedType( media.mainName(), - i, + i.number, MediaType.MANGA ) ) { - chapterAdapter.purgeDownload(i) + chapterAdapter.purgeDownload(i.uniqueNumber()) } } @@ -584,7 +590,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { // Find latest chapter for subscription selected.latest = - media.manga?.chapters?.values?.maxOfOrNull { it.number.toFloatOrNull() ?: 0f } ?: 0f + media.manga?.chapters?.values?.maxOfOrNull { MediaNameAdapter.findChapterNumber(it.number) ?: 0f } ?: 0f selected.latest = media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt index 689ab6af..89597a7c 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt @@ -196,7 +196,7 @@ class MangaReaderActivity : AppCompatActivity() { finish() return@addCallback } - val chapter = (MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!) + val chapter = (MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!.number) ?.minus(1L) ?: 0).toString() if (chapter == "0.0" && PrefManager.getVal(PrefName.ChapterZeroReader) // Not asking individually or incognito @@ -279,7 +279,7 @@ class MangaReaderActivity : AppCompatActivity() { defaultSettings = loadReaderSettings("${media.id}_current_settings") ?: defaultSettings chapters = media.manga?.chapters ?: return - chapter = chapters[media.manga!!.selectedChapter] ?: return + chapter = chapters[media.manga!!.selectedChapter!!.uniqueNumber()] ?: return model.mangaReadSources = if (media.isAdult) HMangaSources else MangaSources binding.mangaReaderSource.isVisible = PrefManager.getVal(PrefName.ShowSource) @@ -309,7 +309,7 @@ class MangaReaderActivity : AppCompatActivity() { binding.mangaReaderTitle.text = media.userPreferredName chaptersArr = chapters.keys.toList() - currentChapterIndex = chaptersArr.indexOf(media.manga!!.selectedChapter) + currentChapterIndex = chaptersArr.indexOf(media.manga!!.selectedChapter!!.uniqueNumber()) chaptersTitleArr = arrayListOf() chapters.forEach { @@ -394,10 +394,10 @@ class MangaReaderActivity : AppCompatActivity() { model.getMangaChapter().observe(this) { chap -> if (chap != null) { chapter = chap - media.manga!!.selectedChapter = chapter.number + media.manga!!.selectedChapter = chapter media.selected = model.loadSelected(media) PrefManager.setCustomVal("${media.id}_current_chp", chap.number) - currentChapterIndex = chaptersArr.indexOf(chap.number) + currentChapterIndex = chaptersArr.indexOf(chap.uniqueNumber()) binding.mangaReaderChapterSelect.setSelection(currentChapterIndex) if (directionRLBT) { binding.mangaReaderNextChap.text = @@ -1036,7 +1036,7 @@ class MangaReaderActivity : AppCompatActivity() { PrefManager.setCustomVal("${media.id}_save_progress", true) updateProgress( media, - MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!) + MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!.number) .toString() ) runnable.run() @@ -1057,7 +1057,7 @@ class MangaReaderActivity : AppCompatActivity() { ) updateProgress( media, - MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!) + MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!.number) .toString() ) runnable.run() diff --git a/app/src/main/java/ani/dantotsu/parsers/BaseParser.kt b/app/src/main/java/ani/dantotsu/parsers/BaseParser.kt index abfe0f8a..948ba2c3 100644 --- a/app/src/main/java/ani/dantotsu/parsers/BaseParser.kt +++ b/app/src/main/java/ani/dantotsu/parsers/BaseParser.kt @@ -1,3 +1,4 @@ + package ani.dantotsu.parsers import android.graphics.drawable.Drawable diff --git a/app/src/main/java/ani/dantotsu/parsers/BaseSources.kt b/app/src/main/java/ani/dantotsu/parsers/BaseSources.kt index 79d84225..aeae9f67 100644 --- a/app/src/main/java/ani/dantotsu/parsers/BaseSources.kt +++ b/app/src/main/java/ani/dantotsu/parsers/BaseSources.kt @@ -90,7 +90,7 @@ abstract class MangaReadSources : BaseSources() { show.sManga?.let { sManga -> tryWithSuspend(true) { parser.loadChapters(show.link, show.extra, sManga).forEach { - map["${it.number}-${it.hashCode()}"] = MangaChapter(it) + map["${it.number}-${it.scanlator}"] = MangaChapter(it) } } } @@ -102,7 +102,7 @@ abstract class MangaReadSources : BaseSources() { tryWithSuspend(true) { // Since we've checked, we can safely cast parser to OfflineMangaParser and call its methods parser.loadChapters(show.link, show.extra, SManga.create()).forEach { - map["${it.number}-${it.hashCode()}"] = MangaChapter(it) + map["${it.number}-${it.scanlator}"] = MangaChapter(it) } } } else { diff --git a/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt b/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt index ec3ca338..eb8a8bda 100644 --- a/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt +++ b/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt @@ -31,13 +31,17 @@ class OfflineMangaParser : MangaParser() { val chapters = mutableListOf() if (directory?.exists() == true) { directory.listFiles().forEach { + val scanlator = downloadManager.mangaDownloadedTypes.find { items -> + items.titleName == mangaLink && + items.chapterName == it.name + }?.scanlator ?: "Unknown" if (it.isDirectory) { val chapter = MangaChapter( it.name!!, "$mangaLink/${it.name}", it.name, null, - null, + scanlator, SChapter.create() ) chapters.add(chapter) @@ -45,8 +49,7 @@ class OfflineMangaParser : MangaParser() { } } chapters.addAll(loadChaptersCompat(mangaLink, extra, sManga)) - return chapters.distinctBy { it.number } - .sortedBy { MediaNameAdapter.findChapterNumber(it.number) } + return chapters.sortedBy { MediaNameAdapter.findChapterNumber(it.number) } } override suspend fun loadImages(chapterLink: String, sChapter: SChapter): List {