From 37ec165319b21318d14c345c293a90e3416169a1 Mon Sep 17 00:00:00 2001 From: TwistedUmbrellaX Date: Thu, 14 Mar 2024 09:23:30 -0400 Subject: [PATCH] chore: lint performance optimization This includes shadowed variables, unnecessary parameters, layouts with string literals, items that cause performance bottlenecks, and the merge of extension types into only the necessary separate classes. --- app/src/main/AndroidManifest.xml | 18 +- app/src/main/java/ani/dantotsu/App.kt | 2 +- .../main/java/ani/dantotsu/MainActivity.kt | 12 +- app/src/main/java/ani/dantotsu/Network.kt | 3 +- .../connections/anilist/AnilistQueries.kt | 5 +- .../connections/anilist/AnilistViewModel.kt | 12 +- .../dantotsu/connections/discord/Discord.kt | 4 +- .../connections/discord/DiscordService.kt | 28 +- .../ani/dantotsu/connections/discord/Login.kt | 2 +- .../java/ani/dantotsu/connections/mal/MAL.kt | 5 +- .../ani/dantotsu/download/DownloadsManager.kt | 226 +++++---- .../download/anime/AnimeDownloaderService.kt | 9 +- .../download/anime/OfflineAnimeFragment.kt | 18 +- .../download/manga/MangaDownloaderService.kt | 8 +- .../download/manga/OfflineMangaFragment.kt | 21 +- .../download/novel/NovelDownloaderService.kt | 5 +- .../ani/dantotsu/download/video/Helper.kt | 29 +- .../ani/dantotsu/home/AnimePageAdapter.kt | 3 +- .../ani/dantotsu/home/MangaPageAdapter.kt | 4 +- .../ani/dantotsu/media/CalendarActivity.kt | 8 +- .../dantotsu/media/MediaDetailsActivity.kt | 9 +- .../dantotsu/media/MediaDetailsViewModel.kt | 24 +- .../main/java/ani/dantotsu/media/MediaType.kt | 26 ++ .../media/SourceSearchDialogFragment.kt | 2 +- .../ani/dantotsu/media/SubtitleDownloader.kt | 4 +- .../dantotsu/media/anime/AnimeNameAdapter.kt | 4 +- .../media/anime/AnimeWatchFragment.kt | 11 +- .../dantotsu/media/anime/EpisodeAdapters.kt | 6 +- .../ani/dantotsu/media/anime/ExoplayerView.kt | 149 ++++-- .../dantotsu/media/comments/CommentItem.kt | 6 +- .../ani/dantotsu/media/manga/MangaCache.kt | 6 +- .../dantotsu/media/manga/MangaNameAdapter.kt | 4 +- .../dantotsu/media/manga/MangaReadFragment.kt | 10 +- .../manga/mangareader/BaseImageAdapter.kt | 13 +- .../manga/mangareader/MangaReaderActivity.kt | 67 ++- .../dantotsu/media/novel/NovelReadFragment.kt | 8 +- .../ani/dantotsu/media/user/ListActivity.kt | 8 +- .../others/AndroidBug5497Workaround.kt | 2 +- .../ani/dantotsu/others/ImageViewDialog.kt | 6 +- .../ani/dantotsu/others/OutlineTextView.kt | 10 +- .../dantotsu/others/webview/CookieCatcher.kt | 6 +- .../ani/dantotsu/parsers/AniyomiAdapter.kt | 30 +- .../dantotsu/parsers/OfflineAnimeParser.kt | 11 +- ...eiver.kt => NovelExtensionFileObserver.kt} | 1 - .../parsers/novel/NovelExtensionInstaller.kt | 3 +- .../parsers/novel/NovelExtensionLoader.kt | 9 +- .../ani/dantotsu/profile/ProfileFragment.kt | 3 +- .../ani/dantotsu/profile/StatsFragment.kt | 11 +- .../dantotsu/profile/activity/FeedActivity.kt | 2 +- .../profile/activity/NotificationActivity.kt | 2 +- .../ani/dantotsu/settings/SettingsActivity.kt | 46 +- .../settings/SettingsDialogFragment.kt | 7 +- .../settings/paging/NovelPagingSource.kt | 10 +- .../java/ani/dantotsu/util/AniMarkdown.kt | 8 +- .../CurrentlyAiringRemoteViewsFactory.kt | 3 +- .../CurrentlyAiringRemoteViewsService.kt | 2 +- .../base/ExtensionInstallerPreference.kt | 2 +- .../tachiyomi/animesource/AnimeSource.kt | 3 +- .../extension/anime/AnimeExtensionManager.kt | 20 +- .../anime/api/AnimeExtensionGithubApi.kt | 6 +- .../extension/anime/model/AnimeLoadResult.kt | 2 +- .../util/AnimeExtensionInstallActivity.kt | 81 ---- .../util/AnimeExtensionInstallReceiver.kt | 132 ------ .../util/AnimeExtensionInstallService.kt | 94 ---- .../anime/util/AnimeExtensionInstaller.kt | 273 ----------- .../anime/util/AnimeExtensionLoader.kt | 244 ---------- .../Installer.kt} | 67 ++- .../PackageInstallerInstaller.kt} | 25 +- .../extension/manga/MangaExtensionManager.kt | 18 +- .../manga/api/MangaExtensionGithubApi.kt | 6 +- .../manga/installer/InstallerManga.kt | 170 ------- .../PackageInstallerInstallerManga.kt | 126 ------ .../extension/manga/model/MangaLoadResult.kt | 2 +- .../util/MangaExtensionInstallReceiver.kt | 132 ------ .../manga/util/MangaExtensionLoader.kt | 240 ---------- .../ExtensionInstallActivity.kt} | 60 ++- .../util/ExtensionInstallReceiver.kt | 205 +++++++++ .../ExtensionInstallService.kt} | 29 +- .../ExtensionInstaller.kt} | 113 ++++- .../extension/util/ExtensionLoader.kt | 427 ++++++++++++++++++ .../eu/kanade/tachiyomi/network/Requests.kt | 3 +- .../source/anime/AndroidAnimeSourceManager.kt | 2 +- .../source/manga/AndroidMangaSourceManager.kt | 2 +- .../tachiyomi/util/system/IntentExtensions.kt | 13 +- .../tachiyomi/util/system/LocaleHelper.kt | 3 +- .../domain/source/anime/model/Pin.kt | 6 +- .../local/entries/anime/LocalAnimeSource.kt | 6 +- .../local/entries/manga/LocalMangaSource.kt | 6 +- .../source/local/filter/anime/AnimeOrderBy.kt | 7 +- .../source/local/filter/manga/MangaOrderBy.kt | 7 +- .../res/layout/activity_player_settings.xml | 4 +- .../res/layout/activity_reader_settings.xml | 6 +- ...om_sheet_current_novel_reader_settings.xml | 4 +- .../res/layout/currently_airing_widget.xml | 13 +- .../main/res/layout/custom_dialog_layout.xml | 6 +- app/src/main/res/layout/dialog_edittext.xml | 4 +- app/src/main/res/layout/dialog_layout.xml | 10 +- app/src/main/res/layout/dialog_user_agent.xml | 2 +- app/src/main/res/layout/fragment_home.xml | 3 +- app/src/main/res/layout/fragment_offline.xml | 4 +- .../main/res/layout/fragment_offline_page.xml | 2 +- app/src/main/res/layout/item_anime_page.xml | 3 +- app/src/main/res/layout/item_anime_watch.xml | 12 +- app/src/main/res/layout/item_chapter_list.xml | 6 +- app/src/main/res/layout/item_extension.xml | 20 +- .../main/res/layout/item_extension_all.xml | 14 +- app/src/main/res/layout/item_manga_page.xml | 3 +- app/src/main/res/values/strings.xml | 34 +- .../xml-v31/currently_airing_widget_info.xml | 14 + .../res/xml/currently_airing_widget_info.xml | 3 - build.gradle | 2 +- 111 files changed, 1561 insertions(+), 2091 deletions(-) create mode 100644 app/src/main/java/ani/dantotsu/media/MediaType.kt rename app/src/main/java/ani/dantotsu/parsers/novel/{NovelExtensionInstallReceiver.kt => NovelExtensionFileObserver.kt} (98%) delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallActivity.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallReceiver.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallService.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstaller.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionLoader.kt rename app/src/main/java/eu/kanade/tachiyomi/extension/{anime/installer/InstallerAnime.kt => installer/Installer.kt} (64%) rename app/src/main/java/eu/kanade/tachiyomi/extension/{anime/installer/PackageInstallerInstallerAnime.kt => installer/PackageInstallerInstaller.kt} (82%) delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/extension/manga/installer/InstallerManga.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/extension/manga/installer/PackageInstallerInstallerManga.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallReceiver.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionLoader.kt rename app/src/main/java/eu/kanade/tachiyomi/extension/{manga/util/MangaExtensionInstallActivity.kt => util/ExtensionInstallActivity.kt} (53%) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstallReceiver.kt rename app/src/main/java/eu/kanade/tachiyomi/extension/{manga/util/MangaExtensionInstallService.kt => util/ExtensionInstallService.kt} (72%) rename app/src/main/java/eu/kanade/tachiyomi/extension/{manga/util/MangaExtensionInstaller.kt => util/ExtensionInstaller.kt} (66%) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionLoader.kt create mode 100644 app/src/main/res/xml-v31/currently_airing_widget_info.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7d5f8fb9..7cc2e732 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,7 +19,7 @@ + android:maxSdkVersion="29" /> @@ -53,11 +53,13 @@ android:label="@string/app_name" android:largeHeap="true" android:requestLegacyExternalStorage="true" + android:enableOnBackInvokedCallback="true" android:roundIcon="${icon_placeholder_round}" android:supportsRtl="true" android:theme="@style/Theme.Dantotsu" android:usesCleartextTraffic="true" - tools:ignore="AllowBackup"> + tools:ignore="AllowBackup" + tools:targetApi="tiramisu"> @@ -300,11 +302,7 @@ - @@ -355,11 +353,7 @@ - (R.id.navbar) + val bottomNavBar = findViewById(R.id.navbar) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - val backgroundDrawable = _bottomBar.background as GradientDrawable + val backgroundDrawable = bottomNavBar.background as GradientDrawable val currentColor = backgroundDrawable.color?.defaultColor ?: 0 val semiTransparentColor = (currentColor and 0x00FFFFFF) or 0xF9000000.toInt() backgroundDrawable.setColor(semiTransparentColor) - _bottomBar.background = backgroundDrawable + bottomNavBar.background = backgroundDrawable } - _bottomBar.background = ContextCompat.getDrawable(this, R.drawable.bottom_nav_gray) + bottomNavBar.background = ContextCompat.getDrawable(this, R.drawable.bottom_nav_gray) val offset = try { val statusBarHeightId = resources.getIdentifier("status_bar_height", "dimen", "android") @@ -337,7 +337,7 @@ class MainActivity : AppCompatActivity() { startActivity(Intent(this, NoInternet::class.java)) } else { val model: AnilistHomeViewModel by viewModels() - model.genres.observe(this) { it -> + model.genres.observe(this) { if (it != null) { if (it) { val navbar = binding.includedNavbar.navbar @@ -362,7 +362,7 @@ class MainActivity : AppCompatActivity() { mainViewPager.setCurrentItem(newIndex, false) } }) - if (mainViewPager.getCurrentItem() != selectedOption) { + if (mainViewPager.currentItem != selectedOption) { navbar.selectTabAt(selectedOption) mainViewPager.post { mainViewPager.setCurrentItem( diff --git a/app/src/main/java/ani/dantotsu/Network.kt b/app/src/main/java/ani/dantotsu/Network.kt index aa71cb48..91840b3e 100644 --- a/app/src/main/java/ani/dantotsu/Network.kt +++ b/app/src/main/java/ani/dantotsu/Network.kt @@ -1,6 +1,5 @@ package ani.dantotsu -import android.content.Context import android.os.Build import androidx.fragment.app.FragmentActivity import ani.dantotsu.others.webview.CloudFlare @@ -35,7 +34,7 @@ lateinit var defaultHeaders: Map lateinit var okHttpClient: OkHttpClient lateinit var client: Requests -fun initializeNetwork(context: Context) { +fun initializeNetwork() { val networkHelper = Injekt.get() diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt index c83fd07f..b0088286 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt @@ -387,6 +387,7 @@ class AnilistQueries { returnArray.addAll(map.values) return returnArray } + @Suppress("UNCHECKED_CAST") val list = PrefManager.getNullableCustomVal( "continueAnimeList", listOf(), @@ -544,6 +545,7 @@ class AnilistQueries { returnMap["current$type"] = returnArray return } + @Suppress("UNCHECKED_CAST") val list = PrefManager.getNullableCustomVal( "continueAnimeList", listOf(), @@ -573,6 +575,7 @@ class AnilistQueries { subMap[m.id] = m } } + @Suppress("UNCHECKED_CAST") val list = PrefManager.getNullableCustomVal( "continueAnimeList", listOf(), @@ -734,7 +737,7 @@ class AnilistQueries { } sorted["All"] = all - val listSort: String = if (anime) PrefManager.getVal(PrefName.AnimeListSortOrder) + val listSort: String? = if (anime) PrefManager.getVal(PrefName.AnimeListSortOrder) else PrefManager.getVal(PrefName.MangaListSortOrder) val sort = listSort ?: sortOrder ?: options?.rowOrder for (i in sorted.keys) { diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt index 5eb28a79..a4092b91 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt @@ -112,8 +112,8 @@ class AnilistHomeViewModel : ViewModel() { suspend fun loadMain(context: FragmentActivity) { Anilist.getSavedToken() - MAL.getSavedToken(context) - Discord.getSavedToken(context) + MAL.getSavedToken() + Discord.getSavedToken() if (!BuildConfig.FLAVOR.contains("fdroid")) { if (PrefManager.getVal(PrefName.CheckUpdate)) AppUpdater.check(context) } @@ -159,7 +159,7 @@ class AnilistAnimeViewModel : ViewModel() { fun getPopular(): LiveData = animePopular suspend fun loadPopular( type: String, - search_val: String? = null, + searchVal: String? = null, genres: ArrayList? = null, sort: String = Anilist.sortBy[1], onList: Boolean = true, @@ -167,7 +167,7 @@ class AnilistAnimeViewModel : ViewModel() { animePopular.postValue( Anilist.query.search( type, - search = search_val, + search = searchVal, onList = if (onList) null else false, sort = sort, genres = genres @@ -231,7 +231,7 @@ class AnilistMangaViewModel : ViewModel() { fun getPopular(): LiveData = mangaPopular suspend fun loadPopular( type: String, - search_val: String? = null, + searchVal: String? = null, genres: ArrayList? = null, sort: String = Anilist.sortBy[1], onList: Boolean = true, @@ -239,7 +239,7 @@ class AnilistMangaViewModel : ViewModel() { mangaPopular.postValue( Anilist.query.search( type, - search = search_val, + search = searchVal, onList = if (onList) null else false, sort = sort, genres = genres diff --git a/app/src/main/java/ani/dantotsu/connections/discord/Discord.kt b/app/src/main/java/ani/dantotsu/connections/discord/Discord.kt index ea34f1bf..0a2f7b3f 100644 --- a/app/src/main/java/ani/dantotsu/connections/discord/Discord.kt +++ b/app/src/main/java/ani/dantotsu/connections/discord/Discord.kt @@ -20,14 +20,14 @@ object Discord { var avatar: String? = null - fun getSavedToken(context: Context): Boolean { + fun getSavedToken(): Boolean { token = PrefManager.getVal( PrefName.DiscordToken, null as String? ) return token != null } - fun saveToken(context: Context, token: String) { + fun saveToken(token: String) { PrefManager.setVal(PrefName.DiscordToken, token) } diff --git a/app/src/main/java/ani/dantotsu/connections/discord/DiscordService.kt b/app/src/main/java/ani/dantotsu/connections/discord/DiscordService.kt index 0a29ab60..7f2c23b0 100644 --- a/app/src/main/java/ani/dantotsu/connections/discord/DiscordService.kt +++ b/app/src/main/java/ani/dantotsu/connections/discord/DiscordService.kt @@ -5,16 +5,12 @@ import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent import android.app.Service -import android.content.ContentValues import android.content.Context import android.content.Intent import android.content.pm.PackageManager -import android.net.Uri import android.os.Build -import android.os.Environment import android.os.IBinder import android.os.PowerManager -import android.provider.MediaStore import androidx.core.app.ActivityCompat import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat @@ -37,7 +33,6 @@ import okhttp3.Response import okhttp3.WebSocket import okhttp3.WebSocketListener import java.io.File -import java.io.OutputStreamWriter class DiscordService : Service() { private var heartbeat: Int = 0 @@ -162,8 +157,8 @@ class DiscordService : Service() { inner class DiscordWebSocketListener : WebSocketListener() { - var retryAttempts = 0 - val maxRetryAttempts = 10 + private var retryAttempts = 0 + private val maxRetryAttempts = 10 override fun onOpen(webSocket: WebSocket, response: Response) { super.onOpen(webSocket, response) this@DiscordService.webSocket = webSocket @@ -232,7 +227,7 @@ class DiscordService : Service() { resume() resume = false } else { - identify(webSocket, baseContext) + identify(webSocket) log("WebSocket: Identified") } } @@ -245,13 +240,13 @@ class DiscordService : Service() { } } - fun identify(webSocket: WebSocket, context: Context) { + private fun identify(webSocket: WebSocket) { val properties = JsonObject() properties.addProperty("os", "linux") properties.addProperty("browser", "unknown") properties.addProperty("device", "unknown") val d = JsonObject() - d.addProperty("token", getToken(context)) + d.addProperty("token", getToken()) d.addProperty("intents", 0) d.add("properties", properties) val payload = JsonObject() @@ -311,7 +306,7 @@ class DiscordService : Service() { } } - fun getToken(context: Context): String { + fun getToken(): String { val token = PrefManager.getVal(PrefName.DiscordToken, null as String?) return if (token == null) { log("WebSocket: Token not found") @@ -375,10 +370,10 @@ class DiscordService : Service() { log("WebSocket: Simple Test Presence Saved") } - fun setPresence(String: String) { + fun setPresence(string: String) { log("WebSocket: Sending Presence payload") - log(String) - webSocket.send(String) + log(string) + webSocket.send(string) } fun log(string: String) { @@ -388,7 +383,7 @@ class DiscordService : Service() { fun resume() { log("Sending Resume payload") val d = JsonObject() - d.addProperty("token", getToken(baseContext)) + d.addProperty("token", getToken()) d.addProperty("session_id", sessionId) d.addProperty("seq", sequence) val json = JsonObject() @@ -404,8 +399,7 @@ class DiscordService : Service() { Thread.sleep(heartbeat.toLong()) heartbeatSend(webSocket, sequence) log("WebSocket: Heartbeat Sent") - } catch (e: InterruptedException) { - } + } catch (ignored: InterruptedException) { } } } diff --git a/app/src/main/java/ani/dantotsu/connections/discord/Login.kt b/app/src/main/java/ani/dantotsu/connections/discord/Login.kt index 676f11e2..513da55b 100644 --- a/app/src/main/java/ani/dantotsu/connections/discord/Login.kt +++ b/app/src/main/java/ani/dantotsu/connections/discord/Login.kt @@ -75,7 +75,7 @@ class Login : AppCompatActivity() { } Toast.makeText(this, "Logged in successfully", Toast.LENGTH_SHORT).show() finish() - saveToken(this, token) + saveToken(token) startMainActivity(this@Login) } diff --git a/app/src/main/java/ani/dantotsu/connections/mal/MAL.kt b/app/src/main/java/ani/dantotsu/connections/mal/MAL.kt index 9eaffdca..770d0e05 100644 --- a/app/src/main/java/ani/dantotsu/connections/mal/MAL.kt +++ b/app/src/main/java/ani/dantotsu/connections/mal/MAL.kt @@ -5,7 +5,6 @@ import android.content.Context import android.net.Uri import android.util.Base64 import androidx.browser.customtabs.CustomTabsIntent -import androidx.fragment.app.FragmentActivity import ani.dantotsu.R import ani.dantotsu.client import ani.dantotsu.currContext @@ -64,7 +63,7 @@ object MAL { } - suspend fun getSavedToken(context: FragmentActivity): Boolean { + suspend fun getSavedToken(): Boolean { return tryWithSuspend(false) { var res: ResponseToken = PrefManager.getNullableVal(PrefName.MALToken, null) @@ -77,7 +76,7 @@ object MAL { } ?: false } - fun removeSavedToken(context: Context) { + fun removeSavedToken() { token = null username = null userid = null diff --git a/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt b/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt index 0cbfa1bc..4eb7f5a3 100644 --- a/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt +++ b/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt @@ -3,6 +3,7 @@ package ani.dantotsu.download import android.content.Context import android.os.Environment import android.widget.Toast +import ani.dantotsu.media.MediaType import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import com.google.gson.Gson @@ -15,11 +16,11 @@ class DownloadsManager(private val context: Context) { private val downloadsList = loadDownloads().toMutableList() val mangaDownloadedTypes: List - get() = downloadsList.filter { it.type == DownloadedType.Type.MANGA } + get() = downloadsList.filter { it.type == MediaType.MANGA } val animeDownloadedTypes: List - get() = downloadsList.filter { it.type == DownloadedType.Type.ANIME } + get() = downloadsList.filter { it.type == MediaType.ANIME } val novelDownloadedTypes: List - get() = downloadsList.filter { it.type == DownloadedType.Type.NOVEL } + get() = downloadsList.filter { it.type == MediaType.NOVEL } private fun saveDownloads() { val jsonString = gson.toJson(downloadsList) @@ -47,14 +48,8 @@ class DownloadsManager(private val context: Context) { saveDownloads() } - fun removeMedia(title: String, type: DownloadedType.Type) { - val subDirectory = if (type == DownloadedType.Type.MANGA) { - "Manga" - } else if (type == DownloadedType.Type.ANIME) { - "Anime" - } else { - "Novel" - } + fun removeMedia(title: String, type: MediaType) { + val subDirectory = type.asText() val directory = File( context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/$subDirectory/$title" @@ -71,53 +66,45 @@ class DownloadsManager(private val context: Context) { cleanDownloads() } when (type) { - DownloadedType.Type.MANGA -> { - downloadsList.removeAll { it.title == title && it.type == DownloadedType.Type.MANGA } + MediaType.MANGA -> { + downloadsList.removeAll { it.title == title && it.type == MediaType.MANGA } } - DownloadedType.Type.ANIME -> { - downloadsList.removeAll { it.title == title && it.type == DownloadedType.Type.ANIME } + MediaType.ANIME -> { + downloadsList.removeAll { it.title == title && it.type == MediaType.ANIME } } - DownloadedType.Type.NOVEL -> { - downloadsList.removeAll { it.title == title && it.type == DownloadedType.Type.NOVEL } + MediaType.NOVEL -> { + downloadsList.removeAll { it.title == title && it.type == MediaType.NOVEL } } } saveDownloads() } private fun cleanDownloads() { - cleanDownload(DownloadedType.Type.MANGA) - cleanDownload(DownloadedType.Type.ANIME) - cleanDownload(DownloadedType.Type.NOVEL) + cleanDownload(MediaType.MANGA) + cleanDownload(MediaType.ANIME) + cleanDownload(MediaType.NOVEL) } - private fun cleanDownload(type: DownloadedType.Type) { + private fun cleanDownload(type: MediaType) { // remove all folders that are not in the downloads list - val subDirectory = if (type == DownloadedType.Type.MANGA) { - "Manga" - } else if (type == DownloadedType.Type.ANIME) { - "Anime" - } else { - "Novel" - } + val subDirectory = type.asText() val directory = File( context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/$subDirectory" ) - val downloadsSubLists = if (type == DownloadedType.Type.MANGA) { - mangaDownloadedTypes - } else if (type == DownloadedType.Type.ANIME) { - animeDownloadedTypes - } else { - novelDownloadedTypes + val downloadsSubLists = when (type) { + MediaType.MANGA -> mangaDownloadedTypes + MediaType.ANIME -> animeDownloadedTypes + else -> novelDownloadedTypes } if (directory.exists()) { val files = directory.listFiles() if (files != null) { for (file in files) { if (!downloadsSubLists.any { it.title == file.name }) { - val deleted = file.deleteRecursively() + file.deleteRecursively() } } } @@ -153,7 +140,7 @@ class DownloadsManager(private val context: Context) { return downloadsList.contains(downloadedType) } - fun queryDownload(title: String, chapter: String, type: DownloadedType.Type? = null): Boolean { + fun queryDownload(title: String, chapter: String, type: MediaType? = null): Boolean { return if (type == null) { downloadsList.any { it.title == title && it.chapter == chapter } } else { @@ -162,21 +149,25 @@ class DownloadsManager(private val context: Context) { } private fun removeDirectory(downloadedType: DownloadedType) { - val directory = if (downloadedType.type == DownloadedType.Type.MANGA) { - File( - context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), - "Dantotsu/Manga/${downloadedType.title}/${downloadedType.chapter}" - ) - } else if (downloadedType.type == DownloadedType.Type.ANIME) { - File( - context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), - "Dantotsu/Anime/${downloadedType.title}/${downloadedType.chapter}" - ) - } else { - File( - context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), - "Dantotsu/Novel/${downloadedType.title}/${downloadedType.chapter}" - ) + val directory = when (downloadedType.type) { + MediaType.MANGA -> { + File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "Dantotsu/Manga/${downloadedType.title}/${downloadedType.chapter}" + ) + } + MediaType.ANIME -> { + File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "Dantotsu/Anime/${downloadedType.title}/${downloadedType.chapter}" + ) + } + else -> { + File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "Dantotsu/Novel/${downloadedType.title}/${downloadedType.chapter}" + ) + } } // Check if the directory exists and delete it recursively @@ -193,21 +184,25 @@ class DownloadsManager(private val context: Context) { } fun exportDownloads(downloadedType: DownloadedType) { //copies to the downloads folder available to the user - val directory = if (downloadedType.type == DownloadedType.Type.MANGA) { - File( - context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), - "Dantotsu/Manga/${downloadedType.title}/${downloadedType.chapter}" - ) - } else if (downloadedType.type == DownloadedType.Type.ANIME) { - File( - context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), - "Dantotsu/Anime/${downloadedType.title}/${downloadedType.chapter}" - ) - } else { - File( - context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), - "Dantotsu/Novel/${downloadedType.title}/${downloadedType.chapter}" - ) + val directory = when (downloadedType.type) { + MediaType.MANGA -> { + File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "Dantotsu/Manga/${downloadedType.title}/${downloadedType.chapter}" + ) + } + MediaType.ANIME -> { + File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "Dantotsu/Anime/${downloadedType.title}/${downloadedType.chapter}" + ) + } + else -> { + File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "Dantotsu/Novel/${downloadedType.title}/${downloadedType.chapter}" + ) + } } val destination = File( context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), @@ -225,13 +220,17 @@ class DownloadsManager(private val context: Context) { } } - fun purgeDownloads(type: DownloadedType.Type) { - val directory = if (type == DownloadedType.Type.MANGA) { - File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/Manga") - } else if (type == DownloadedType.Type.ANIME) { - File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/Anime") - } else { - File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/Novel") + fun purgeDownloads(type: MediaType) { + val directory = when (type) { + MediaType.MANGA -> { + File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/Manga") + } + MediaType.ANIME -> { + File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/Anime") + } + else -> { + File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/Novel") + } } if (directory.exists()) { val deleted = directory.deleteRecursively() @@ -255,56 +254,53 @@ class DownloadsManager(private val context: Context) { fun getDirectory( context: Context, - type: DownloadedType.Type, + type: MediaType, title: String, chapter: String? = null ): File { - return if (type == DownloadedType.Type.MANGA) { - if (chapter != null) { - File( - context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), - "$mangaLocation/$title/$chapter" - ) - } else { - File( - context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), - "$mangaLocation/$title" - ) + return when (type) { + MediaType.MANGA -> { + if (chapter != null) { + File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "$mangaLocation/$title/$chapter" + ) + } else { + File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "$mangaLocation/$title" + ) + } } - } else if (type == DownloadedType.Type.ANIME) { - if (chapter != null) { - File( - context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), - "$animeLocation/$title/$chapter" - ) - } else { - File( - context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), - "$animeLocation/$title" - ) + MediaType.ANIME -> { + if (chapter != null) { + File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "$animeLocation/$title/$chapter" + ) + } else { + File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "$animeLocation/$title" + ) + } } - } else { - if (chapter != null) { - File( - context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), - "$novelLocation/$title/$chapter" - ) - } else { - File( - context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), - "$novelLocation/$title" - ) + else -> { + if (chapter != null) { + File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "$novelLocation/$title/$chapter" + ) + } else { + File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "$novelLocation/$title" + ) + } } } } } - } -data class DownloadedType(val title: String, val chapter: String, val type: Type) : Serializable { - enum class Type { - MANGA, - ANIME, - NOVEL - } -} +data class DownloadedType(val title: String, val chapter: String, val type: MediaType) : Serializable diff --git a/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt b/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt index 22b20dcb..fc498743 100644 --- a/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt +++ b/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt @@ -27,14 +27,15 @@ import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.video.ExoplayerDownloadService import ani.dantotsu.download.video.Helper -import ani.dantotsu.util.Logger import ani.dantotsu.media.Media +import ani.dantotsu.media.MediaType import ani.dantotsu.media.SubtitleDownloader import ani.dantotsu.media.anime.AnimeWatchFragment import ani.dantotsu.parsers.Subtitle import ani.dantotsu.parsers.Video import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import com.google.gson.GsonBuilder import com.google.gson.InstanceCreator import eu.kanade.tachiyomi.animesource.model.SAnime @@ -242,7 +243,7 @@ class AnimeDownloaderService : Service() { DownloadedType( task.title, task.episode, - DownloadedType.Type.ANIME, + MediaType.ANIME, ) ) } @@ -273,7 +274,7 @@ class AnimeDownloaderService : Service() { DownloadedType( task.title, task.episode, - DownloadedType.Type.ANIME, + MediaType.ANIME, ) ) Injekt.get().logException( @@ -302,7 +303,7 @@ class AnimeDownloaderService : Service() { DownloadedType( task.title, task.episode, - DownloadedType.Type.ANIME, + MediaType.ANIME, ) ) currentTasks.removeAll { it.getTaskName() == task.getTaskName() } 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 a081f181..64329759 100644 --- a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt +++ b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt @@ -34,15 +34,16 @@ import ani.dantotsu.currContext import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager import ani.dantotsu.initActivity -import ani.dantotsu.util.Logger import ani.dantotsu.media.Media import ani.dantotsu.media.MediaDetailsActivity +import ani.dantotsu.media.MediaType import ani.dantotsu.navBarHeight import ani.dantotsu.setSafeOnClickListener import ani.dantotsu.settings.SettingsDialogFragment import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import com.google.android.material.card.MaterialCardView import com.google.android.material.imageview.ShapeableImageView import com.google.android.material.textfield.TextInputLayout @@ -188,8 +189,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener { gridView.setOnItemLongClickListener { _, _, position, _ -> // Get the OfflineAnimeModel that was clicked val item = adapter.getItem(position) as OfflineAnimeModel - val type: DownloadedType.Type = - DownloadedType.Type.ANIME + val type: MediaType = MediaType.ANIME // Alert dialog to confirm deletion val builder = @@ -293,11 +293,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener { } private fun getMedia(downloadedType: DownloadedType): Media? { - val type = when (downloadedType.type) { - DownloadedType.Type.MANGA -> "Manga" - DownloadedType.Type.ANIME -> "Anime" - else -> "Novel" - } + val type = downloadedType.type.asText() val directory = File( currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/$type/${downloadedType.title}" @@ -327,11 +323,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener { } private fun loadOfflineAnimeModel(downloadedType: DownloadedType): OfflineAnimeModel { - val type = when (downloadedType.type) { - DownloadedType.Type.MANGA -> "Manga" - DownloadedType.Type.ANIME -> "Anime" - else -> "Novel" - } + val type = downloadedType.type.asText() val directory = File( currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/$type/${downloadedType.title}" 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 188c9dc3..9b884883 100644 --- a/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt +++ b/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt @@ -21,8 +21,8 @@ import ani.dantotsu.R import ani.dantotsu.connections.crashlytics.CrashlyticsInterface import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager -import ani.dantotsu.util.Logger import ani.dantotsu.media.Media +import ani.dantotsu.media.MediaType import ani.dantotsu.media.manga.ImageData import ani.dantotsu.media.manga.MangaReadFragment.Companion.ACTION_DOWNLOAD_FAILED import ani.dantotsu.media.manga.MangaReadFragment.Companion.ACTION_DOWNLOAD_FINISHED @@ -30,6 +30,7 @@ import ani.dantotsu.media.manga.MangaReadFragment.Companion.ACTION_DOWNLOAD_PROG import ani.dantotsu.media.manga.MangaReadFragment.Companion.ACTION_DOWNLOAD_STARTED import ani.dantotsu.media.manga.MangaReadFragment.Companion.EXTRA_CHAPTER_NUMBER import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import com.google.gson.GsonBuilder import com.google.gson.InstanceCreator import eu.kanade.tachiyomi.data.notification.Notifications.CHANNEL_DOWNLOADER_PROGRESS @@ -211,8 +212,7 @@ class MangaDownloaderService : Service() { while (bitmap == null && retryCount < task.retries) { bitmap = image.fetchAndProcessImage( image.page, - image.source, - this@MangaDownloaderService + image.source ) retryCount++ } @@ -246,7 +246,7 @@ class MangaDownloaderService : Service() { DownloadedType( task.title, task.chapter, - DownloadedType.Type.MANGA + MediaType.MANGA ) ) broadcastDownloadFinished(task.chapter) 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 045e00ed..99250edf 100644 --- a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt +++ b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt @@ -31,15 +31,16 @@ import ani.dantotsu.currContext import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager import ani.dantotsu.initActivity -import ani.dantotsu.util.Logger import ani.dantotsu.media.Media import ani.dantotsu.media.MediaDetailsActivity +import ani.dantotsu.media.MediaType import ani.dantotsu.navBarHeight import ani.dantotsu.setSafeOnClickListener import ani.dantotsu.settings.SettingsDialogFragment import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import com.google.android.material.card.MaterialCardView import com.google.android.material.imageview.ShapeableImageView import com.google.android.material.textfield.TextInputLayout @@ -179,11 +180,11 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener { gridView.setOnItemLongClickListener { _, _, position, _ -> // Get the OfflineMangaModel that was clicked val item = adapter.getItem(position) as OfflineMangaModel - val type: DownloadedType.Type = + val type: MediaType = if (downloadManager.mangaDownloadedTypes.any { it.title == item.title }) { - DownloadedType.Type.MANGA + MediaType.MANGA } else { - DownloadedType.Type.NOVEL + MediaType.NOVEL } // Alert dialog to confirm deletion val builder = @@ -289,11 +290,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener { } private fun getMedia(downloadedType: DownloadedType): Media? { - val type = when (downloadedType.type) { - DownloadedType.Type.MANGA -> "Manga" - DownloadedType.Type.ANIME -> "Anime" - else -> "Novel" - } + val type = downloadedType.type.asText() val directory = File( currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/$type/${downloadedType.title}" @@ -317,11 +314,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener { } private fun loadOfflineMangaModel(downloadedType: DownloadedType): OfflineMangaModel { - val type = when (downloadedType.type) { - DownloadedType.Type.MANGA -> "Manga" - DownloadedType.Type.ANIME -> "Anime" - else -> "Novel" - } + val type = downloadedType.type.asText() val directory = File( currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/$type/${downloadedType.title}" diff --git a/app/src/main/java/ani/dantotsu/download/novel/NovelDownloaderService.kt b/app/src/main/java/ani/dantotsu/download/novel/NovelDownloaderService.kt index 0c3575a3..9cb46d31 100644 --- a/app/src/main/java/ani/dantotsu/download/novel/NovelDownloaderService.kt +++ b/app/src/main/java/ani/dantotsu/download/novel/NovelDownloaderService.kt @@ -20,10 +20,11 @@ import ani.dantotsu.R import ani.dantotsu.connections.crashlytics.CrashlyticsInterface import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager -import ani.dantotsu.util.Logger import ani.dantotsu.media.Media +import ani.dantotsu.media.MediaType import ani.dantotsu.media.novel.NovelReadFragment import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import com.google.gson.GsonBuilder import com.google.gson.InstanceCreator import eu.kanade.tachiyomi.data.notification.Notifications @@ -335,7 +336,7 @@ class NovelDownloaderService : Service() { DownloadedType( task.title, task.chapter, - DownloadedType.Type.NOVEL + MediaType.NOVEL ) ) broadcastDownloadFinished(task.originalLink) diff --git a/app/src/main/java/ani/dantotsu/download/video/Helper.kt b/app/src/main/java/ani/dantotsu/download/video/Helper.kt index 4e82e76c..6cb688fa 100644 --- a/app/src/main/java/ani/dantotsu/download/video/Helper.kt +++ b/app/src/main/java/ani/dantotsu/download/video/Helper.kt @@ -9,7 +9,6 @@ import android.content.Intent import android.content.pm.PackageManager import android.net.Uri import android.os.Build -import android.util.Log import androidx.annotation.OptIn import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat @@ -37,6 +36,7 @@ import ani.dantotsu.download.anime.AnimeDownloaderService import ani.dantotsu.download.anime.AnimeServiceDataSingleton import ani.dantotsu.logError import ani.dantotsu.media.Media +import ani.dantotsu.media.MediaType import ani.dantotsu.okHttpClient import ani.dantotsu.parsers.Subtitle import ani.dantotsu.parsers.SubtitleType @@ -49,13 +49,14 @@ import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.File import java.io.IOException -import java.util.concurrent.* +import java.util.concurrent.Executors +@SuppressLint("UnsafeOptInUsageError") object Helper { + private var simpleCache: SimpleCache? = null - @SuppressLint("UnsafeOptInUsageError") fun downloadVideo(context: Context, video: Video, subtitle: Subtitle?) { val dataSourceFactory = DataSource.Factory { val dataSource: HttpDataSource = @@ -157,16 +158,14 @@ object Helper { 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") + when (download.state) { + Download.STATE_COMPLETED -> Logger.log("Download Completed") + Download.STATE_FAILED -> Logger.log("Download Failed") + Download.STATE_STOPPED -> Logger.log("Download Stopped") + Download.STATE_QUEUED -> Logger.log("Download Queued") + Download.STATE_DOWNLOADING -> Logger.log("Download Downloading") + Download.STATE_REMOVING -> Logger.log("Download Removing") + Download.STATE_RESTARTING -> Logger.log("Download Restarting") } } } @@ -220,7 +219,7 @@ object Helper { val downloadsManger = Injekt.get() val downloadCheck = downloadsManger - .queryDownload(title, episode, DownloadedType.Type.ANIME) + .queryDownload(title, episode, MediaType.ANIME) if (downloadCheck) { AlertDialog.Builder(context, R.style.MyPopup) @@ -243,7 +242,7 @@ object Helper { DownloadedType( title, episode, - DownloadedType.Type.ANIME + MediaType.ANIME ) ) AnimeServiceDataSingleton.downloadQueue.offer(animeDownloadTask) diff --git a/app/src/main/java/ani/dantotsu/home/AnimePageAdapter.kt b/app/src/main/java/ani/dantotsu/home/AnimePageAdapter.kt index e9252521..59d401c8 100644 --- a/app/src/main/java/ani/dantotsu/home/AnimePageAdapter.kt +++ b/app/src/main/java/ani/dantotsu/home/AnimePageAdapter.kt @@ -167,8 +167,7 @@ class AnimePageAdapter : RecyclerView.Adapter { topMargin = statusBarHeight } diff --git a/app/src/main/java/ani/dantotsu/media/MediaDetailsActivity.kt b/app/src/main/java/ani/dantotsu/media/MediaDetailsActivity.kt index a781326a..06b2a6b7 100644 --- a/app/src/main/java/ani/dantotsu/media/MediaDetailsActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/MediaDetailsActivity.kt @@ -2,7 +2,6 @@ package ani.dantotsu.media import android.animation.ObjectAnimator import android.annotation.SuppressLint -import android.app.Activity import android.content.Intent import android.graphics.Rect import android.content.res.Configuration @@ -13,9 +12,7 @@ import android.view.GestureDetector import android.view.MotionEvent import android.view.View import android.view.ViewGroup -import android.view.WindowManager import android.view.animation.AccelerateDecelerateInterpolator -import android.widget.FrameLayout import android.widget.ImageView import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity @@ -243,13 +240,13 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi @SuppressLint("ResourceType") fun total() { val text = SpannableStringBuilder().apply { - val typedValue = TypedValue() + val mediaTypedValue = TypedValue() this@MediaDetailsActivity.theme.resolveAttribute( com.google.android.material.R.attr.colorOnBackground, - typedValue, + mediaTypedValue, true ) - val white = typedValue.data + val white = mediaTypedValue.data if (media.userStatus != null) { append(if (media.anime != null) getString(R.string.watched_num) else getString(R.string.read_num)) val typedValue = TypedValue() diff --git a/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt b/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt index 650e722d..b9d005e3 100644 --- a/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt +++ b/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt @@ -52,12 +52,16 @@ class MediaDetailsViewModel : ViewModel() { it } if (isDownload) { - data.sourceIndex = if (media.anime != null) { - AnimeSources.list.size - 1 - } else if (media.format == "MANGA" || media.format == "ONE_SHOT") { - MangaSources.list.size - 1 - } else { - NovelSources.list.size - 1 + data.sourceIndex = when { + media.anime != null -> { + AnimeSources.list.size - 1 + } + media.format == "MANGA" || media.format == "ONE_SHOT" -> { + MangaSources.list.size - 1 + } + else -> { + NovelSources.list.size - 1 + } } } return data @@ -152,10 +156,10 @@ class MediaDetailsViewModel : ViewModel() { watchSources?.get(i)?.apply { if (!post && !allowsPreloading) return@apply ep.sEpisode?.let { - loadByVideoServers(link, ep.extra, it) { - if (it.videos.isNotEmpty()) { - list.add(it) - ep.extractorCallback?.invoke(it) + loadByVideoServers(link, ep.extra, it) { extractor -> + if (extractor.videos.isNotEmpty()) { + list.add(extractor) + ep.extractorCallback?.invoke(extractor) } } } diff --git a/app/src/main/java/ani/dantotsu/media/MediaType.kt b/app/src/main/java/ani/dantotsu/media/MediaType.kt new file mode 100644 index 00000000..6762d98e --- /dev/null +++ b/app/src/main/java/ani/dantotsu/media/MediaType.kt @@ -0,0 +1,26 @@ +package ani.dantotsu.media + +enum class MediaType { + ANIME, + MANGA, + NOVEL; + + fun asText(): String { + return when (this) { + ANIME -> "Anime" + MANGA -> "Manga" + NOVEL -> "Novel" + } + } + + companion object { + fun fromText(string : String): MediaType { + return when (string) { + "Anime" -> ANIME + "Manga" -> MANGA + "Novel" -> NOVEL + else -> { ANIME } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/media/SourceSearchDialogFragment.kt b/app/src/main/java/ani/dantotsu/media/SourceSearchDialogFragment.kt index 3925bcce..06b784e8 100644 --- a/app/src/main/java/ani/dantotsu/media/SourceSearchDialogFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/SourceSearchDialogFragment.kt @@ -65,7 +65,7 @@ class SourceSearchDialogFragment : BottomSheetDialogFragment() { i = media!!.selected!!.sourceIndex val source = if (media!!.anime != null) { - (if (!media!!.isAdult) AnimeSources else HAnimeSources)[i!!] + (if (media!!.isAdult) HAnimeSources else AnimeSources)[i!!] } else { anime = false (if (media!!.isAdult) HMangaSources else MangaSources)[i!!] diff --git a/app/src/main/java/ani/dantotsu/media/SubtitleDownloader.kt b/app/src/main/java/ani/dantotsu/media/SubtitleDownloader.kt index e5ebd81b..6672f37d 100644 --- a/app/src/main/java/ani/dantotsu/media/SubtitleDownloader.kt +++ b/app/src/main/java/ani/dantotsu/media/SubtitleDownloader.kt @@ -17,7 +17,7 @@ class SubtitleDownloader { companion object { //doesn't really download the subtitles -\_(o_o)_/- - suspend fun loadSubtitleType(context: Context, url: String): SubtitleType = + suspend fun loadSubtitleType(url: String): SubtitleType = withContext(Dispatchers.IO) { // Initialize the NetworkHelper instance. Replace this line based on how you usually initialize it val networkHelper = Injekt.get() @@ -60,7 +60,7 @@ class SubtitleDownloader { if (!directory.exists()) { //just in case directory.mkdirs() } - val type = loadSubtitleType(context, url) + val type = loadSubtitleType(url) val subtiteFile = File(directory, "subtitle.${type}") if (subtiteFile.exists()) { subtiteFile.delete() diff --git a/app/src/main/java/ani/dantotsu/media/anime/AnimeNameAdapter.kt b/app/src/main/java/ani/dantotsu/media/anime/AnimeNameAdapter.kt index ad8c378e..16142902 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/AnimeNameAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/AnimeNameAdapter.kt @@ -7,7 +7,7 @@ import java.util.regex.Pattern class AnimeNameAdapter { companion object { const val episodeRegex = - "(episode|episodio|ep|e)[\\s:.\\-]*([\\d]+\\.?[\\d]*)[\\s:.\\-]*\\(?\\s*(sub|subbed|dub|dubbed)*\\s*\\)?\\s*" + "(episode|episodio|ep|e)[\\s:.\\-]*(\\d+\\.?\\d*)[\\s:.\\-]*\\(?\\s*(sub|subbed|dub|dubbed)*\\s*\\)?\\s*" const val failedEpisodeNumberRegex = "(? mr.value.replaceFirst(mr.groupValues[1], "") diff --git a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt index 2acc52d8..28d10c6b 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt @@ -29,19 +29,24 @@ import androidx.recyclerview.widget.ConcatAdapter import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 -import ani.dantotsu.* +import ani.dantotsu.FileUrl +import ani.dantotsu.R import ani.dantotsu.databinding.FragmentAnimeWatchBinding import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.anime.AnimeDownloaderService import ani.dantotsu.download.video.ExoplayerDownloadService +import ani.dantotsu.dp import ani.dantotsu.media.Media import ani.dantotsu.media.MediaDetailsActivity import ani.dantotsu.media.MediaDetailsViewModel +import ani.dantotsu.media.MediaType +import ani.dantotsu.navBarHeight import ani.dantotsu.others.LanguageMapper import ani.dantotsu.parsers.AnimeParser import ani.dantotsu.parsers.AnimeSources import ani.dantotsu.parsers.HAnimeSources +import ani.dantotsu.setNavigationTheme import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName @@ -433,7 +438,7 @@ class AnimeWatchFragment : Fragment() { DownloadedType( media.mainName(), i, - DownloadedType.Type.ANIME + MediaType.ANIME ) ) episodeAdapter.purgeDownload(i) @@ -445,7 +450,7 @@ class AnimeWatchFragment : Fragment() { DownloadedType( media.mainName(), i, - DownloadedType.Type.ANIME + MediaType.ANIME ) ) val taskName = AnimeDownloaderService.AnimeDownloadTask.getTaskName(media.mainName(), i) diff --git a/app/src/main/java/ani/dantotsu/media/anime/EpisodeAdapters.kt b/app/src/main/java/ani/dantotsu/media/anime/EpisodeAdapters.kt index 1f543319..3f06bf4d 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/EpisodeAdapters.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/EpisodeAdapters.kt @@ -13,14 +13,16 @@ import androidx.lifecycle.coroutineScope import androidx.media3.common.util.UnstableApi import androidx.media3.exoplayer.offline.DownloadIndex import androidx.recyclerview.widget.RecyclerView -import ani.dantotsu.* +import ani.dantotsu.R import ani.dantotsu.connections.updateProgress +import ani.dantotsu.currContext import ani.dantotsu.databinding.ItemEpisodeCompactBinding import ani.dantotsu.databinding.ItemEpisodeGridBinding import ani.dantotsu.databinding.ItemEpisodeListBinding import ani.dantotsu.download.anime.AnimeDownloaderService import ani.dantotsu.download.video.Helper import ani.dantotsu.media.Media +import ani.dantotsu.setAnimation import ani.dantotsu.settings.saving.PrefManager import com.bumptech.glide.Glide import com.bumptech.glide.load.model.GlideUrl @@ -427,7 +429,7 @@ class EpisodeAdapter( if (bytes < 0) return null val unit = 1000 if (bytes < unit) return "$bytes B" - val exp = (Math.log(bytes.toDouble()) / ln(unit.toDouble())).toInt() + val exp = (ln(bytes.toDouble()) / ln(unit.toDouble())).toInt() val pre = ("KMGTPE")[exp - 1] return String.format("%.1f %sB", bytes / unit.toDouble().pow(exp.toDouble()), pre) } diff --git a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt index 17f858e8..ea95e077 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt @@ -16,7 +16,10 @@ import android.graphics.Color import android.graphics.drawable.Animatable import android.hardware.SensorManager import android.media.AudioManager -import android.media.AudioManager.* +import android.media.AudioManager.AUDIOFOCUS_GAIN +import android.media.AudioManager.AUDIOFOCUS_LOSS +import android.media.AudioManager.AUDIOFOCUS_LOSS_TRANSIENT +import android.media.AudioManager.STREAM_MUSIC import android.net.Uri import android.os.Build import android.os.Bundle @@ -27,8 +30,18 @@ import android.provider.Settings.System import android.util.AttributeSet import android.util.Rational import android.util.TypedValue -import android.view.* -import android.view.KeyEvent.* +import android.view.GestureDetector +import android.view.KeyEvent +import android.view.KeyEvent.ACTION_UP +import android.view.KeyEvent.KEYCODE_B +import android.view.KeyEvent.KEYCODE_DPAD_LEFT +import android.view.KeyEvent.KEYCODE_DPAD_RIGHT +import android.view.KeyEvent.KEYCODE_N +import android.view.KeyEvent.KEYCODE_SPACE +import android.view.MotionEvent +import android.view.OrientationEventListener +import android.view.View +import android.view.ViewGroup import android.view.animation.AnimationUtils import android.widget.AdapterView import android.widget.ImageButton @@ -46,27 +59,43 @@ import androidx.core.view.updateLayoutParams import androidx.lifecycle.lifecycleScope import androidx.media3.cast.CastPlayer import androidx.media3.cast.SessionAvailabilityListener -import androidx.media3.common.* +import androidx.media3.common.C import androidx.media3.common.C.AUDIO_CONTENT_TYPE_MOVIE import androidx.media3.common.C.TRACK_TYPE_VIDEO +import androidx.media3.common.MediaItem +import androidx.media3.common.MimeTypes +import androidx.media3.common.PlaybackException +import androidx.media3.common.PlaybackParameters +import androidx.media3.common.Player +import androidx.media3.common.TrackSelectionOverride +import androidx.media3.common.Tracks import androidx.media3.common.util.UnstableApi -import androidx.media3.common.util.Util import androidx.media3.datasource.DataSource -import androidx.media3.datasource.DefaultDataSourceFactory +import androidx.media3.datasource.DefaultDataSource import androidx.media3.datasource.HttpDataSource import androidx.media3.datasource.cache.CacheDataSource import androidx.media3.datasource.okhttp.OkHttpDataSource +import androidx.media3.exoplayer.DefaultLoadControl import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.source.DefaultMediaSourceFactory import androidx.media3.exoplayer.trackselection.DefaultTrackSelector import androidx.media3.exoplayer.util.EventLogger import androidx.media3.session.MediaSession -import androidx.media3.ui.* -import androidx.media3.ui.CaptionStyleCompat.* -import androidx.media3.exoplayer.DefaultLoadControl +import androidx.media3.ui.AspectRatioFrameLayout +import androidx.media3.ui.CaptionStyleCompat +import androidx.media3.ui.CaptionStyleCompat.EDGE_TYPE_DEPRESSED +import androidx.media3.ui.CaptionStyleCompat.EDGE_TYPE_DROP_SHADOW +import androidx.media3.ui.CaptionStyleCompat.EDGE_TYPE_NONE +import androidx.media3.ui.CaptionStyleCompat.EDGE_TYPE_OUTLINE +import androidx.media3.ui.DefaultTimeBar +import androidx.media3.ui.PlayerView +import androidx.media3.ui.SubtitleView import androidx.mediarouter.app.MediaRouteButton -import ani.dantotsu.* +import ani.dantotsu.GesturesListener +import ani.dantotsu.NoPaddingArrayAdapter import ani.dantotsu.R +import ani.dantotsu.brightnessConverter +import ani.dantotsu.circularReveal import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.connections.crashlytics.CrashlyticsInterface import ani.dantotsu.connections.discord.Discord @@ -75,19 +104,38 @@ import ani.dantotsu.connections.discord.DiscordServiceRunningSingleton import ani.dantotsu.connections.discord.RPC import ani.dantotsu.connections.updateProgress import ani.dantotsu.databinding.ActivityExoplayerBinding +import ani.dantotsu.defaultHeaders import ani.dantotsu.download.video.Helper +import ani.dantotsu.dp +import ani.dantotsu.getCurrentBrightnessValue +import ani.dantotsu.hideSystemBars +import ani.dantotsu.hideSystemBarsExtendView +import ani.dantotsu.isOnline +import ani.dantotsu.logError import ani.dantotsu.media.Media import ani.dantotsu.media.MediaDetailsViewModel import ani.dantotsu.media.SubtitleDownloader +import ani.dantotsu.okHttpClient import ani.dantotsu.others.AniSkip import ani.dantotsu.others.AniSkip.getType import ani.dantotsu.others.ResettableTimer import ani.dantotsu.others.getSerialized -import ani.dantotsu.parsers.* +import ani.dantotsu.parsers.AnimeSources +import ani.dantotsu.parsers.HAnimeSources +import ani.dantotsu.parsers.Subtitle +import ani.dantotsu.parsers.SubtitleType +import ani.dantotsu.parsers.Video +import ani.dantotsu.parsers.VideoExtractor +import ani.dantotsu.parsers.VideoType +import ani.dantotsu.px import ani.dantotsu.settings.PlayerSettingsActivity import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName +import ani.dantotsu.snackString +import ani.dantotsu.startMainActivity import ani.dantotsu.themes.ThemeManager +import ani.dantotsu.toast +import ani.dantotsu.tryWithSuspend import ani.dantotsu.util.Logger import com.bumptech.glide.Glide import com.google.android.gms.cast.framework.CastButtonFactory @@ -103,8 +151,11 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -import java.util.* -import java.util.concurrent.* +import java.util.Calendar +import java.util.Timer +import java.util.TimerTask +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit import kotlin.math.max import kotlin.math.min import kotlin.math.roundToInt @@ -344,15 +395,14 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL isCastApiAvailable = GoogleApiAvailability.getInstance() .isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS try { - castContext = CastContext.getSharedInstance(this) + castContext = CastContext.getSharedInstance(this, Executors.newSingleThreadExecutor()).result castPlayer = CastPlayer(castContext!!) castPlayer!!.setSessionAvailabilityListener(this) } catch (e: Exception) { isCastApiAvailable = false } - WindowCompat.setDecorFitsSystemWindows(window, false) - hideSystemBars() + hideSystemBarsExtendView() onBackPressedDispatcher.addCallback(this) { finishAndRemoveTask() @@ -397,21 +447,25 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL orientationListener = object : OrientationEventListener(this, SensorManager.SENSOR_DELAY_UI) { override fun onOrientationChanged(orientation: Int) { - if (orientation in 45..135) { - if (rotation != ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE) { - exoRotate.visibility = View.VISIBLE + when (orientation) { + in 45..135 -> { + if (rotation != ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE) { + exoRotate.visibility = View.VISIBLE + } + rotation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE } - rotation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE - } else if (orientation in 225..315) { - if (rotation != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { - exoRotate.visibility = View.VISIBLE + in 225..315 -> { + if (rotation != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { + exoRotate.visibility = View.VISIBLE + } + rotation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE } - rotation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE - } else if (orientation in 315..360 || orientation in 0..45) { - if (rotation != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { - exoRotate.visibility = View.VISIBLE + in 315..360, in 0..45 -> { + if (rotation != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { + exoRotate.visibility = View.VISIBLE + } + rotation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT } - rotation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT } } } @@ -943,7 +997,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL episodeArr = episodes.keys.toList() currentEpisodeIndex = episodeArr.indexOf(media.anime!!.selectedEpisode!!) - episodeTitleArr = arrayListOf() + episodeTitleArr = arrayListOf() episodes.forEach { val episode = it.value val cleanedTitle = AnimeNameAdapter.removeEpisodeNumberCompletely(episode.title ?: "") @@ -1054,7 +1108,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""), RPC.Link( "Stream on Dantotsu", - "https://github.com/rebelonion/Dantotsu/" + getString(R.string.github) ) ) ) @@ -1266,6 +1320,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL media.anime!!.selectedEpisode!! ) + @Suppress("UNCHECKED_CAST") val list = (PrefManager.getNullableCustomVal("continueAnimeList", listOf(), List::class.java) as List).toMutableList() if (list.contains(media.id)) list.remove(media.id) list.add(media.id) @@ -1303,9 +1358,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL if (subtitle != null) { //var localFile: String? = null if (subtitle?.type == SubtitleType.UNKNOWN) { - val context = this runBlocking { - val type = SubtitleDownloader.loadSubtitleType(context, subtitle!!.file.url) + val type = SubtitleDownloader.loadSubtitleType(subtitle!!.file.url) val fileUri = Uri.parse(subtitle!!.file.url) sub = MediaItem.SubtitleConfiguration .Builder(fileUri) @@ -1360,8 +1414,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL } dataSource } - val dafuckDataSourceFactory = - DefaultDataSourceFactory(this, Util.getUserAgent(this, R.string.app_name.toString())) + val dafuckDataSourceFactory = DefaultDataSource.Factory(this) cacheFactory = CacheDataSource.Factory().apply { setCache(Helper.getSimpleCache(this@ExoplayerView)) if (ext.server.offline) { @@ -1737,28 +1790,26 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL timer = null return } - if (timer == null) { - timer = object : CountDownTimer(5000, 1000) { - override fun onTick(millisUntilFinished: Long) { - if (new == null){ - skipTimeButton.visibility = View.GONE - exoSkip.visibility = View.VISIBLE - disappeared = false - functionstarted = false - cancelTimer() - } - } - - override fun onFinish() { + timer = object : CountDownTimer(5000, 1000) { + override fun onTick(millisUntilFinished: Long) { + if (new == null) { skipTimeButton.visibility = View.GONE exoSkip.visibility = View.VISIBLE - disappeared = true + disappeared = false functionstarted = false cancelTimer() } } - timer?.start() + + override fun onFinish() { + skipTimeButton.visibility = View.GONE + exoSkip.visibility = View.VISIBLE + disappeared = true + functionstarted = false + cancelTimer() + } } + timer?.start() } if (PrefManager.getVal(PrefName.ShowTimeStampButton)) { diff --git a/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt b/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt index c45c274a..d5b887bd 100644 --- a/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt +++ b/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt @@ -29,6 +29,7 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import java.text.SimpleDateFormat import java.util.Date +import java.util.Locale import java.util.TimeZone import kotlin.math.abs import kotlin.math.sqrt @@ -258,6 +259,7 @@ class CommentItem(val comment: Comment, private fun removeSubCommentIds(){ subCommentIds.forEach { id -> + @Suppress("UNCHECKED_CAST") val parentComments = parentSection.groups as? List ?: emptyList() val commentToRemove = parentComments.find { it.comment.commentId == id } commentToRemove?.let { @@ -290,7 +292,7 @@ class CommentItem(val comment: Comment, @SuppressLint("SimpleDateFormat") private fun formatTimestamp(timestamp: String): String { return try { - val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT) dateFormat.timeZone = TimeZone.getTimeZone("UTC") val parsedDate = dateFormat.parse(timestamp) val currentDate = Date() @@ -315,7 +317,7 @@ class CommentItem(val comment: Comment, companion object { @SuppressLint("SimpleDateFormat") fun timestampToMillis(timestamp: String): Long { - val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT) dateFormat.timeZone = TimeZone.getTimeZone("UTC") val parsedDate = dateFormat.parse(timestamp) return parsedDate?.time ?: 0 diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaCache.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaCache.kt index ebf1c57f..6302a6c9 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaCache.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaCache.kt @@ -2,7 +2,6 @@ package ani.dantotsu.media.manga import android.content.ContentResolver import android.content.ContentValues -import android.content.Context import android.graphics.Bitmap import android.graphics.BitmapFactory import android.net.Uri @@ -10,8 +9,8 @@ import android.os.Build import android.os.Environment import android.provider.MediaStore import android.util.LruCache -import ani.dantotsu.util.Logger import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.online.HttpSource import kotlinx.coroutines.Dispatchers @@ -25,8 +24,7 @@ data class ImageData( ) { suspend fun fetchAndProcessImage( page: Page, - httpSource: HttpSource, - context: Context + httpSource: HttpSource ): Bitmap? { return withContext(Dispatchers.IO) { try { diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaNameAdapter.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaNameAdapter.kt index ae755faa..d265b69a 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaNameAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaNameAdapter.kt @@ -5,8 +5,8 @@ import java.util.regex.Pattern class MangaNameAdapter { companion object { - const val chapterRegex = "(chapter|chap|ch|c)[\\s:.\\-]*([\\d]+\\.?[\\d]*)[\\s:.\\-]*" - const val filedChapterNumberRegex = "(? ): Bitmap? { //still used in some places return tryWithSuspend { withContext(Dispatchers.IO) { - Glide.with(this@loadBitmap_old) + Glide.with(this@loadBitmapOld) .asBitmap() .let { if (link.url.startsWith("file://")) { @@ -168,8 +172,7 @@ abstract class BaseImageAdapter( mangaCache.get(link.url)?.let { imageData -> val bitmap = imageData.fetchAndProcessImage( imageData.page, - imageData.source, - context = this@loadBitmap + imageData.source ) it.load(bitmap) .skipMemoryCache(true) 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 5ae6e5a1..747bb8dd 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 @@ -10,8 +10,19 @@ import android.content.res.Resources import android.graphics.Bitmap import android.os.Build import android.os.Bundle -import android.view.* -import android.view.KeyEvent.* +import android.view.HapticFeedbackConstants +import android.view.KeyEvent +import android.view.KeyEvent.ACTION_DOWN +import android.view.KeyEvent.KEYCODE_DPAD_DOWN +import android.view.KeyEvent.KEYCODE_DPAD_UP +import android.view.KeyEvent.KEYCODE_PAGE_DOWN +import android.view.KeyEvent.KEYCODE_PAGE_UP +import android.view.KeyEvent.KEYCODE_VOLUME_DOWN +import android.view.KeyEvent.KEYCODE_VOLUME_UP +import android.view.MotionEvent +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager import android.view.animation.OvershootInterpolator import android.widget.AdapterView import android.widget.CheckBox @@ -27,7 +38,9 @@ import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.PagerSnapHelper import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 -import ani.dantotsu.* +import ani.dantotsu.GesturesListener +import ani.dantotsu.NoPaddingArrayAdapter +import ani.dantotsu.R import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.connections.crashlytics.CrashlyticsInterface import ani.dantotsu.connections.discord.Discord @@ -35,7 +48,12 @@ import ani.dantotsu.connections.discord.DiscordService import ani.dantotsu.connections.discord.DiscordServiceRunningSingleton import ani.dantotsu.connections.discord.RPC import ani.dantotsu.connections.updateProgress +import ani.dantotsu.currContext import ani.dantotsu.databinding.ActivityMangaReaderBinding +import ani.dantotsu.dp +import ani.dantotsu.hideSystemBarsExtendView +import ani.dantotsu.isOnline +import ani.dantotsu.logError import ani.dantotsu.media.Media import ani.dantotsu.media.MediaDetailsViewModel import ani.dantotsu.media.MediaSingleton @@ -46,14 +64,25 @@ import ani.dantotsu.others.ImageViewDialog import ani.dantotsu.parsers.HMangaSources import ani.dantotsu.parsers.MangaImage import ani.dantotsu.parsers.MangaSources +import ani.dantotsu.px +import ani.dantotsu.setSafeOnClickListener import ani.dantotsu.settings.CurrentReaderSettings import ani.dantotsu.settings.CurrentReaderSettings.Companion.applyWebtoon -import ani.dantotsu.settings.CurrentReaderSettings.Directions.* -import ani.dantotsu.settings.CurrentReaderSettings.DualPageModes.* -import ani.dantotsu.settings.CurrentReaderSettings.Layouts.* +import ani.dantotsu.settings.CurrentReaderSettings.Directions.BOTTOM_TO_TOP +import ani.dantotsu.settings.CurrentReaderSettings.Directions.LEFT_TO_RIGHT +import ani.dantotsu.settings.CurrentReaderSettings.Directions.RIGHT_TO_LEFT +import ani.dantotsu.settings.CurrentReaderSettings.Directions.TOP_TO_BOTTOM +import ani.dantotsu.settings.CurrentReaderSettings.DualPageModes.Automatic +import ani.dantotsu.settings.CurrentReaderSettings.DualPageModes.Force +import ani.dantotsu.settings.CurrentReaderSettings.DualPageModes.No +import ani.dantotsu.settings.CurrentReaderSettings.Layouts.CONTINUOUS_PAGED +import ani.dantotsu.settings.CurrentReaderSettings.Layouts.PAGED import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName +import ani.dantotsu.showSystemBarsRetractView +import ani.dantotsu.snackString import ani.dantotsu.themes.ThemeManager +import ani.dantotsu.tryWith import com.alexvasilkov.gestures.views.GestureFrameLayout import com.bumptech.glide.load.resource.bitmap.BitmapTransformation import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView @@ -66,7 +95,8 @@ import java.io.FileInputStream import java.io.FileOutputStream import java.io.ObjectInputStream import java.io.ObjectOutputStream -import java.util.* +import java.util.Timer +import java.util.TimerTask import kotlin.math.min import kotlin.properties.Delegates @@ -88,7 +118,6 @@ class MangaReaderActivity : AppCompatActivity() { private var isContVisible = false private var showProgressDialog = true - private var hidescrollbar = false private var maxChapterPage = 0L private var currentChapterPage = 0L @@ -123,7 +152,7 @@ class MangaReaderActivity : AppCompatActivity() { } private fun hideSystemBars() { - if (PrefManager.getVal(PrefName.ShowSystemBars)) + if (PrefManager.getVal(PrefName.ShowSystemBars)) showSystemBarsRetractView() else hideSystemBarsExtendView() @@ -368,7 +397,7 @@ class MangaReaderActivity : AppCompatActivity() { RPC.Link(getString(R.string.view_manga), media.shareLink ?: ""), RPC.Link( "Stream on Dantotsu", - "https://github.com/rebelonion/Dantotsu/" + getString(R.string.github) ) ) ) @@ -740,12 +769,12 @@ class MangaReaderActivity : AppCompatActivity() { goneTimer.schedule(timerTask, controllerDuration) } - enum class pressPos { + enum class PressPos { LEFT, RIGHT, CENTER } fun handleController(shouldShow: Boolean? = null, event: MotionEvent? = null) { - var pressLocation = pressPos.CENTER + var pressLocation = PressPos.CENTER if (!sliding) { if (event != null && defaultSettings.layout == PAGED) { if (event.action != MotionEvent.ACTION_UP) return @@ -755,23 +784,23 @@ class MangaReaderActivity : AppCompatActivity() { //if in the 1st 1/5th of the screen width, left and lower than 1/5th of the screen height, left if (screenWidth / 5 in x + 1.. screenWidth - screenWidth / 5 && y > screenWidth / 5) { pressLocation = if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) { - pressPos.LEFT + PressPos.LEFT } else { - pressPos.RIGHT + PressPos.RIGHT } } } // if pressLocation is left or right go to previous or next page (paged mode only) - if (pressLocation == pressPos.LEFT) { + if (pressLocation == PressPos.LEFT) { if (binding.mangaReaderPager.currentItem > 0) { //if the current images zoomed in, go back to normal before going to previous page @@ -782,7 +811,7 @@ class MangaReaderActivity : AppCompatActivity() { return } - } else if (pressLocation == pressPos.RIGHT) { + } else if (pressLocation == PressPos.RIGHT) { if (binding.mangaReaderPager.currentItem < maxChapterPage - 1) { //if the current images zoomed in, go back to normal before going to next page if (imageAdapter?.isZoomed() == true) { @@ -960,7 +989,7 @@ class MangaReaderActivity : AppCompatActivity() { if (!incognito && PrefManager.getCustomVal( "${media.id}_save_progress", true - ) && if (media.isAdult) PrefManager.getVal(PrefName.UpdateForHReader) else true + ) && if (media.isAdult) PrefManager.getVal(PrefName.UpdateForHReader) else true ) updateProgress( media, 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 859dfdac..867912a7 100644 --- a/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt @@ -9,7 +9,6 @@ import android.os.Environment import android.os.Handler import android.os.Looper import android.os.Parcelable -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -28,6 +27,7 @@ import ani.dantotsu.download.novel.NovelDownloaderService import ani.dantotsu.download.novel.NovelServiceDataSingleton import ani.dantotsu.media.Media import ani.dantotsu.media.MediaDetailsViewModel +import ani.dantotsu.media.MediaType import ani.dantotsu.media.novel.novelreader.NovelReaderActivity import ani.dantotsu.navBarHeight import ani.dantotsu.parsers.ShowResponse @@ -90,7 +90,7 @@ class NovelReadFragment : Fragment(), DownloadedType( media.mainName(), novel.name, - DownloadedType.Type.NOVEL + MediaType.NOVEL ) ) ) { @@ -122,7 +122,7 @@ class NovelReadFragment : Fragment(), DownloadedType( media.mainName(), novel.name, - DownloadedType.Type.NOVEL + MediaType.NOVEL ) ) } @@ -133,7 +133,7 @@ class NovelReadFragment : Fragment(), DownloadedType( media.mainName(), novel.name, - DownloadedType.Type.NOVEL + MediaType.NOVEL ) ) } diff --git a/app/src/main/java/ani/dantotsu/media/user/ListActivity.kt b/app/src/main/java/ani/dantotsu/media/user/ListActivity.kt index bd2536d1..81a80cfa 100644 --- a/app/src/main/java/ani/dantotsu/media/user/ListActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/user/ListActivity.kt @@ -6,7 +6,6 @@ import android.util.TypedValue import android.view.View import android.view.ViewGroup import android.view.Window -import android.view.WindowManager import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.PopupMenu @@ -17,7 +16,7 @@ import androidx.lifecycle.lifecycleScope import ani.dantotsu.R import ani.dantotsu.Refresh import ani.dantotsu.databinding.ActivityListBinding -import ani.dantotsu.navBarHeight +import ani.dantotsu.hideSystemBarsExtendView import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.statusBarHeight @@ -71,10 +70,7 @@ class ListActivity : AppCompatActivity() { } else { binding.root.fitsSystemWindows = false requestWindowFeature(Window.FEATURE_NO_TITLE) - window.setFlags( - WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN - ) + hideSystemBarsExtendView() binding.settingsContainer.updateLayoutParams { topMargin = statusBarHeight } diff --git a/app/src/main/java/ani/dantotsu/others/AndroidBug5497Workaround.kt b/app/src/main/java/ani/dantotsu/others/AndroidBug5497Workaround.kt index 46e8a297..7e46880d 100644 --- a/app/src/main/java/ani/dantotsu/others/AndroidBug5497Workaround.kt +++ b/app/src/main/java/ani/dantotsu/others/AndroidBug5497Workaround.kt @@ -11,7 +11,7 @@ class AndroidBug5497Workaround private constructor(activity: Activity, private v private val frameLayoutParams: FrameLayout.LayoutParams init { - val content = activity.findViewById(android.R.id.content) as FrameLayout + val content: FrameLayout = activity.findViewById(android.R.id.content) mChildOfContent = content.getChildAt(0) mChildOfContent.viewTreeObserver.addOnGlobalLayoutListener { possiblyResizeChildOfContent() } frameLayoutParams = mChildOfContent.layoutParams as FrameLayout.LayoutParams diff --git a/app/src/main/java/ani/dantotsu/others/ImageViewDialog.kt b/app/src/main/java/ani/dantotsu/others/ImageViewDialog.kt index e11715c7..346bd592 100644 --- a/app/src/main/java/ani/dantotsu/others/ImageViewDialog.kt +++ b/app/src/main/java/ani/dantotsu/others/ImageViewDialog.kt @@ -14,7 +14,7 @@ import ani.dantotsu.R import ani.dantotsu.databinding.BottomSheetImageBinding import ani.dantotsu.downloadsPermission import ani.dantotsu.media.manga.mangareader.BaseImageAdapter.Companion.loadBitmap -import ani.dantotsu.media.manga.mangareader.BaseImageAdapter.Companion.loadBitmap_old +import ani.dantotsu.media.manga.mangareader.BaseImageAdapter.Companion.loadBitmapOld import ani.dantotsu.media.manga.mangareader.BaseImageAdapter.Companion.mergeBitmap import ani.dantotsu.openLinkInBrowser import ani.dantotsu.saveImageToDownloads @@ -84,9 +84,9 @@ class ImageViewDialog : BottomSheetDialogFragment() { viewLifecycleOwner.lifecycleScope.launch { val binding = _binding ?: return@launch - var bitmap = context.loadBitmap_old(image, trans1 ?: listOf()) + var bitmap = context.loadBitmapOld(image, trans1 ?: listOf()) var bitmap2 = - if (image2 != null) context.loadBitmap_old(image2, trans2 ?: listOf()) else null + if (image2 != null) context.loadBitmapOld(image2, trans2 ?: listOf()) else null if (bitmap == null) { bitmap = context.loadBitmap(image, trans1 ?: listOf()) bitmap2 = diff --git a/app/src/main/java/ani/dantotsu/others/OutlineTextView.kt b/app/src/main/java/ani/dantotsu/others/OutlineTextView.kt index e2c17cc0..7a0cf925 100644 --- a/app/src/main/java/ani/dantotsu/others/OutlineTextView.kt +++ b/app/src/main/java/ani/dantotsu/others/OutlineTextView.kt @@ -1,9 +1,11 @@ package ani.dantotsu.others import android.content.Context +import android.content.res.Resources import android.graphics.Canvas import android.graphics.Paint import android.util.AttributeSet +import android.util.TypedValue import androidx.appcompat.widget.AppCompatTextView import ani.dantotsu.R @@ -54,14 +56,14 @@ class OutlineTextView : AppCompatTextView { setStrokeWidth(strokeWidth) } + private val Float.toPx get() = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics + ) private fun setStrokeWidth(width: Float) { - strokeWidth = width.toPx(context) + strokeWidth = width.toPx } - private fun Float.toPx(context: Context) = - (this * context.resources.displayMetrics.scaledDensity + 0.5F) - override fun invalidate() { if (isDrawing) return super.invalidate() diff --git a/app/src/main/java/ani/dantotsu/others/webview/CookieCatcher.kt b/app/src/main/java/ani/dantotsu/others/webview/CookieCatcher.kt index 73ae553a..e9e171f8 100644 --- a/app/src/main/java/ani/dantotsu/others/webview/CookieCatcher.kt +++ b/app/src/main/java/ani/dantotsu/others/webview/CookieCatcher.kt @@ -12,19 +12,19 @@ import androidx.appcompat.app.AppCompatActivity import ani.dantotsu.R import ani.dantotsu.themes.ThemeManager import eu.kanade.tachiyomi.network.NetworkHelper +import eu.kanade.tachiyomi.util.system.getSerializableExtraCompat import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get class CookieCatcher : AppCompatActivity() { @SuppressLint("SetJavaScriptEnabled") - @Suppress("UNCHECKED_CAST") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ThemeManager(this).applyTheme() //get url from intent - val url = intent.getStringExtra("url") ?: "https://www.youtube.com/watch?v=dQw4w9WgXcQ" - val headers: Map = intent.getSerializableExtra("headers") as? Map ?: emptyMap() + val url = intent.getStringExtra("url") ?: getString(R.string.cursed_yt) + val headers: Map = intent.getSerializableExtraCompat("headers") as? Map ?: emptyMap() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { val process = Application.getProcessName() diff --git a/app/src/main/java/ani/dantotsu/parsers/AniyomiAdapter.kt b/app/src/main/java/ani/dantotsu/parsers/AniyomiAdapter.kt index 5ef0adf1..fc271de6 100644 --- a/app/src/main/java/ani/dantotsu/parsers/AniyomiAdapter.kt +++ b/app/src/main/java/ani/dantotsu/parsers/AniyomiAdapter.kt @@ -11,11 +11,11 @@ import android.os.Environment import android.provider.MediaStore import ani.dantotsu.FileUrl import ani.dantotsu.currContext -import ani.dantotsu.util.Logger import ani.dantotsu.media.anime.AnimeNameAdapter import ani.dantotsu.media.manga.ImageData import ani.dantotsu.media.manga.MangaCache import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource import eu.kanade.tachiyomi.animesource.model.AnimesPage @@ -59,8 +59,6 @@ class AniyomiAdapter { fun aniyomiToAnimeParser(extension: AnimeExtension.Installed): DynamicAnimeParser { return DynamicAnimeParser(extension) } - - } class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() { @@ -192,7 +190,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() { // Group by season, sort within each season, and then renumber while keeping episode number 0 as is val seasonGroups = res.groupBy { AnimeNameAdapter.findSeasonNumber(it.name) ?: 0 } - seasonGroups.keys.sortedBy { it.toInt() } + seasonGroups.keys.sortedBy { it } .flatMap { season -> seasonGroups[season]?.sortedBy { it.episode_number }?.map { episode -> if (episode.episode_number != 0f) { // Skip renumbering for episode number 0 @@ -209,7 +207,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() { } ?: emptyList() } } - return sortedEpisodes.map { SEpisodeToEpisode(it) } + return sortedEpisodes.map { sEpisodeToEpisode(it) } } catch (e: Exception) { Logger.log("Exception: $e") } @@ -244,7 +242,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() { return try { val videos = source.getVideoList(sEpisode) - videos.map { VideoToVideoServer(it) } + videos.map { videoToVideoServer(it) } } catch (e: Exception) { Logger.log("Exception occurred: ${e.message}") emptyList() @@ -296,7 +294,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() { } } - private fun SEpisodeToEpisode(sEpisode: SEpisode): Episode { + private fun sEpisodeToEpisode(sEpisode: SEpisode): Episode { //if the float episode number is a whole number, convert it to an int val episodeNumberInt = if (sEpisode.episode_number % 1 == 0f) { @@ -324,7 +322,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() { ) } - private fun VideoToVideoServer(video: Video): VideoServer { + private fun videoToVideoServer(video: Video): VideoServer { return VideoServer( video.quality, video.url, @@ -363,7 +361,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { return try { val res = source.getChapterList(sManga) val reversedRes = res.reversed() - val chapterList = reversedRes.map { SChapterToMangaChapter(it) } + val chapterList = reversedRes.map { sChapterToMangaChapter(it) } Logger.log("chapterList size: ${chapterList.size}") Logger.log("chapterList: ${chapterList[1].title}") Logger.log("chapterList: ${chapterList[1].description}") @@ -382,7 +380,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { sourceLanguage = 0 extension.sources[sourceLanguage] } as? HttpSource ?: return emptyList() - var imageDataList: List = listOf() + val imageDataList: MutableList = mutableListOf() val ret = coroutineScope { try { Logger.log("source.name " + source.name) @@ -632,7 +630,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { } - private fun SChapterToMangaChapter(sChapter: SChapter): MangaChapter { + private fun sChapterToMangaChapter(sChapter: SChapter): MangaChapter { return MangaChapter( sChapter.name, sChapter.url, @@ -676,8 +674,8 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() { get() = videoServer override suspend fun extract(): VideoContainer { - val vidList = listOfNotNull(videoServer.video?.let { AniVideoToSaiVideo(it) }) - val subList = videoServer.video?.subtitleTracks?.map { TrackToSubtitle(it) } ?: emptyList() + val vidList = listOfNotNull(videoServer.video?.let { aniVideoToSaiVideo(it) }) + val subList = videoServer.video?.subtitleTracks?.map { trackToSubtitle(it) } ?: emptyList() return if (vidList.isNotEmpty()) { VideoContainer(vidList, subList) @@ -686,7 +684,7 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() { } } - private fun AniVideoToSaiVideo(aniVideo: Video): ani.dantotsu.parsers.Video { + private fun aniVideoToSaiVideo(aniVideo: Video): ani.dantotsu.parsers.Video { // Find the number value from the .quality string val number = Regex("""\d+""").find(aniVideo.quality)?.value?.toInt() ?: 0 @@ -789,9 +787,9 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() { } - private fun TrackToSubtitle(track: Track): Subtitle { + private fun trackToSubtitle(track: Track): Subtitle { //use Dispatchers.IO to make a HTTP request to determine the subtitle type - var type: SubtitleType? = null + var type: SubtitleType? runBlocking { type = findSubtitleType(track.url) } diff --git a/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt b/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt index 1c9c3b6c..57098894 100644 --- a/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt +++ b/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt @@ -4,6 +4,7 @@ import android.net.Uri import android.os.Environment import ani.dantotsu.currContext import ani.dantotsu.download.DownloadsManager +import ani.dantotsu.media.MediaType import ani.dantotsu.media.anime.AnimeNameAdapter import ani.dantotsu.tryWithSuspend import eu.kanade.tachiyomi.animesource.model.SAnime @@ -132,16 +133,16 @@ class OfflineVideoExtractor(val videoServer: VideoServer) : VideoExtractor() { currContext()?.let { DownloadsManager.getDirectory( it, - ani.dantotsu.download.DownloadedType.Type.ANIME, + MediaType.ANIME, title, episode - ).listFiles()?.forEach { - if (it.name.contains("subtitle")) { + ).listFiles()?.forEach { file -> + if (file.name.contains("subtitle")) { return listOf( Subtitle( "Downloaded Subtitle", - Uri.fromFile(it).toString(), - determineSubtitletype(it.absolutePath) + Uri.fromFile(file).toString(), + determineSubtitletype(file.absolutePath) ) ) } diff --git a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstallReceiver.kt b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionFileObserver.kt similarity index 98% rename from app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstallReceiver.kt rename to app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionFileObserver.kt index 056118a5..b69cea44 100644 --- a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstallReceiver.kt +++ b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionFileObserver.kt @@ -1,7 +1,6 @@ package ani.dantotsu.parsers.novel import android.os.FileObserver -import android.util.Log import ani.dantotsu.parsers.novel.FileObserver.fileObserver import ani.dantotsu.util.Logger import java.io.File diff --git a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstaller.kt b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstaller.kt index 14d7b75e..818713c2 100644 --- a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstaller.kt +++ b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstaller.kt @@ -10,7 +10,6 @@ import android.net.Uri import android.os.Build import android.os.Environment import android.provider.MediaStore -import android.util.Log import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import androidx.core.net.toUri @@ -63,7 +62,7 @@ internal class NovelExtensionInstaller(private val context: Context) { * @param url The url of the apk. * @param extension The extension to install. */ - fun downloadAndInstall(url: String, extension: NovelExtension) = Observable.defer { + fun downloadAndInstall(url: String, extension: NovelExtension): Observable = Observable.defer { val pkgName = extension.pkgName val oldDownload = activeDownloads[pkgName] diff --git a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionLoader.kt b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionLoader.kt index 78535115..d4c94da5 100644 --- a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionLoader.kt +++ b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionLoader.kt @@ -5,11 +5,10 @@ import android.content.pm.PackageInfo import android.content.pm.PackageManager.GET_SIGNATURES import android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES import android.os.Build -import android.util.Log import ani.dantotsu.connections.crashlytics.CrashlyticsInterface -import ani.dantotsu.util.Logger import ani.dantotsu.parsers.NovelInterface import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import dalvik.system.PathClassLoader import eu.kanade.tachiyomi.util.lang.Hash import uy.kohesive.injekt.Injekt @@ -134,10 +133,10 @@ internal object NovelExtensionLoader { } Logger.log("isFileWritable: ${file.canWrite()}") val classLoader = PathClassLoader(file.absolutePath, null, context.classLoader) - val className = + val extensionClassName = "some.random.novelextensions.${className.lowercase(Locale.getDefault())}.$className" - val loadedClass = classLoader.loadClass(className) - val instance = loadedClass.newInstance() + val loadedClass = classLoader.loadClass(extensionClassName) + val instance = loadedClass.getDeclaredConstructor().newInstance() val novelInterfaceInstance = instance as? NovelInterface listOfNotNull(novelInterfaceInstance) } catch (e: Exception) { diff --git a/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt b/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt index 9fbb60e3..d008f966 100644 --- a/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt +++ b/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt @@ -34,6 +34,7 @@ import ani.dantotsu.setSlideIn import ani.dantotsu.setSlideUp import ani.dantotsu.util.AniMarkdown.Companion.getFullAniHTML import ani.dantotsu.util.Logger +import eu.kanade.tachiyomi.util.system.getSerializableCompat import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -58,7 +59,7 @@ class ProfileFragment : Fragment() { super.onViewCreated(view, savedInstanceState) activity = requireActivity() as ProfileActivity - user = arguments?.getSerializable("user") as Query.UserProfile + user = arguments?.getSerializableCompat("user") as Query.UserProfile viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) { model.setData(user.id) } diff --git a/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt b/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt index b90cba33..2f01cac6 100644 --- a/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt +++ b/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt @@ -20,6 +20,7 @@ import ani.dantotsu.profile.ChartBuilder.Companion.StatType import ani.dantotsu.statusBarHeight import com.github.aachartmodel.aainfographics.aachartcreator.AAChartType import com.xwray.groupie.GroupieAdapter +import eu.kanade.tachiyomi.util.system.getSerializableCompat import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -48,7 +49,7 @@ class StatsFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) activity = requireActivity() as ProfileActivity - user = arguments?.getSerializable("user") as Query.UserProfile + user = arguments?.getSerializableCompat("user") as Query.UserProfile binding.statisticList.adapter = adapter binding.statisticList.recycledViewPool.setMaxRecycledViews(0, 0) @@ -95,7 +96,7 @@ class StatsFragment : } } else { stats.removeAll( - stats.filter { it?.id == Anilist.userid } + stats.filter { it?.id == Anilist.userid }.toSet() ) loadStats(type == MediaType.ANIME) } @@ -445,6 +446,7 @@ class StatsFragment : }.toMutableList() chartPackets.clear() chartPackets.addAll(standardizedPackets) + @Suppress("UNCHECKED_CAST") val genreChart = ChartBuilder.buildChart( activity, ChartType.TwoDimensional, @@ -499,6 +501,7 @@ class StatsFragment : }.toMutableList() chartPackets.clear() chartPackets.addAll(standardizedPackets) + @Suppress("UNCHECKED_CAST") val tagChart = ChartBuilder.buildChart( activity, ChartType.TwoDimensional, @@ -553,6 +556,7 @@ class StatsFragment : }.toMutableList() chartPackets.clear() chartPackets.addAll(standardizedPackets) + @Suppress("UNCHECKED_CAST") val countryChart = ChartBuilder.buildChart( activity, ChartType.OneDimensional, @@ -609,6 +613,7 @@ class StatsFragment : }.toMutableList() chartPackets.clear() chartPackets.addAll(standardizedPackets) + @Suppress("UNCHECKED_CAST") val voiceActorsChart = ChartBuilder.buildChart( activity, ChartType.TwoDimensional, @@ -663,6 +668,7 @@ class StatsFragment : }.toMutableList() chartPackets.clear() chartPackets.addAll(standardizedPackets) + @Suppress("UNCHECKED_CAST") val studioChart = ChartBuilder.buildChart( activity, ChartType.TwoDimensional, @@ -720,6 +726,7 @@ class StatsFragment : }.toMutableList() chartPackets.clear() chartPackets.addAll(standardizedPackets) + @Suppress("UNCHECKED_CAST") val staffChart = ChartBuilder.buildChart( activity, ChartType.TwoDimensional, diff --git a/app/src/main/java/ani/dantotsu/profile/activity/FeedActivity.kt b/app/src/main/java/ani/dantotsu/profile/activity/FeedActivity.kt index 6a85c640..0b35f047 100644 --- a/app/src/main/java/ani/dantotsu/profile/activity/FeedActivity.kt +++ b/app/src/main/java/ani/dantotsu/profile/activity/FeedActivity.kt @@ -61,7 +61,7 @@ class FeedActivity : AppCompatActivity() { } }) binding.listBack.setOnClickListener { - onBackPressed() + onBackPressedDispatcher.onBackPressed() } } diff --git a/app/src/main/java/ani/dantotsu/profile/activity/NotificationActivity.kt b/app/src/main/java/ani/dantotsu/profile/activity/NotificationActivity.kt index c8f5141c..a8214004 100644 --- a/app/src/main/java/ani/dantotsu/profile/activity/NotificationActivity.kt +++ b/app/src/main/java/ani/dantotsu/profile/activity/NotificationActivity.kt @@ -58,7 +58,7 @@ class NotificationActivity : AppCompatActivity() { binding.followerGrid.visibility = ViewGroup.GONE binding.followerList.visibility = ViewGroup.GONE binding.listBack.setOnClickListener { - onBackPressed() + onBackPressedDispatcher.onBackPressed() } binding.listProgressBar.visibility = ViewGroup.VISIBLE val activityId = intent.getIntExtra("activityId", -1) diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt index f4788122..6a46d826 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt @@ -46,7 +46,6 @@ import ani.dantotsu.databinding.ActivitySettingsAboutBinding import ani.dantotsu.databinding.ActivitySettingsAccountsBinding import ani.dantotsu.databinding.ActivitySettingsAnimeBinding import ani.dantotsu.databinding.ActivitySettingsBinding -import ani.dantotsu.download.DownloadedType import ani.dantotsu.databinding.ActivitySettingsCommonBinding import ani.dantotsu.databinding.ActivitySettingsExtensionsBinding import ani.dantotsu.databinding.ActivitySettingsMangaBinding @@ -57,7 +56,7 @@ import ani.dantotsu.download.video.ExoplayerDownloadService import ani.dantotsu.downloadsPermission import ani.dantotsu.initActivity import ani.dantotsu.loadImage -import ani.dantotsu.util.Logger +import ani.dantotsu.media.MediaType import ani.dantotsu.navBarHeight import ani.dantotsu.notifications.TaskScheduler import ani.dantotsu.notifications.anilist.AnilistNotificationWorker @@ -81,6 +80,7 @@ import ani.dantotsu.startMainActivity import ani.dantotsu.statusBarHeight import ani.dantotsu.themes.ThemeManager import ani.dantotsu.toast +import ani.dantotsu.util.Logger import com.google.android.material.snackbar.Snackbar import com.google.android.material.textfield.TextInputEditText import eltos.simpledialogfragment.SimpleDialog @@ -151,13 +151,13 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene salt ) } catch (e: Exception) { - toast("Incorrect password") + toast(getString(R.string.incorrect_password)) return@passwordAlertDialog } if (PreferencePackager.unpack(decryptedJson)) restartApp() } else { - toast("Password cannot be empty") + toast(getString(R.string.password_cannot_be_empty)) } } } else if (name.endsWith(".ani")) { @@ -165,11 +165,11 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene if (PreferencePackager.unpack(decryptedJson)) restartApp() } else { - toast("Unknown file type") + toast(getString(R.string.unknown_file_type)) } } catch (e: Exception) { e.printStackTrace() - toast("Error importing settings") + toast(getString(R.string.error_importing_settings)) } } } @@ -254,7 +254,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene } val tag = "colorPicker" - CustomColorDialog().title("Custom Theme") + CustomColorDialog().title(R.string.custom_theme) .colorPreset(originalColor) .colors(this, SimpleColorDialog.MATERIAL_COLOR_PALLET) .allowCustom(true) @@ -271,7 +271,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene val managers = arrayOf("Default", "1DM", "ADM") val downloadManagerDialog = - AlertDialog.Builder(this, R.style.MyPopup).setTitle("Download Manager") + AlertDialog.Builder(this, R.style.MyPopup).setTitle(R.string.download_manager) var downloadManager: Int = PrefManager.getVal(PrefName.DownloadManager) bindingCommon.settingsDownloadManager.setOnClickListener { val dialog = downloadManagerDialog.setSingleChoiceItems( @@ -291,7 +291,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene val filteredLocations = Location.entries.filter { it.exportable } selectedArray.addAll(List(filteredLocations.size - 1) { false }) val dialog = AlertDialog.Builder(this, R.style.MyPopup) - .setTitle("Import/Export Settings") + .setTitle(R.string.import_export_settings) .setMultiChoiceItems( filteredLocations.map { it.name }.toTypedArray(), selectedArray.toBooleanArray() @@ -346,7 +346,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene .setMessage(getString(R.string.purge_confirm, getString(R.string.anime))) .setPositiveButton(R.string.yes) { dialog, _ -> val downloadsManager = Injekt.get() - downloadsManager.purgeDownloads(DownloadedType.Type.ANIME) + downloadsManager.purgeDownloads(MediaType.ANIME) DownloadService.sendRemoveAllDownloads( this, ExoplayerDownloadService::class.java, @@ -354,7 +354,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene ) dialog.dismiss() } - .setNegativeButton("No") { dialog, _ -> + .setNegativeButton(R.string.no) { dialog, _ -> dialog.dismiss() } .create() @@ -368,10 +368,10 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene .setMessage(getString(R.string.purge_confirm, getString(R.string.manga))) .setPositiveButton(R.string.yes) { dialog, _ -> val downloadsManager = Injekt.get() - downloadsManager.purgeDownloads(DownloadedType.Type.MANGA) + downloadsManager.purgeDownloads(MediaType.MANGA) dialog.dismiss() } - .setNegativeButton("No") { dialog, _ -> + .setNegativeButton(R.string.no) { dialog, _ -> dialog.dismiss() } .create() @@ -385,10 +385,10 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene .setMessage(getString(R.string.purge_confirm, getString(R.string.novels))) .setPositiveButton(R.string.yes) { dialog, _ -> val downloadsManager = Injekt.get() - downloadsManager.purgeDownloads(DownloadedType.Type.NOVEL) + downloadsManager.purgeDownloads(MediaType.NOVEL) dialog.dismiss() } - .setNegativeButton("No") { dialog, _ -> + .setNegativeButton(R.string.no) { dialog, _ -> dialog.dismiss() } .create() @@ -423,16 +423,16 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene val alertDialog = AlertDialog.Builder(this, R.style.MyPopup) .setTitle("User Agent") .setView(dialogView) - .setPositiveButton("OK") { dialog, _ -> + .setPositiveButton(getString(R.string.ok)) { dialog, _ -> PrefManager.setVal(PrefName.DefaultUserAgent, editText.text.toString()) dialog.dismiss() } - .setNeutralButton("Reset") { dialog, _ -> + .setNeutralButton(getString(R.string.reset)) { dialog, _ -> PrefManager.removeVal(PrefName.DefaultUserAgent) editText.setText("") dialog.dismiss() } - .setNegativeButton("Cancel") { dialog, _ -> + .setNegativeButton(getString(R.string.cancel)) { dialog, _ -> dialog.dismiss() } .create() @@ -613,7 +613,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene lifecycleScope.launch { it.pop() } - openLinkInBrowser("https://www.buymeacoffee.com/rebelonion") + openLinkInBrowser(getString(R.string.coffee)) } lifecycleScope.launch { binding.settingBuyMeCoffee.pop() @@ -905,7 +905,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene if (MAL.token != null) { bindingAccounts.settingsMALLogin.setText(R.string.logout) bindingAccounts.settingsMALLogin.setOnClickListener { - MAL.removeSavedToken(it.context) + MAL.removeSavedToken() restartMainActivity.isEnabled = true reload() } @@ -1060,7 +1060,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene box?.setSingleLine() val dialog = AlertDialog.Builder(this, R.style.MyPopup) - .setTitle("Enter Password") + .setTitle(getString(R.string.enter_password)) .setView(dialogView) .setPositiveButton("OK", null) .setNegativeButton("Cancel") { dialog, _ -> @@ -1076,7 +1076,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene dialog.dismiss() callback(password) } else { - toast("Password cannot be empty") + toast(getString(R.string.password_cannot_be_empty)) } } box?.setOnEditorActionListener { _, actionId, _ -> @@ -1090,7 +1090,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene val subtitleTextView = dialogView.findViewById(R.id.subtitle) subtitleTextView?.visibility = View.VISIBLE if (!isExporting) - subtitleTextView?.text = "Enter your password to decrypt the file" + subtitleTextView?.text = getString(R.string.enter_password_to_decrypt_file) dialog.window?.setDimAmount(0.8f) diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsDialogFragment.kt b/app/src/main/java/ani/dantotsu/settings/SettingsDialogFragment.kt index 2efc8c7d..535b7273 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsDialogFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsDialogFragment.kt @@ -12,7 +12,6 @@ import androidx.core.content.ContextCompat import androidx.core.view.isVisible import ani.dantotsu.BottomSheetDialogFragment import ani.dantotsu.MainActivity -import ani.dantotsu.profile.ProfileActivity import ani.dantotsu.R import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.databinding.BottomSheetSettingsBinding @@ -25,13 +24,15 @@ import ani.dantotsu.home.MangaFragment import ani.dantotsu.home.NoInternet import ani.dantotsu.incognitoNotification import ani.dantotsu.loadImage -import ani.dantotsu.profile.activity.NotificationActivity import ani.dantotsu.offline.OfflineFragment +import ani.dantotsu.profile.ProfileActivity import ani.dantotsu.profile.activity.FeedActivity +import ani.dantotsu.profile.activity.NotificationActivity import ani.dantotsu.setSafeOnClickListener import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.startMainActivity +import eu.kanade.tachiyomi.util.system.getSerializableCompat import java.util.Timer import kotlin.concurrent.schedule @@ -42,7 +43,7 @@ class SettingsDialogFragment : BottomSheetDialogFragment() { private lateinit var pageType: PageType override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - pageType = arguments?.getSerializable("pageType") as? PageType ?: PageType.HOME + pageType = arguments?.getSerializableCompat("pageType") as? PageType ?: PageType.HOME } override fun onCreateView( diff --git a/app/src/main/java/ani/dantotsu/settings/paging/NovelPagingSource.kt b/app/src/main/java/ani/dantotsu/settings/paging/NovelPagingSource.kt index 46379b76..fa2bf1ae 100644 --- a/app/src/main/java/ani/dantotsu/settings/paging/NovelPagingSource.kt +++ b/app/src/main/java/ani/dantotsu/settings/paging/NovelPagingSource.kt @@ -41,13 +41,14 @@ import kotlinx.coroutines.withContext class NovelExtensionsViewModelFactory( private val novelExtensionManager: NovelExtensionManager ) : ViewModelProvider.Factory { + @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T { return NovelExtensionsViewModel(novelExtensionManager) as T } } class NovelExtensionsViewModel( - private val novelExtensionManager: NovelExtensionManager + novelExtensionManager: NovelExtensionManager ) : ViewModel() { private val searchQuery = MutableStateFlow("") private var currentPagingSource: NovelExtensionPagingSource? = null @@ -102,21 +103,20 @@ class NovelExtensionPagingSource( } else { availableExtensions.filter { it.name.contains(query, ignoreCase = true) } } - val filternfsw = filteredExtensions /*val filternfsw = if(isNsfwEnabled) { currently not implemented filteredExtensions } else { filteredExtensions.filterNot { it.isNsfw } }*/ return try { - val sublist = filternfsw.subList( + val sublist = filteredExtensions.subList( fromIndex = position, - toIndex = (position + params.loadSize).coerceAtMost(filternfsw.size) + toIndex = (position + params.loadSize).coerceAtMost(filteredExtensions.size) ) LoadResult.Page( data = sublist, prevKey = if (position == 0) null else position - params.loadSize, - nextKey = if (position + params.loadSize >= filternfsw.size) null else position + params.loadSize + nextKey = if (position + params.loadSize >= filteredExtensions.size) null else position + params.loadSize ) } catch (e: Exception) { LoadResult.Error(e) diff --git a/app/src/main/java/ani/dantotsu/util/AniMarkdown.kt b/app/src/main/java/ani/dantotsu/util/AniMarkdown.kt index 6bac3fcc..54cd0dff 100644 --- a/app/src/main/java/ani/dantotsu/util/AniMarkdown.kt +++ b/app/src/main/java/ani/dantotsu/util/AniMarkdown.kt @@ -6,7 +6,7 @@ import ani.dantotsu.util.ColorEditor.Companion.toHexColor class AniMarkdown { //istg anilist has the worst api companion object { private fun convertNestedImageToHtml(markdown: String): String { - val regex = """\[\!\[(.*?)\]\((.*?)\)\]\((.*?)\)""".toRegex() + val regex = """\[!\[(.*?)]\((.*?)\)]\((.*?)\)""".toRegex() return regex.replace(markdown) { matchResult -> val altText = matchResult.groupValues[1] val imageUrl = matchResult.groupValues[2] @@ -16,7 +16,7 @@ class AniMarkdown { //istg anilist has the worst api } private fun convertImageToHtml(markdown: String): String { - val regex = """\!\[(.*?)\]\((.*?)\)""".toRegex() + val regex = """!\[(.*?)]\((.*?)\)""".toRegex() return regex.replace(markdown) { matchResult -> val altText = matchResult.groupValues[1] val imageUrl = matchResult.groupValues[2] @@ -25,7 +25,7 @@ class AniMarkdown { //istg anilist has the worst api } private fun convertLinkToHtml(markdown: String): String { - val regex = """\[(.*?)\]\((.*?)\)""".toRegex() + val regex = """\[(.*?)]\((.*?)\)""".toRegex() return regex.replace(markdown) { matchResult -> val linkText = matchResult.groupValues[1] val linkUrl = matchResult.groupValues[2] @@ -50,7 +50,7 @@ class AniMarkdown { //istg anilist has the worst api private fun underlineToHtml(html: String): String { return html.replace("(?s)___(.*?)___".toRegex(), "
$1
") .replace("(?s)__(.*?)__".toRegex(), "
$1
") - .replace("(?s)[\\s]+_([^_]+)_[\\s]+".toRegex(), "$1") + .replace("(?s)\\s+_([^_]+)_\\s+".toRegex(), "$1") } fun getBasicAniHTML(html: String): String { diff --git a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsFactory.kt b/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsFactory.kt index 75f35588..8cf8029a 100644 --- a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsFactory.kt +++ b/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsFactory.kt @@ -1,7 +1,6 @@ package ani.dantotsu.widgets import android.content.Context -import android.content.Intent import android.graphics.Bitmap import android.graphics.BitmapFactory import android.widget.RemoteViews @@ -12,7 +11,7 @@ import java.io.InputStream import java.net.HttpURLConnection import java.net.URL -class CurrentlyAiringRemoteViewsFactory(private val context: Context, intent: Intent) : +class CurrentlyAiringRemoteViewsFactory(private val context: Context) : RemoteViewsService.RemoteViewsFactory { private var widgetItems = mutableListOf() diff --git a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsService.kt b/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsService.kt index a0ff2efc..4d042b33 100644 --- a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsService.kt +++ b/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsService.kt @@ -7,6 +7,6 @@ import ani.dantotsu.util.Logger class CurrentlyAiringRemoteViewsService : RemoteViewsService() { override fun onGetViewFactory(intent: Intent): RemoteViewsFactory { Logger.log("CurrentlyAiringRemoteViewsFactory onGetViewFactory") - return CurrentlyAiringRemoteViewsFactory(applicationContext, intent) + return CurrentlyAiringRemoteViewsFactory(applicationContext) } } diff --git a/app/src/main/java/eu/kanade/domain/base/ExtensionInstallerPreference.kt b/app/src/main/java/eu/kanade/domain/base/ExtensionInstallerPreference.kt index e9a5c3a7..a52789f5 100644 --- a/app/src/main/java/eu/kanade/domain/base/ExtensionInstallerPreference.kt +++ b/app/src/main/java/eu/kanade/domain/base/ExtensionInstallerPreference.kt @@ -20,7 +20,7 @@ class ExtensionInstallerPreference( val entries - get() = ExtensionInstaller.values().run { + get() = ExtensionInstaller.entries.toTypedArray().run { if (context.hasMiuiPackageInstaller) { filter { it != ExtensionInstaller.PACKAGEINSTALLER } } else { diff --git a/app/src/main/java/eu/kanade/tachiyomi/animesource/AnimeSource.kt b/app/src/main/java/eu/kanade/tachiyomi/animesource/AnimeSource.kt index 53da5305..171b07b2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/animesource/AnimeSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/animesource/AnimeSource.kt @@ -58,8 +58,7 @@ interface AnimeSource { */ @Suppress("DEPRECATION") suspend fun getVideoList(episode: SEpisode): List