diff --git a/app/src/main/java/ani/dantotsu/Functions.kt b/app/src/main/java/ani/dantotsu/Functions.kt index bf8a6059..56e8782d 100644 --- a/app/src/main/java/ani/dantotsu/Functions.kt +++ b/app/src/main/java/ani/dantotsu/Functions.kt @@ -636,6 +636,23 @@ fun ImageView.loadImage(file: FileUrl?, size: Int = 0) { } } +fun ImageView.loadImage(file: FileUrl?, width: Int = 0, height: Int = 0) { + file?.url = PrefManager.getVal(PrefName.ImageUrl).ifEmpty { file?.url ?: "" } + if (file?.url?.isNotEmpty() == true) { + tryWith { + if (file.url.startsWith("content://")) { + Glide.with(this.context).load(Uri.parse(file.url)).transition(withCrossFade()) + .override(width, height).into(this) + } else { + val glideUrl = GlideUrl(file.url) { file.headers } + Glide.with(this.context).load(glideUrl).transition(withCrossFade()).override(width, height) + .into(this) + } + } + } +} + + fun ImageView.loadLocalImage(file: File?, size: Int = 0) { if (file?.exists() == true) { tryWith { diff --git a/app/src/main/java/ani/dantotsu/addons/AddonDownloader.kt b/app/src/main/java/ani/dantotsu/addons/AddonDownloader.kt index ddd57abd..76f077c1 100644 --- a/app/src/main/java/ani/dantotsu/addons/AddonDownloader.kt +++ b/app/src/main/java/ani/dantotsu/addons/AddonDownloader.kt @@ -79,7 +79,6 @@ class AddonDownloader { activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val installerSteps = InstallerSteps(notificationManager, activity) manager.install(this) - .observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { installStep -> installerSteps.onInstallStep(installStep) {} }, diff --git a/app/src/main/java/ani/dantotsu/addons/AddonInstallReceiver.kt b/app/src/main/java/ani/dantotsu/addons/AddonInstallReceiver.kt index 117ddf49..decc4d30 100644 --- a/app/src/main/java/ani/dantotsu/addons/AddonInstallReceiver.kt +++ b/app/src/main/java/ani/dantotsu/addons/AddonInstallReceiver.kt @@ -75,7 +75,6 @@ internal class AddonInstallReceiver : BroadcastReceiver() { } Intent.ACTION_PACKAGE_REPLACED -> { - if (ExtensionInstallReceiver.isReplacing(intent)) return launchNow { when (type) { AddonType.DOWNLOAD -> { diff --git a/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt b/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt index 222bdcbb..b97c3b34 100644 --- a/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt +++ b/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt @@ -369,7 +369,7 @@ class DownloadsManager(private val context: Context) { } private const val RESERVED_CHARS = "|\\?*<\":>+[]/'" -private fun String?.findValidName(): String { +fun String?.findValidName(): String { return this?.filterNot { RESERVED_CHARS.contains(it) } ?: "" } diff --git a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt index 3a3216c1..ea63bcd8 100644 --- a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt +++ b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt @@ -36,6 +36,7 @@ import ani.dantotsu.download.DownloadCompat.Companion.loadOfflineAnimeModelCompa import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.DownloadsManager.Companion.compareName +import ani.dantotsu.download.findValidName import ani.dantotsu.initActivity import ani.dantotsu.media.Media import ani.dantotsu.media.MediaDetailsActivity @@ -289,7 +290,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener { } downloadsJob = Job() CoroutineScope(Dispatchers.IO + downloadsJob).launch { - val animeTitles = downloadManager.animeDownloadedTypes.map { it.titleName }.distinct() + val animeTitles = downloadManager.animeDownloadedTypes.map { it.titleName.findValidName() }.distinct() val newAnimeDownloads = mutableListOf() for (title in animeTitles) { val tDownloads = downloadManager.animeDownloadedTypes.filter { it.titleName == title } @@ -365,6 +366,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener { val bannerUri: Uri? = if (banner?.exists() == true) { banner.uri } else null + if (coverUri == null && bannerUri == null) throw Exception("No cover or banner found, probably compat") val title = mediaModel.mainName() val score = ((if (mediaModel.userScore == 0) (mediaModel.meanScore ?: 0) else mediaModel.userScore) / 10.0).toString() diff --git a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt index f368a77a..3ee64ee4 100644 --- a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt +++ b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt @@ -34,6 +34,7 @@ import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.DownloadsManager.Companion.compareName import ani.dantotsu.download.DownloadsManager.Companion.getSubDirectory +import ani.dantotsu.download.findValidName import ani.dantotsu.initActivity import ani.dantotsu.media.Media import ani.dantotsu.media.MediaDetailsActivity @@ -280,7 +281,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener { downloads = listOf() downloadsJob = Job() CoroutineScope(Dispatchers.IO + downloadsJob).launch { - val mangaTitles = downloadManager.mangaDownloadedTypes.map { it.titleName }.distinct() + val mangaTitles = downloadManager.mangaDownloadedTypes.map { it.titleName.findValidName() }.distinct() val newMangaDownloads = mutableListOf() for (title in mangaTitles) { val tDownloads = downloadManager.mangaDownloadedTypes.filter { it.titleName == title } @@ -356,6 +357,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener { val bannerUri: Uri? = if (banner?.exists() == true) { banner.uri } else null + if (coverUri == null && bannerUri == null) throw Exception("No cover or banner found, probably compat") val title = mediaModel.mainName() val score = ((if (mediaModel.userScore == 0) (mediaModel.meanScore ?: 0) else mediaModel.userScore) / 10.0).toString() diff --git a/app/src/main/java/ani/dantotsu/media/MediaNameAdapter.kt b/app/src/main/java/ani/dantotsu/media/MediaNameAdapter.kt index 07d151a0..a28bc018 100644 --- a/app/src/main/java/ani/dantotsu/media/MediaNameAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/MediaNameAdapter.kt @@ -70,7 +70,7 @@ object MediaNameAdapter { return if (seasonMatcher.find()) { seasonMatcher.group(2)?.toInt() } else { - null + text.toIntOrNull() } } @@ -93,7 +93,7 @@ object MediaNameAdapter { } } } else { - null + text.toFloatOrNull() } } @@ -139,7 +139,7 @@ object MediaNameAdapter { if (failedChapterNumberMatcher.find()) { failedChapterNumberMatcher.group(1)?.toFloat() } else { - null + text.toFloatOrNull() } } } diff --git a/app/src/main/java/ani/dantotsu/media/SearchAdapter.kt b/app/src/main/java/ani/dantotsu/media/SearchAdapter.kt index 90778272..a47a495b 100644 --- a/app/src/main/java/ani/dantotsu/media/SearchAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/SearchAdapter.kt @@ -305,14 +305,12 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri private fun fadeInAnimation(): Animation { return AlphaAnimation(0f, 1f).apply { duration = 150 - fillAfter = true } } private fun fadeOutAnimation(): Animation { return AlphaAnimation(1f, 0f).apply { duration = 150 - fillAfter = true } } diff --git a/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt b/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt index 7f4e77b4..ff861dbe 100644 --- a/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt @@ -121,7 +121,6 @@ class CommentsFragment : Fragment() { } } } else { - toast("Not logged in") activity.binding.commentMessageContainer.visibility = View.GONE } diff --git a/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt b/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt index 0b614564..c95328f6 100644 --- a/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt @@ -117,9 +117,10 @@ class NovelReadFragment : Fragment(), context ?: currContext()!!, MediaType.NOVEL, false, + media.mainName(), novel.name ) - val file = directory?.findFile(novel.name) + val file = directory?.findFile("0.epub") if (file?.exists() == false) return false val fileUri = file?.uri ?: return false val intent = Intent(context, NovelReaderActivity::class.java).apply { diff --git a/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt b/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt index 1f68b224..bd723319 100644 --- a/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt @@ -8,6 +8,7 @@ import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import ani.dantotsu.R import ani.dantotsu.databinding.ItemNovelResponseBinding +import ani.dantotsu.loadImage import ani.dantotsu.parsers.ShowResponse import ani.dantotsu.setAnimation import ani.dantotsu.snackString @@ -37,10 +38,7 @@ class NovelResponseAdapter( val binding = holder.binding val novel = list[position] setAnimation(fragment.requireContext(), holder.binding.root) - - val cover = GlideUrl(novel.coverUrl.url) { novel.coverUrl.headers } - Glide.with(binding.itemEpisodeImage).load(cover).override(400, 0) - .into(binding.itemEpisodeImage) + binding.itemEpisodeImage.loadImage(novel.coverUrl, 400, 0) val typedValue = TypedValue() fragment.requireContext().theme?.resolveAttribute( diff --git a/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt b/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt index e35e8a8c..85d1af90 100644 --- a/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt +++ b/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt @@ -55,12 +55,11 @@ class OfflineAnimeParser : AnimeParser() { episodes.add(episode) } } - return if (episodes.isNotEmpty()) { - episodes.sortBy { MediaNameAdapter.findEpisodeNumber(it.number) } - episodes - } else { - loadEpisodesCompat(animeLink, extra, sAnime) - } + //episodes.sortBy { MediaNameAdapter.findEpisodeNumber(it.number) } + episodes.addAll(loadEpisodesCompat(animeLink, extra, sAnime)) + //filter those with the same name + return episodes.distinctBy { it.number } + .sortedBy { MediaNameAdapter.findEpisodeNumber(it.number) } } return emptyList() } diff --git a/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt b/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt index b943a2fa..f0c1237f 100644 --- a/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt +++ b/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt @@ -43,12 +43,9 @@ class OfflineMangaParser : MangaParser() { chapters.add(chapter) } } - return if (chapters.isNotEmpty()) { - chapters.sortBy { MediaNameAdapter.findChapterNumber(it.number) } - chapters - } else { - loadChaptersCompat(mangaLink, extra, sManga) - } + chapters.addAll(loadChaptersCompat(mangaLink, extra, sManga)) + return chapters.distinctBy { it.number } + .sortedBy { MediaNameAdapter.findChapterNumber(it.number) } } return emptyList() } diff --git a/app/src/main/java/ani/dantotsu/parsers/OfflineNovelParser.kt b/app/src/main/java/ani/dantotsu/parsers/OfflineNovelParser.kt index 8f0fa2d1..7a3535e0 100644 --- a/app/src/main/java/ani/dantotsu/parsers/OfflineNovelParser.kt +++ b/app/src/main/java/ani/dantotsu/parsers/OfflineNovelParser.kt @@ -73,7 +73,7 @@ class OfflineNovelParser : NovelParser() { } val cover = directory?.findFile("cover.jpg")?.uri.toString() names.forEach { - returnList.add(ShowResponse(it, it, cover)) + returnList.add(ShowResponse(it, query, cover)) } } return returnList diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/installer/PackageInstallerInstaller.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/installer/PackageInstallerInstaller.kt index 5e7be9ef..a76b68d9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/installer/PackageInstallerInstaller.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/installer/PackageInstallerInstaller.kt @@ -10,7 +10,9 @@ import android.content.pm.PackageInstaller import android.os.Build import androidx.core.content.ContextCompat import androidx.core.content.IntentSanitizer +import ani.dantotsu.R import ani.dantotsu.snackString +import ani.dantotsu.toast import ani.dantotsu.util.Logger import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.util.lang.use @@ -55,7 +57,16 @@ class PackageInstallerInstaller(private val service: Service) : Installer(servic } PackageInstaller.STATUS_SUCCESS -> continueQueue(InstallStep.Installed) - else -> continueQueue(InstallStep.Error) + PackageInstaller.STATUS_FAILURE_CONFLICT -> { + Logger.log("Failed to install extension due to conflict") + toast(context.getString(R.string.failed_ext_install_conflict)) + continueQueue(InstallStep.Error) + } + else -> { + Logger.log("Fatal error for $intent") + Logger.log("Status: ${intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -1)}") + continueQueue(InstallStep.Error) + } } } } diff --git a/app/src/main/res/layout/item_search_header.xml b/app/src/main/res/layout/item_search_header.xml index 0274d224..dfd6083c 100644 --- a/app/src/main/res/layout/item_search_header.xml +++ b/app/src/main/res/layout/item_search_header.xml @@ -111,7 +111,7 @@ android:layout_gravity="center" android:drawablePadding="4dp" android:fontFamily="@font/poppins_bold" - android:text="Image" + android:text="@string/image" android:textColor="?attr/colorPrimary" app:drawableStartCompat="@drawable/ic_round_search_24" app:drawableTint="?attr/colorPrimary" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fab4b7d1..3e00305c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -956,4 +956,6 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc Update Addon Install Addon Download addon not found + Image + Failed to install extension due to conflict