fix: allow deprecated media to be played
This commit is contained in:
parent
3c46c21a25
commit
3622d91886
12 changed files with 647 additions and 103 deletions
381
app/src/main/java/ani/dantotsu/download/DownloadCompat.kt
Normal file
381
app/src/main/java/ani/dantotsu/download/DownloadCompat.kt
Normal file
|
@ -0,0 +1,381 @@
|
|||
package ani.dantotsu.download
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import android.widget.Toast
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.download.anime.OfflineAnimeModel
|
||||
import ani.dantotsu.download.manga.OfflineMangaModel
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.parsers.Episode
|
||||
import ani.dantotsu.parsers.MangaChapter
|
||||
import ani.dantotsu.parsers.MangaImage
|
||||
import ani.dantotsu.parsers.Subtitle
|
||||
import ani.dantotsu.parsers.SubtitleType
|
||||
import ani.dantotsu.util.Logger
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.InstanceCreator
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnimeImpl
|
||||
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||
import eu.kanade.tachiyomi.animesource.model.SEpisodeImpl
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SChapterImpl
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
import java.util.Locale
|
||||
|
||||
@Deprecated("external storage is deprecated, use SAF instead")
|
||||
class DownloadCompat {
|
||||
companion object {
|
||||
@Deprecated("external storage is deprecated, use SAF instead")
|
||||
fun loadMediaCompat(downloadedType: DownloadedType): Media? {
|
||||
val type = when (downloadedType.type) {
|
||||
MediaType.MANGA -> "Manga"
|
||||
MediaType.ANIME -> "Anime"
|
||||
else -> "Novel"
|
||||
}
|
||||
val directory = File(
|
||||
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/$type/${downloadedType.titleName}"
|
||||
)
|
||||
//load media.json and convert to media class with gson
|
||||
return try {
|
||||
val gson = GsonBuilder()
|
||||
.registerTypeAdapter(SChapter::class.java, InstanceCreator<SChapter> {
|
||||
SChapterImpl() // Provide an instance of SChapterImpl
|
||||
})
|
||||
.registerTypeAdapter(SAnime::class.java, InstanceCreator<SAnime> {
|
||||
SAnimeImpl() // Provide an instance of SAnimeImpl
|
||||
})
|
||||
.registerTypeAdapter(SEpisode::class.java, InstanceCreator<SEpisode> {
|
||||
SEpisodeImpl() // Provide an instance of SEpisodeImpl
|
||||
})
|
||||
.create()
|
||||
val media = File(directory, "media.json")
|
||||
val mediaJson = media.readText()
|
||||
gson.fromJson(mediaJson, Media::class.java)
|
||||
} catch (e: Exception) {
|
||||
Logger.log("Error loading media.json: ${e.message}")
|
||||
Logger.log(e)
|
||||
Injekt.get<CrashlyticsInterface>().logException(e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("external storage is deprecated, use SAF instead")
|
||||
fun loadOfflineAnimeModelCompat(downloadedType: DownloadedType): OfflineAnimeModel {
|
||||
val type = when (downloadedType.type) {
|
||||
MediaType.MANGA -> "Manga"
|
||||
MediaType.ANIME -> "Anime"
|
||||
else -> "Novel"
|
||||
}
|
||||
val directory = File(
|
||||
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/$type/${downloadedType.titleName}"
|
||||
)
|
||||
//load media.json and convert to media class with gson
|
||||
try {
|
||||
val mediaModel = loadMediaCompat(downloadedType)!!
|
||||
val cover = File(directory, "cover.jpg")
|
||||
val coverUri: Uri? = if (cover.exists()) {
|
||||
Uri.fromFile(cover)
|
||||
} else null
|
||||
val banner = File(directory, "banner.jpg")
|
||||
val bannerUri: Uri? = if (banner.exists()) {
|
||||
Uri.fromFile(banner)
|
||||
} else null
|
||||
val title = mediaModel.mainName()
|
||||
val score = ((if (mediaModel.userScore == 0) (mediaModel.meanScore
|
||||
?: 0) else mediaModel.userScore) / 10.0).toString()
|
||||
val isOngoing =
|
||||
mediaModel.status == currActivity()!!.getString(R.string.status_releasing)
|
||||
val isUserScored = mediaModel.userScore != 0
|
||||
val watchedEpisodes = (mediaModel.userProgress ?: "~").toString()
|
||||
val totalEpisode =
|
||||
if (mediaModel.anime?.nextAiringEpisode != null) (mediaModel.anime.nextAiringEpisode.toString() + " | " + (mediaModel.anime.totalEpisodes
|
||||
?: "~").toString()) else (mediaModel.anime?.totalEpisodes ?: "~").toString()
|
||||
val chapters = " Chapters"
|
||||
val totalEpisodesList =
|
||||
if (mediaModel.anime?.nextAiringEpisode != null) (mediaModel.anime.nextAiringEpisode.toString()) else (mediaModel.anime?.totalEpisodes
|
||||
?: "~").toString()
|
||||
return OfflineAnimeModel(
|
||||
title,
|
||||
score,
|
||||
totalEpisode,
|
||||
totalEpisodesList,
|
||||
watchedEpisodes,
|
||||
type,
|
||||
chapters,
|
||||
isOngoing,
|
||||
isUserScored,
|
||||
coverUri,
|
||||
bannerUri
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Logger.log("Error loading media.json: ${e.message}")
|
||||
Logger.log(e)
|
||||
Injekt.get<CrashlyticsInterface>().logException(e)
|
||||
return OfflineAnimeModel(
|
||||
"unknown",
|
||||
"0",
|
||||
"??",
|
||||
"??",
|
||||
"??",
|
||||
"movie",
|
||||
"hmm",
|
||||
isOngoing = false,
|
||||
isUserScored = false,
|
||||
null,
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("external storage is deprecated, use SAF instead")
|
||||
fun loadOfflineMangaModelCompat(downloadedType: DownloadedType): OfflineMangaModel {
|
||||
val type = when (downloadedType.type) {
|
||||
MediaType.MANGA -> "Manga"
|
||||
MediaType.ANIME -> "Anime"
|
||||
else -> "Novel"
|
||||
}
|
||||
val directory = File(
|
||||
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/$type/${downloadedType.titleName}"
|
||||
)
|
||||
//load media.json and convert to media class with gson
|
||||
try {
|
||||
val mediaModel = loadMediaCompat(downloadedType)!!
|
||||
val cover = File(directory, "cover.jpg")
|
||||
val coverUri: Uri? = if (cover.exists()) {
|
||||
Uri.fromFile(cover)
|
||||
} else null
|
||||
val banner = File(directory, "banner.jpg")
|
||||
val bannerUri: Uri? = if (banner.exists()) {
|
||||
Uri.fromFile(banner)
|
||||
} else null
|
||||
val title = mediaModel.mainName()
|
||||
val score = ((if (mediaModel.userScore == 0) (mediaModel.meanScore
|
||||
?: 0) else mediaModel.userScore) / 10.0).toString()
|
||||
val isOngoing =
|
||||
mediaModel.status == currActivity()!!.getString(R.string.status_releasing)
|
||||
val isUserScored = mediaModel.userScore != 0
|
||||
val readchapter = (mediaModel.userProgress ?: "~").toString()
|
||||
val totalchapter = "${mediaModel.manga?.totalChapters ?: "??"}"
|
||||
val chapters = " Chapters"
|
||||
return OfflineMangaModel(
|
||||
title,
|
||||
score,
|
||||
totalchapter,
|
||||
readchapter,
|
||||
type,
|
||||
chapters,
|
||||
isOngoing,
|
||||
isUserScored,
|
||||
coverUri,
|
||||
bannerUri
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Logger.log("Error loading media.json: ${e.message}")
|
||||
Logger.log(e)
|
||||
Injekt.get<CrashlyticsInterface>().logException(e)
|
||||
return OfflineMangaModel(
|
||||
"unknown",
|
||||
"0",
|
||||
"??",
|
||||
"??",
|
||||
"movie",
|
||||
"hmm",
|
||||
isOngoing = false,
|
||||
isUserScored = false,
|
||||
null,
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("external storage is deprecated, use SAF instead")
|
||||
suspend fun loadEpisodesCompat(
|
||||
animeLink: String,
|
||||
extra: Map<String, String>?,
|
||||
sAnime: SAnime
|
||||
): List<Episode> {
|
||||
|
||||
val directory = File(
|
||||
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"${animeLocation}/$animeLink"
|
||||
)
|
||||
//get all of the folder names and add them to the list
|
||||
val episodes = mutableListOf<Episode>()
|
||||
if (directory.exists()) {
|
||||
directory.listFiles()?.forEach {
|
||||
//put the title and episdode number in the extra data
|
||||
val extraData = mutableMapOf<String, String>()
|
||||
extraData["title"] = animeLink
|
||||
extraData["episode"] = it.name
|
||||
if (it.isDirectory) {
|
||||
val episode = Episode(
|
||||
it.name,
|
||||
"$animeLink - ${it.name}",
|
||||
it.name,
|
||||
null,
|
||||
null,
|
||||
extra = extraData,
|
||||
sEpisode = SEpisodeImpl()
|
||||
)
|
||||
episodes.add(episode)
|
||||
}
|
||||
}
|
||||
episodes.sortBy { MediaNameAdapter.findEpisodeNumber(it.number) }
|
||||
return episodes
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
@Deprecated("external storage is deprecated, use SAF instead")
|
||||
suspend fun loadChaptersCompat(
|
||||
mangaLink: String,
|
||||
extra: Map<String, String>?,
|
||||
sManga: SManga
|
||||
): List<MangaChapter> {
|
||||
val directory = File(
|
||||
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/Manga/$mangaLink"
|
||||
)
|
||||
//get all of the folder names and add them to the list
|
||||
val chapters = mutableListOf<MangaChapter>()
|
||||
if (directory.exists()) {
|
||||
directory.listFiles()?.forEach {
|
||||
if (it.isDirectory) {
|
||||
val chapter = MangaChapter(
|
||||
it.name,
|
||||
"$mangaLink/${it.name}",
|
||||
it.name,
|
||||
null,
|
||||
null,
|
||||
SChapter.create()
|
||||
)
|
||||
chapters.add(chapter)
|
||||
}
|
||||
}
|
||||
chapters.sortBy { MediaNameAdapter.findChapterNumber(it.number) }
|
||||
return chapters
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
@Deprecated("external storage is deprecated, use SAF instead")
|
||||
suspend fun loadImagesCompat(chapterLink: String, sChapter: SChapter): List<MangaImage> {
|
||||
val directory = File(
|
||||
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/Manga/$chapterLink"
|
||||
)
|
||||
val images = mutableListOf<MangaImage>()
|
||||
val imageNumberRegex = Regex("""(\d+)\.jpg$""")
|
||||
if (directory.exists()) {
|
||||
directory.listFiles()?.forEach {
|
||||
if (it.isFile) {
|
||||
val image = MangaImage(it.absolutePath, false, null)
|
||||
images.add(image)
|
||||
}
|
||||
}
|
||||
images.sortBy { image ->
|
||||
val matchResult = imageNumberRegex.find(image.url.url)
|
||||
matchResult?.groups?.get(1)?.value?.toIntOrNull() ?: Int.MAX_VALUE
|
||||
}
|
||||
for (image in images) {
|
||||
Logger.log("imageNumber: ${image.url.url}")
|
||||
}
|
||||
return images
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
@Deprecated("external storage is deprecated, use SAF instead")
|
||||
fun loadSubtitleCompat(title: String, episode: String): List<Subtitle>? {
|
||||
currContext()?.let {
|
||||
File(
|
||||
it.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"$animeLocation/$title/$episode"
|
||||
).listFiles()?.forEach {
|
||||
if (it.name.contains("subtitle")) {
|
||||
return listOf(
|
||||
Subtitle(
|
||||
"Downloaded Subtitle",
|
||||
Uri.fromFile(it).toString(),
|
||||
determineSubtitletype(it.absolutePath)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun determineSubtitletype(url: String): SubtitleType {
|
||||
return when {
|
||||
url.lowercase(Locale.ROOT).endsWith("ass") -> SubtitleType.ASS
|
||||
url.lowercase(Locale.ROOT).endsWith("vtt") -> SubtitleType.VTT
|
||||
else -> SubtitleType.SRT
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("external storage is deprecated, use SAF instead")
|
||||
fun removeMediaCompat(context: Context, title: String, type: MediaType) {
|
||||
val subDirectory = if (type == MediaType.MANGA) {
|
||||
"Manga"
|
||||
} else if (type == MediaType.ANIME) {
|
||||
"Anime"
|
||||
} else {
|
||||
"Novel"
|
||||
}
|
||||
val directory = File(
|
||||
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/$subDirectory/$title"
|
||||
)
|
||||
if (directory.exists()) {
|
||||
directory.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("external storage is deprecated, use SAF instead")
|
||||
fun removeDownloadCompat(context: Context, downloadedType: DownloadedType) {
|
||||
val directory = if (downloadedType.type == MediaType.MANGA) {
|
||||
File(
|
||||
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/Manga/${downloadedType.titleName}/${downloadedType.chapterName}"
|
||||
)
|
||||
} else if (downloadedType.type == MediaType.ANIME) {
|
||||
File(
|
||||
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/Anime/${downloadedType.titleName}/${downloadedType.chapterName}"
|
||||
)
|
||||
} else {
|
||||
File(
|
||||
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/Novel/${downloadedType.titleName}/${downloadedType.chapterName}"
|
||||
)
|
||||
}
|
||||
|
||||
// Check if the directory exists and delete it recursively
|
||||
if (directory.exists()) {
|
||||
val deleted = directory.deleteRecursively()
|
||||
if (deleted) {
|
||||
Toast.makeText(context, "Successfully deleted", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Toast.makeText(context, "Failed to delete directory", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val animeLocation = "Dantotsu/Anime"
|
||||
}
|
||||
}
|
|
@ -3,6 +3,8 @@ package ani.dantotsu.download
|
|||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import ani.dantotsu.download.DownloadCompat.Companion.removeDownloadCompat
|
||||
import ani.dantotsu.download.DownloadCompat.Companion.removeMediaCompat
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
|
@ -58,6 +60,7 @@ class DownloadsManager(private val context: Context) {
|
|||
toast: Boolean = true,
|
||||
onFinished: () -> Unit
|
||||
) {
|
||||
removeDownloadCompat(context, downloadedType)
|
||||
downloadsList.remove(downloadedType)
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
removeDirectory(downloadedType, toast)
|
||||
|
@ -69,6 +72,7 @@ class DownloadsManager(private val context: Context) {
|
|||
}
|
||||
|
||||
fun removeMedia(title: String, type: MediaType) {
|
||||
removeMediaCompat(context, title, type)
|
||||
val baseDirectory = getBaseDirectory(context, type)
|
||||
val directory = baseDirectory?.findFolder(title)
|
||||
if (directory?.exists() == true) {
|
||||
|
@ -84,15 +88,15 @@ class DownloadsManager(private val context: Context) {
|
|||
}
|
||||
when (type) {
|
||||
MediaType.MANGA -> {
|
||||
downloadsList.removeAll { it.title == title && it.type == MediaType.MANGA }
|
||||
downloadsList.removeAll { it.titleName == title && it.type == MediaType.MANGA }
|
||||
}
|
||||
|
||||
MediaType.ANIME -> {
|
||||
downloadsList.removeAll { it.title == title && it.type == MediaType.ANIME }
|
||||
downloadsList.removeAll { it.titleName == title && it.type == MediaType.ANIME }
|
||||
}
|
||||
|
||||
MediaType.NOVEL -> {
|
||||
downloadsList.removeAll { it.title == title && it.type == MediaType.NOVEL }
|
||||
downloadsList.removeAll { it.titleName == title && it.type == MediaType.NOVEL }
|
||||
}
|
||||
}
|
||||
saveDownloads()
|
||||
|
@ -115,7 +119,7 @@ class DownloadsManager(private val context: Context) {
|
|||
if (directory?.exists() == true && directory.isDirectory) {
|
||||
val files = directory.listFiles()
|
||||
for (file in files) {
|
||||
if (!downloadsSubLists.any { it.title == file.name }) {
|
||||
if (!downloadsSubLists.any { it.titleName == file.name }) {
|
||||
file.deleteRecursively(context, false)
|
||||
}
|
||||
}
|
||||
|
@ -124,8 +128,8 @@ class DownloadsManager(private val context: Context) {
|
|||
val iterator = downloadsList.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val download = iterator.next()
|
||||
val downloadDir = directory?.findFolder(download.title)
|
||||
if ((downloadDir?.exists() == false && download.type == type) || download.title.isBlank()) {
|
||||
val downloadDir = directory?.findFolder(download.titleName)
|
||||
if ((downloadDir?.exists() == false && download.type == type) || download.titleName.isBlank()) {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
|
@ -211,16 +215,17 @@ class DownloadsManager(private val context: Context) {
|
|||
|
||||
fun queryDownload(title: String, chapter: String, type: MediaType? = null): Boolean {
|
||||
return if (type == null) {
|
||||
downloadsList.any { it.title == title && it.chapter == chapter }
|
||||
downloadsList.any { it.titleName == title && it.chapterName == chapter }
|
||||
} else {
|
||||
downloadsList.any { it.title == title && it.chapter == chapter && it.type == type }
|
||||
downloadsList.any { it.titleName == title && it.chapterName == chapter && it.type == type }
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeDirectory(downloadedType: DownloadedType, toast: Boolean) {
|
||||
val baseDirectory = getBaseDirectory(context, downloadedType.type)
|
||||
val directory =
|
||||
baseDirectory?.findFolder(downloadedType.title)?.findFolder(downloadedType.chapter)
|
||||
baseDirectory?.findFolder(downloadedType.titleName)
|
||||
?.findFolder(downloadedType.chapterName)
|
||||
downloadsList.remove(downloadedType)
|
||||
// Check if the directory exists and delete it recursively
|
||||
if (directory?.exists() == true) {
|
||||
|
@ -369,10 +374,16 @@ private fun String?.findValidName(): String {
|
|||
}
|
||||
|
||||
data class DownloadedType(
|
||||
val pTitle: String, val pChapter: String, val type: MediaType
|
||||
private val pTitle: String?,
|
||||
private val pChapter: String?,
|
||||
val type: MediaType,
|
||||
@Deprecated("use pTitle instead")
|
||||
private val title: String? = null,
|
||||
@Deprecated("use pChapter instead")
|
||||
private val chapter: String? = null
|
||||
) : Serializable {
|
||||
val title: String
|
||||
get() = pTitle.findValidName()
|
||||
val chapter: String
|
||||
get() = pChapter.findValidName()
|
||||
val titleName: String
|
||||
get() = title?:pTitle.findValidName()
|
||||
val chapterName: String
|
||||
get() = chapter?:pChapter.findValidName()
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ import ani.dantotsu.bottomBar
|
|||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.download.DownloadCompat.Companion.loadMediaCompat
|
||||
import ani.dantotsu.download.DownloadCompat.Companion.loadOfflineAnimeModelCompat
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.DownloadsManager.Companion.compareName
|
||||
|
@ -175,7 +177,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
|||
// Get the OfflineAnimeModel that was clicked
|
||||
val item = adapter.getItem(position) as OfflineAnimeModel
|
||||
val media =
|
||||
downloadManager.animeDownloadedTypes.firstOrNull { it.title.compareName(item.title) }
|
||||
downloadManager.animeDownloadedTypes.firstOrNull { it.titleName.compareName(item.title) }
|
||||
media?.let {
|
||||
lifecycleScope.launch {
|
||||
val mediaModel = getMedia(it)
|
||||
|
@ -287,10 +289,10 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
|||
}
|
||||
downloadsJob = Job()
|
||||
CoroutineScope(Dispatchers.IO + downloadsJob).launch {
|
||||
val animeTitles = downloadManager.animeDownloadedTypes.map { it.title }.distinct()
|
||||
val animeTitles = downloadManager.animeDownloadedTypes.map { it.titleName }.distinct()
|
||||
val newAnimeDownloads = mutableListOf<OfflineAnimeModel>()
|
||||
for (title in animeTitles) {
|
||||
val tDownloads = downloadManager.animeDownloadedTypes.filter { it.title == title }
|
||||
val tDownloads = downloadManager.animeDownloadedTypes.filter { it.titleName == title }
|
||||
val download = tDownloads.first()
|
||||
val offlineAnimeModel = loadOfflineAnimeModel(download)
|
||||
newAnimeDownloads += offlineAnimeModel
|
||||
|
@ -313,7 +315,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
|||
return try {
|
||||
val directory = DownloadsManager.getSubDirectory(
|
||||
context ?: currContext()!!, downloadedType.type,
|
||||
false, downloadedType.title
|
||||
false, downloadedType.titleName
|
||||
)
|
||||
val gson = GsonBuilder()
|
||||
.registerTypeAdapter(SChapter::class.java, InstanceCreator<SChapter> {
|
||||
|
@ -327,7 +329,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
|||
})
|
||||
.create()
|
||||
val media = directory?.findFile("media.json")
|
||||
?: return null
|
||||
?: return loadMediaCompat(downloadedType)
|
||||
val mediaJson =
|
||||
media.openInputStream(context ?: currContext()!!)?.bufferedReader().use {
|
||||
it?.readText()
|
||||
|
@ -352,7 +354,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
|||
try {
|
||||
val directory = DownloadsManager.getSubDirectory(
|
||||
context ?: currContext()!!, downloadedType.type,
|
||||
false, downloadedType.title
|
||||
false, downloadedType.titleName
|
||||
)
|
||||
val mediaModel = getMedia(downloadedType)!!
|
||||
val cover = directory?.findFile("cover.jpg")
|
||||
|
@ -390,11 +392,14 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
|||
coverUri,
|
||||
bannerUri
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
return try {
|
||||
loadOfflineAnimeModelCompat(downloadedType)
|
||||
} catch (e: Exception) {
|
||||
Logger.log("Error loading media.json: ${e.message}")
|
||||
Logger.log(e)
|
||||
Injekt.get<CrashlyticsInterface>().logException(e)
|
||||
return OfflineAnimeModel(
|
||||
OfflineAnimeModel(
|
||||
"unknown",
|
||||
"0",
|
||||
"??",
|
||||
|
@ -409,6 +414,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface OfflineAnimeSearchListener {
|
||||
|
|
|
@ -28,6 +28,8 @@ import ani.dantotsu.bottomBar
|
|||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.download.DownloadCompat
|
||||
import ani.dantotsu.download.DownloadCompat.Companion.loadOfflineMangaModelCompat
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.DownloadsManager.Companion.compareName
|
||||
|
@ -169,8 +171,8 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
// Get the OfflineMangaModel that was clicked
|
||||
val item = adapter.getItem(position) as OfflineMangaModel
|
||||
val media =
|
||||
downloadManager.mangaDownloadedTypes.firstOrNull { it.title.compareName(item.title) }
|
||||
?: downloadManager.novelDownloadedTypes.firstOrNull { it.title.compareName(item.title) }
|
||||
downloadManager.mangaDownloadedTypes.firstOrNull { it.titleName.compareName(item.title) }
|
||||
?: downloadManager.novelDownloadedTypes.firstOrNull { it.titleName.compareName(item.title) }
|
||||
media?.let {
|
||||
lifecycleScope.launch {
|
||||
ContextCompat.startActivity(
|
||||
|
@ -190,7 +192,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
// Get the OfflineMangaModel that was clicked
|
||||
val item = adapter.getItem(position) as OfflineMangaModel
|
||||
val type: MediaType =
|
||||
if (downloadManager.mangaDownloadedTypes.any { it.title == item.title }) {
|
||||
if (downloadManager.mangaDownloadedTypes.any { it.titleName == item.title }) {
|
||||
MediaType.MANGA
|
||||
} else {
|
||||
MediaType.NOVEL
|
||||
|
@ -278,19 +280,19 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
downloads = listOf()
|
||||
downloadsJob = Job()
|
||||
CoroutineScope(Dispatchers.IO + downloadsJob).launch {
|
||||
val mangaTitles = downloadManager.mangaDownloadedTypes.map { it.title }.distinct()
|
||||
val mangaTitles = downloadManager.mangaDownloadedTypes.map { it.titleName }.distinct()
|
||||
val newMangaDownloads = mutableListOf<OfflineMangaModel>()
|
||||
for (title in mangaTitles) {
|
||||
val tDownloads = downloadManager.mangaDownloadedTypes.filter { it.title == title }
|
||||
val tDownloads = downloadManager.mangaDownloadedTypes.filter { it.titleName == title }
|
||||
val download = tDownloads.first()
|
||||
val offlineMangaModel = loadOfflineMangaModel(download)
|
||||
newMangaDownloads += offlineMangaModel
|
||||
}
|
||||
downloads = newMangaDownloads
|
||||
val novelTitles = downloadManager.novelDownloadedTypes.map { it.title }.distinct()
|
||||
val novelTitles = downloadManager.novelDownloadedTypes.map { it.titleName }.distinct()
|
||||
val newNovelDownloads = mutableListOf<OfflineMangaModel>()
|
||||
for (title in novelTitles) {
|
||||
val tDownloads = downloadManager.novelDownloadedTypes.filter { it.title == title }
|
||||
val tDownloads = downloadManager.novelDownloadedTypes.filter { it.titleName == title }
|
||||
val download = tDownloads.first()
|
||||
val offlineMangaModel = loadOfflineMangaModel(download)
|
||||
newNovelDownloads += offlineMangaModel
|
||||
|
@ -315,7 +317,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
return try {
|
||||
val directory = getSubDirectory(
|
||||
context ?: currContext()!!, downloadedType.type,
|
||||
false, downloadedType.title
|
||||
false, downloadedType.titleName
|
||||
)
|
||||
val gson = GsonBuilder()
|
||||
.registerTypeAdapter(SChapter::class.java, InstanceCreator<SChapter> {
|
||||
|
@ -323,7 +325,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
})
|
||||
.create()
|
||||
val media = directory?.findFile("media.json")
|
||||
?: return null
|
||||
?: return DownloadCompat.loadMediaCompat(downloadedType)
|
||||
val mediaJson =
|
||||
media.openInputStream(context ?: currContext()!!)?.bufferedReader().use {
|
||||
it?.readText()
|
||||
|
@ -343,7 +345,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
try {
|
||||
val directory = getSubDirectory(
|
||||
context ?: currContext()!!, downloadedType.type,
|
||||
false, downloadedType.title
|
||||
false, downloadedType.titleName
|
||||
)
|
||||
val mediaModel = getMedia(downloadedType)!!
|
||||
val cover = directory?.findFile("cover.jpg")
|
||||
|
@ -375,6 +377,9 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
coverUri,
|
||||
bannerUri
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
return try {
|
||||
loadOfflineMangaModelCompat(downloadedType)
|
||||
} catch (e: Exception) {
|
||||
Logger.log("Error loading media.json: ${e.message}")
|
||||
Logger.log(e)
|
||||
|
@ -393,6 +398,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface OfflineMangaSearchListener {
|
||||
|
|
|
@ -12,7 +12,17 @@ import androidx.annotation.OptIn
|
|||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.database.StandaloneDatabaseProvider
|
||||
import androidx.media3.datasource.DataSource
|
||||
import androidx.media3.datasource.HttpDataSource
|
||||
import androidx.media3.datasource.cache.NoOpCacheEvictor
|
||||
import androidx.media3.datasource.cache.SimpleCache
|
||||
import androidx.media3.datasource.okhttp.OkHttpDataSource
|
||||
import androidx.media3.exoplayer.offline.Download
|
||||
import androidx.media3.exoplayer.offline.DownloadManager
|
||||
import androidx.media3.exoplayer.scheduler.Requirements
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.defaultHeaders
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.anime.AnimeDownloaderService
|
||||
|
@ -22,8 +32,12 @@ import ani.dantotsu.media.MediaType
|
|||
import ani.dantotsu.parsers.Subtitle
|
||||
import ani.dantotsu.parsers.Video
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
@SuppressLint("UnsafeOptInUsageError")
|
||||
object Helper {
|
||||
|
@ -104,4 +118,92 @@ object Helper {
|
|||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
@UnstableApi
|
||||
@Deprecated("exoplayer download manager is no longer used")
|
||||
fun downloadManager(context: Context): DownloadManager {
|
||||
return download ?: let {
|
||||
val database = Injekt.get<StandaloneDatabaseProvider>()
|
||||
val downloadDirectory = File(getDownloadDirectory(context), DOWNLOAD_CONTENT_DIRECTORY)
|
||||
val dataSourceFactory = DataSource.Factory {
|
||||
//val dataSource: HttpDataSource = OkHttpDataSource.Factory(okHttpClient).createDataSource()
|
||||
val networkHelper = Injekt.get<NetworkHelper>()
|
||||
val okHttpClient = networkHelper.client
|
||||
val dataSource: HttpDataSource =
|
||||
OkHttpDataSource.Factory(okHttpClient).createDataSource()
|
||||
defaultHeaders.forEach {
|
||||
dataSource.setRequestProperty(it.key, it.value)
|
||||
}
|
||||
dataSource
|
||||
}
|
||||
val threadPoolSize = Runtime.getRuntime().availableProcessors()
|
||||
val executorService = Executors.newFixedThreadPool(threadPoolSize)
|
||||
val downloadManager = DownloadManager(
|
||||
context,
|
||||
database,
|
||||
getSimpleCache(context),
|
||||
dataSourceFactory,
|
||||
executorService
|
||||
).apply {
|
||||
requirements =
|
||||
Requirements(Requirements.NETWORK or Requirements.DEVICE_STORAGE_NOT_LOW)
|
||||
maxParallelDownloads = 3
|
||||
}
|
||||
downloadManager.addListener( //for testing
|
||||
object : DownloadManager.Listener {
|
||||
override fun onDownloadChanged(
|
||||
downloadManager: DownloadManager,
|
||||
download: Download,
|
||||
finalException: Exception?
|
||||
) {
|
||||
if (download.state == Download.STATE_COMPLETED) {
|
||||
Logger.log("Download Completed")
|
||||
} else if (download.state == Download.STATE_FAILED) {
|
||||
Logger.log("Download Failed")
|
||||
} else if (download.state == Download.STATE_STOPPED) {
|
||||
Logger.log("Download Stopped")
|
||||
} else if (download.state == Download.STATE_QUEUED) {
|
||||
Logger.log("Download Queued")
|
||||
} else if (download.state == Download.STATE_DOWNLOADING) {
|
||||
Logger.log("Download Downloading")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
downloadManager
|
||||
}
|
||||
}
|
||||
@Deprecated("exoplayer download manager is no longer used")
|
||||
@OptIn(UnstableApi::class)
|
||||
fun getSimpleCache(context: Context): SimpleCache {
|
||||
return if (simpleCache == null) {
|
||||
val downloadDirectory = File(getDownloadDirectory(context), DOWNLOAD_CONTENT_DIRECTORY)
|
||||
val database = Injekt.get<StandaloneDatabaseProvider>()
|
||||
simpleCache = SimpleCache(downloadDirectory, NoOpCacheEvictor(), database)
|
||||
simpleCache!!
|
||||
} else {
|
||||
simpleCache!!
|
||||
}
|
||||
}
|
||||
@Synchronized
|
||||
@Deprecated("exoplayer download manager is no longer used")
|
||||
private fun getDownloadDirectory(context: Context): File {
|
||||
if (downloadDirectory == null) {
|
||||
downloadDirectory = context.getExternalFilesDir(null)
|
||||
if (downloadDirectory == null) {
|
||||
downloadDirectory = context.filesDir
|
||||
}
|
||||
}
|
||||
return downloadDirectory!!
|
||||
}
|
||||
@Deprecated("exoplayer download manager is no longer used")
|
||||
private var download: DownloadManager? = null
|
||||
@Deprecated("exoplayer download manager is no longer used")
|
||||
private const val DOWNLOAD_CONTENT_DIRECTORY = "Anime_Downloads"
|
||||
@Deprecated("exoplayer download manager is no longer used")
|
||||
private var simpleCache: SimpleCache? = null
|
||||
@Deprecated("exoplayer download manager is no longer used")
|
||||
private var downloadDirectory: File? = null
|
||||
}
|
|
@ -55,8 +55,8 @@ class SubtitleDownloader {
|
|||
context,
|
||||
downloadedType.type,
|
||||
false,
|
||||
downloadedType.title,
|
||||
downloadedType.chapter
|
||||
downloadedType.titleName,
|
||||
downloadedType.chapterName
|
||||
) ?: throw Exception("Could not create directory")
|
||||
val type = loadSubtitleType(url)
|
||||
directory.findFile("subtitle.${type}")?.delete()
|
||||
|
|
|
@ -553,8 +553,8 @@ class AnimeWatchFragment : Fragment() {
|
|||
episodeAdapter.updateType(style ?: PrefManager.getVal(PrefName.AnimeDefaultView))
|
||||
episodeAdapter.notifyItemRangeInserted(0, arr.size)
|
||||
for (download in downloadManager.animeDownloadedTypes) {
|
||||
if (media.compareName(download.title)) {
|
||||
episodeAdapter.stopDownload(download.chapter)
|
||||
if (media.compareName(download.titleName)) {
|
||||
episodeAdapter.stopDownload(download.chapterName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,6 +111,7 @@ import ani.dantotsu.connections.updateProgress
|
|||
import ani.dantotsu.databinding.ActivityExoplayerBinding
|
||||
import ani.dantotsu.defaultHeaders
|
||||
import ani.dantotsu.download.DownloadsManager.Companion.getSubDirectory
|
||||
import ani.dantotsu.download.video.Helper
|
||||
import ani.dantotsu.dp
|
||||
import ani.dantotsu.getCurrentBrightnessValue
|
||||
import ani.dantotsu.hideSystemBars
|
||||
|
@ -1481,8 +1482,20 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
val downloadedMediaItem = if (ext.server.offline) {
|
||||
val titleName = ext.server.name.split("/").first()
|
||||
val episodeName = ext.server.name.split("/").last()
|
||||
downloadId = PrefManager.getAnimeDownloadPreferences()
|
||||
.getString("$titleName - $episodeName", null) ?:
|
||||
PrefManager.getAnimeDownloadPreferences()
|
||||
.getString(ext.server.name, null)
|
||||
val exoItem = if (downloadId != null) {
|
||||
Helper.downloadManager(this)
|
||||
.downloadIndex.getDownload(downloadId!!)?.request?.toMediaItem()
|
||||
} else null
|
||||
if (exoItem != null) {
|
||||
exoItem
|
||||
} else {
|
||||
|
||||
val directory = getSubDirectory(this, MediaType.ANIME, false, titleName, episodeName)
|
||||
val directory =
|
||||
getSubDirectory(this, MediaType.ANIME, false, titleName, episodeName)
|
||||
if (directory != null) {
|
||||
val files = directory.listFiles()
|
||||
println(files)
|
||||
|
@ -1500,7 +1513,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
snackString("Directory not found")
|
||||
null
|
||||
}
|
||||
|
||||
}
|
||||
} else null
|
||||
|
||||
mediaItem = if (downloadedMediaItem == null) {
|
||||
|
|
|
@ -194,8 +194,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
)
|
||||
|
||||
for (download in downloadManager.mangaDownloadedTypes) {
|
||||
if (media.compareName(download.title)) {
|
||||
chapterAdapter.stopDownload(download.chapter)
|
||||
if (media.compareName(download.titleName)) {
|
||||
chapterAdapter.stopDownload(download.chapterName)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ package ani.dantotsu.parsers
|
|||
|
||||
import android.app.Application
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.download.DownloadCompat.Companion.loadEpisodesCompat
|
||||
import ani.dantotsu.download.DownloadCompat.Companion.loadSubtitleCompat
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.DownloadsManager.Companion.getSubDirectory
|
||||
import ani.dantotsu.download.anime.AnimeDownloaderService.AnimeDownloadTask.Companion.getTaskName
|
||||
|
@ -53,8 +55,12 @@ class OfflineAnimeParser : AnimeParser() {
|
|||
episodes.add(episode)
|
||||
}
|
||||
}
|
||||
return if (episodes.isNotEmpty()) {
|
||||
episodes.sortBy { MediaNameAdapter.findEpisodeNumber(it.number) }
|
||||
return episodes
|
||||
episodes
|
||||
} else {
|
||||
loadEpisodesCompat(animeLink, extra, sAnime)
|
||||
}
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
|
@ -75,14 +81,16 @@ class OfflineAnimeParser : AnimeParser() {
|
|||
|
||||
|
||||
override suspend fun search(query: String): List<ShowResponse> {
|
||||
val titles = downloadManager.animeDownloadedTypes.map { it.title }.distinct()
|
||||
val returnTitles: MutableList<String> = mutableListOf()
|
||||
val titles = downloadManager.animeDownloadedTypes.map { it.titleName }.distinct()
|
||||
val returnTitlesPair: MutableList<Pair<String, Int>> = mutableListOf()
|
||||
for (title in titles) {
|
||||
Logger.log("Comparing $title to $query")
|
||||
if (FuzzySearch.ratio(title.lowercase(), query.lowercase()) > 80) {
|
||||
returnTitles.add(title)
|
||||
val score = FuzzySearch.ratio(title.lowercase(), query.lowercase())
|
||||
if (score > 80) {
|
||||
returnTitlesPair.add(Pair(title, score))
|
||||
}
|
||||
}
|
||||
val returnTitles = returnTitlesPair.sortedByDescending { it.second }.map { it.first }
|
||||
val returnList: MutableList<ShowResponse> = mutableListOf()
|
||||
for (title in returnTitles) {
|
||||
returnList.add(ShowResponse(title, title, title))
|
||||
|
@ -148,6 +156,7 @@ class OfflineVideoExtractor(private val videoServer: VideoServer) : VideoExtract
|
|||
)
|
||||
}
|
||||
}
|
||||
loadSubtitleCompat(title, episode)?.let { return it }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package ani.dantotsu.parsers
|
||||
|
||||
import android.app.Application
|
||||
import ani.dantotsu.download.DownloadCompat.Companion.loadChaptersCompat
|
||||
import ani.dantotsu.download.DownloadCompat.Companion.loadImagesCompat
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.DownloadsManager.Companion.getSubDirectory
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
|
@ -41,8 +43,12 @@ class OfflineMangaParser : MangaParser() {
|
|||
chapters.add(chapter)
|
||||
}
|
||||
}
|
||||
return if (chapters.isNotEmpty()) {
|
||||
chapters.sortBy { MediaNameAdapter.findChapterNumber(it.number) }
|
||||
return chapters
|
||||
chapters
|
||||
} else {
|
||||
loadChaptersCompat(mangaLink, extra, sManga)
|
||||
}
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
|
@ -60,26 +66,32 @@ class OfflineMangaParser : MangaParser() {
|
|||
images.add(image)
|
||||
}
|
||||
}
|
||||
for (image in images) {
|
||||
Logger.log("imageNumber: ${image.url.url}")
|
||||
}
|
||||
return if (images.isNotEmpty()) {
|
||||
images.sortBy { image ->
|
||||
val matchResult = imageNumberRegex.find(image.url.url)
|
||||
matchResult?.groups?.get(1)?.value?.toIntOrNull() ?: Int.MAX_VALUE
|
||||
}
|
||||
for (image in images) {
|
||||
Logger.log("imageNumber: ${image.url.url}")
|
||||
images
|
||||
} else {
|
||||
loadImagesCompat(chapterLink, sChapter)
|
||||
}
|
||||
return images
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<ShowResponse> {
|
||||
val titles = downloadManager.mangaDownloadedTypes.map { it.title }.distinct()
|
||||
val returnTitles: MutableList<String> = mutableListOf()
|
||||
val titles = downloadManager.mangaDownloadedTypes.map { it.titleName }.distinct()
|
||||
val returnTitlesPair: MutableList<Pair<String, Int>> = mutableListOf()
|
||||
for (title in titles) {
|
||||
if (FuzzySearch.ratio(title.lowercase(), query.lowercase()) > 80) {
|
||||
returnTitles.add(title)
|
||||
val score = FuzzySearch.ratio(title.lowercase(), query.lowercase())
|
||||
if (score > 80) {
|
||||
returnTitlesPair.add(Pair(title, score))
|
||||
}
|
||||
}
|
||||
val returnTitles = returnTitlesPair.sortedByDescending { it.second }.map { it.first }
|
||||
val returnList: MutableList<ShowResponse> = mutableListOf()
|
||||
for (title in returnTitles) {
|
||||
returnList.add(ShowResponse(title, title, title))
|
||||
|
|
|
@ -5,6 +5,7 @@ import ani.dantotsu.download.DownloadsManager
|
|||
import ani.dantotsu.download.DownloadsManager.Companion.getSubDirectory
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.util.Logger
|
||||
import me.xdrop.fuzzywuzzy.FuzzySearch
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
@ -48,13 +49,16 @@ class OfflineNovelParser : NovelParser() {
|
|||
}
|
||||
|
||||
override suspend fun search(query: String): List<ShowResponse> {
|
||||
val titles = downloadManager.novelDownloadedTypes.map { it.title }.distinct()
|
||||
val returnTitles: MutableList<String> = mutableListOf()
|
||||
val titles = downloadManager.novelDownloadedTypes.map { it.titleName }.distinct()
|
||||
val returnTitlesPair: MutableList<Pair<String, Int>> = mutableListOf()
|
||||
for (title in titles) {
|
||||
if (FuzzySearch.ratio(title.lowercase(), query.lowercase()) > 80) {
|
||||
returnTitles.add(title)
|
||||
Logger.log("Comparing $title to $query")
|
||||
val score = FuzzySearch.ratio(title.lowercase(), query.lowercase())
|
||||
if (score > 80) {
|
||||
returnTitlesPair.add(Pair(title, score))
|
||||
}
|
||||
}
|
||||
val returnTitles = returnTitlesPair.sortedByDescending { it.second }.map { it.first }
|
||||
val returnList: MutableList<ShowResponse> = mutableListOf()
|
||||
for (title in returnTitles) {
|
||||
//need to search the subdirectories for the ShowResponses
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue