mirror of
https://github.com/rebelonion/Dantotsu.git
synced 2026-01-20 07:53:56 +00:00
chore: execute lint inspection
address issues from lint inspection convert string literals to resources merge extension & download type
This commit is contained in:
@@ -5,7 +5,6 @@ import com.google.firebase.FirebaseApp
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.google.firebase.crashlytics.ktx.crashlytics
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import com.google.firebase.ktx.app
|
||||
|
||||
class FirebaseCrashlytics : CrashlyticsInterface {
|
||||
override fun initialize(context: Context) {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
android:maxSdkVersion="29" />
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" /> <!-- For background jobs -->
|
||||
@@ -52,11 +52,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">
|
||||
<receiver
|
||||
android:name=".widgets.CurrentlyAiringWidget"
|
||||
android:exported="false">
|
||||
@@ -278,11 +280,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="eu.kanade.tachiyomi.extension.manga.util.MangaExtensionInstallActivity"
|
||||
android:exported="false"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
||||
<activity
|
||||
android:name="eu.kanade.tachiyomi.extension.anime.util.AnimeExtensionInstallActivity"
|
||||
android:name="eu.kanade.tachiyomi.extension.util.ExtensionInstallActivity"
|
||||
android:exported="false"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
||||
|
||||
@@ -325,11 +323,7 @@
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service
|
||||
android:name="eu.kanade.tachiyomi.extension.manga.util.MangaExtensionInstallService"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="dataSync" />
|
||||
<service
|
||||
android:name="eu.kanade.tachiyomi.extension.anime.util.AnimeExtensionInstallService"
|
||||
android:name="eu.kanade.tachiyomi.extension.util.ExtensionInstallService"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="dataSync" />
|
||||
<service
|
||||
|
||||
@@ -89,7 +89,7 @@ class App : MultiDexApplication() {
|
||||
Logger.init(this)
|
||||
Thread.setDefaultUncaughtExceptionHandler(FinalExceptionHandler())
|
||||
|
||||
initializeNetwork(baseContext)
|
||||
initializeNetwork()
|
||||
|
||||
setupNotificationChannels()
|
||||
if (!LogcatLogger.isInstalled) {
|
||||
|
||||
@@ -101,7 +101,6 @@ import java.lang.reflect.Field
|
||||
import java.util.*
|
||||
import kotlin.math.*
|
||||
|
||||
|
||||
var statusBarHeight = 0
|
||||
var navBarHeight = 0
|
||||
val Int.dp: Float get() = (this / getSystem().displayMetrics.density)
|
||||
@@ -289,7 +288,7 @@ class DatePickerFragment(activity: Activity, var date: FuzzyDate = FuzzyDate().g
|
||||
dialog.setButton(
|
||||
DialogInterface.BUTTON_NEUTRAL,
|
||||
activity.getString(R.string.remove)
|
||||
) { dialog, which ->
|
||||
) { _, which ->
|
||||
if (which == DialogInterface.BUTTON_NEUTRAL) {
|
||||
date = FuzzyDate()
|
||||
}
|
||||
@@ -337,7 +336,7 @@ class InputFilterMinMax(
|
||||
}
|
||||
|
||||
|
||||
class ZoomOutPageTransformer() :
|
||||
class ZoomOutPageTransformer :
|
||||
ViewPager2.PageTransformer {
|
||||
override fun transformPage(view: View, position: Float) {
|
||||
if (position == 0.0f && PrefManager.getVal(PrefName.LayoutAnimations)) {
|
||||
|
||||
@@ -91,16 +91,16 @@ class MainActivity : AppCompatActivity() {
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
val _bottomBar = findViewById<AnimatedBottomBar>(R.id.navbar)
|
||||
val bottomNavBar = findViewById<AnimatedBottomBar>(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")
|
||||
@@ -269,7 +269,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
|
||||
@@ -294,7 +294,7 @@ class MainActivity : AppCompatActivity() {
|
||||
mainViewPager.setCurrentItem(newIndex, false)
|
||||
}
|
||||
})
|
||||
if (mainViewPager.getCurrentItem() != selectedOption) {
|
||||
if (mainViewPager.currentItem != selectedOption) {
|
||||
navbar.selectTabAt(selectedOption)
|
||||
mainViewPager.post {
|
||||
mainViewPager.setCurrentItem(
|
||||
|
||||
@@ -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<String, String>
|
||||
lateinit var okHttpClient: OkHttpClient
|
||||
lateinit var client: Requests
|
||||
|
||||
fun initializeNetwork(context: Context) {
|
||||
fun initializeNetwork() {
|
||||
|
||||
val networkHelper = Injekt.get<NetworkHelper>()
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.source.anime.AndroidAnimeSourceManager
|
||||
import eu.kanade.tachiyomi.source.manga.AndroidMangaSourceManager
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.domain.source.anime.service.AnimeSourceManager
|
||||
@@ -29,7 +30,7 @@ import uy.kohesive.injekt.api.addSingletonFactory
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class AppModule(val app: Application) : InjektModule {
|
||||
@OptIn(UnstableApi::class)
|
||||
@OptIn(UnstableApi::class) @kotlin.OptIn(ExperimentalSerializationApi::class)
|
||||
override fun InjektRegistrar.registerInjectables() {
|
||||
addSingleton(app)
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package ani.dantotsu.connections.anilist
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.client
|
||||
@@ -13,7 +12,6 @@ import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.tryWithSuspend
|
||||
import ani.dantotsu.util.Logger
|
||||
import java.util.Calendar
|
||||
|
||||
|
||||
@@ -337,6 +337,7 @@ class AnilistQueries {
|
||||
returnArray.addAll(map.values)
|
||||
return returnArray
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val list = PrefManager.getNullableCustomVal(
|
||||
"continueAnimeList",
|
||||
listOf<Int>(),
|
||||
@@ -494,6 +495,7 @@ class AnilistQueries {
|
||||
returnMap["current$type"] = returnArray
|
||||
return
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val list = PrefManager.getNullableCustomVal(
|
||||
"continueAnimeList",
|
||||
listOf<Int>(),
|
||||
@@ -523,6 +525,7 @@ class AnilistQueries {
|
||||
subMap[m.id] = m
|
||||
}
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val list = PrefManager.getNullableCustomVal(
|
||||
"continueAnimeList",
|
||||
listOf<Int>(),
|
||||
@@ -684,7 +687,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) {
|
||||
|
||||
@@ -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<SearchResults?> = animePopular
|
||||
suspend fun loadPopular(
|
||||
type: String,
|
||||
search_val: String? = null,
|
||||
searchVal: String? = null,
|
||||
genres: ArrayList<String>? = 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<SearchResults?> = mangaPopular
|
||||
suspend fun loadPopular(
|
||||
type: String,
|
||||
search_val: String? = null,
|
||||
searchVal: String? = null,
|
||||
genres: ArrayList<String>? = 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
|
||||
|
||||
@@ -80,9 +80,9 @@ data class Notification(
|
||||
@SerialName("createdAt")
|
||||
val createdAt: Int,
|
||||
@SerialName("media")
|
||||
val media: ani.dantotsu.connections.anilist.api.Media?,
|
||||
val media: Media?,
|
||||
@SerialName("user")
|
||||
val user: ani.dantotsu.connections.anilist.api.User?,
|
||||
val user: User?,
|
||||
@SerialName("message")
|
||||
val message: MessageActivity?,
|
||||
@SerialName("activity")
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ object Discord {
|
||||
"Dantotsu",
|
||||
small_Image
|
||||
)
|
||||
buttons.add(RPC.Link("Stream on Dantotsu", "https://github.com/rebelonion/Dantotsu/"))
|
||||
buttons.add(RPC.Link("Stream on Dantotsu", getString(R.string.github)))
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@@ -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) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import kotlinx.serialization.json.Json
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import ani.dantotsu.client as app
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
open class RPC(val token: String, val coroutineContext: CoroutineContext) {
|
||||
|
||||
private val json = Json {
|
||||
|
||||
@@ -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<ResponseToken>(PrefName.MALToken, null)
|
||||
@@ -77,7 +76,7 @@ object MAL {
|
||||
} ?: false
|
||||
}
|
||||
|
||||
fun removeSavedToken(context: Context) {
|
||||
fun removeSavedToken() {
|
||||
token = null
|
||||
username = null
|
||||
userid = null
|
||||
|
||||
@@ -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<DownloadedType>
|
||||
get() = downloadsList.filter { it.type == DownloadedType.Type.MANGA }
|
||||
get() = downloadsList.filter { it.type == MediaType.MANGA }
|
||||
val animeDownloadedTypes: List<DownloadedType>
|
||||
get() = downloadsList.filter { it.type == DownloadedType.Type.ANIME }
|
||||
get() = downloadsList.filter { it.type == MediaType.ANIME }
|
||||
val novelDownloadedTypes: List<DownloadedType>
|
||||
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
|
||||
|
||||
@@ -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
|
||||
@@ -241,7 +242,7 @@ class AnimeDownloaderService : Service() {
|
||||
DownloadedType(
|
||||
task.title,
|
||||
task.episode,
|
||||
DownloadedType.Type.ANIME,
|
||||
MediaType.ANIME,
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -272,7 +273,7 @@ class AnimeDownloaderService : Service() {
|
||||
DownloadedType(
|
||||
task.title,
|
||||
task.episode,
|
||||
DownloadedType.Type.ANIME,
|
||||
MediaType.ANIME,
|
||||
)
|
||||
)
|
||||
Injekt.get<CrashlyticsInterface>().logException(
|
||||
@@ -301,7 +302,7 @@ class AnimeDownloaderService : Service() {
|
||||
DownloadedType(
|
||||
task.title,
|
||||
task.episode,
|
||||
DownloadedType.Type.ANIME,
|
||||
MediaType.ANIME,
|
||||
)
|
||||
)
|
||||
currentTasks.removeAll { it.getTaskName() == task.getTaskName() }
|
||||
|
||||
@@ -17,7 +17,7 @@ import ani.dantotsu.settings.saving.PrefName
|
||||
|
||||
|
||||
class OfflineAnimeAdapter(
|
||||
private val context: Context,
|
||||
context: Context,
|
||||
private var items: List<OfflineAnimeModel>,
|
||||
private val searchListener: OfflineAnimeSearchListener
|
||||
) : BaseAdapter() {
|
||||
|
||||
@@ -33,15 +33,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
|
||||
@@ -187,8 +188,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 =
|
||||
@@ -292,11 +292,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}"
|
||||
@@ -326,11 +322,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}"
|
||||
|
||||
@@ -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
|
||||
@@ -209,8 +210,7 @@ class MangaDownloaderService : Service() {
|
||||
while (bitmap == null && retryCount < task.retries) {
|
||||
bitmap = image.fetchAndProcessImage(
|
||||
image.page,
|
||||
image.source,
|
||||
this@MangaDownloaderService
|
||||
image.source
|
||||
)
|
||||
retryCount++
|
||||
}
|
||||
@@ -244,7 +244,7 @@ class MangaDownloaderService : Service() {
|
||||
DownloadedType(
|
||||
task.title,
|
||||
task.chapter,
|
||||
DownloadedType.Type.MANGA
|
||||
MediaType.MANGA
|
||||
)
|
||||
)
|
||||
broadcastDownloadFinished(task.chapter)
|
||||
|
||||
@@ -16,7 +16,7 @@ import ani.dantotsu.settings.saving.PrefName
|
||||
|
||||
|
||||
class OfflineMangaAdapter(
|
||||
private val context: Context,
|
||||
context: Context,
|
||||
private var items: List<OfflineMangaModel>,
|
||||
private val searchListener: OfflineMangaSearchListener
|
||||
) : BaseAdapter() {
|
||||
|
||||
@@ -30,15 +30,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
|
||||
@@ -178,11 +179,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 =
|
||||
@@ -288,11 +289,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}"
|
||||
@@ -316,11 +313,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}"
|
||||
|
||||
@@ -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
|
||||
@@ -333,7 +334,7 @@ class NovelDownloaderService : Service() {
|
||||
DownloadedType(
|
||||
task.title,
|
||||
task.chapter,
|
||||
DownloadedType.Type.NOVEL
|
||||
MediaType.NOVEL
|
||||
)
|
||||
)
|
||||
broadcastDownloadFinished(task.originalLink)
|
||||
|
||||
@@ -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<DownloadsManager>()
|
||||
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)
|
||||
|
||||
@@ -167,8 +167,7 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
||||
|
||||
trendHandler = Handler(Looper.getMainLooper())
|
||||
trendRun = Runnable {
|
||||
binding.animeTrendingViewPager.currentItem =
|
||||
binding.animeTrendingViewPager.currentItem + 1
|
||||
binding.animeTrendingViewPager.currentItem += 1
|
||||
}
|
||||
binding.animeTrendingViewPager.registerOnPageChangeCallback(
|
||||
object : ViewPager2.OnPageChangeCallback() {
|
||||
|
||||
@@ -50,7 +50,7 @@ class LoginFragment : Fragment() {
|
||||
DocumentFile.fromSingleUri(requireActivity(), uri)?.name ?: "settings"
|
||||
//.sani is encrypted, .ani is not
|
||||
if (name.endsWith(".sani")) {
|
||||
passwordAlertDialog() { password ->
|
||||
passwordAlertDialog { password ->
|
||||
if (password != null) {
|
||||
val salt = jsonString.copyOfRange(0, 16)
|
||||
val encrypted = jsonString.copyOfRange(16, jsonString.size)
|
||||
|
||||
@@ -65,8 +65,8 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
|
||||
currContext()?.theme?.resolveAttribute(android.R.attr.windowBackground, typedValue, true)
|
||||
val color = typedValue.data
|
||||
|
||||
textInputLayout.boxBackgroundColor = (color and 0x00FFFFFF) or 0x28000000.toInt()
|
||||
materialCardView.setCardBackgroundColor((color and 0x00FFFFFF) or 0x28000000.toInt())
|
||||
textInputLayout.boxBackgroundColor = (color and 0x00FFFFFF) or 0x28000000
|
||||
materialCardView.setCardBackgroundColor((color and 0x00FFFFFF) or 0x28000000)
|
||||
|
||||
binding.mangaTitleContainer.updatePadding(top = statusBarHeight)
|
||||
|
||||
|
||||
@@ -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.core.content.ContextCompat
|
||||
@@ -16,8 +15,8 @@ import androidx.lifecycle.lifecycleScope
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.Refresh
|
||||
import ani.dantotsu.databinding.ActivityListBinding
|
||||
import ani.dantotsu.hideSystemBarsExtendView
|
||||
import ani.dantotsu.media.user.ListViewPagerAdapter
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.statusBarHeight
|
||||
@@ -74,10 +73,7 @@ class CalendarActivity : 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<ViewGroup.MarginLayoutParams> {
|
||||
topMargin = statusBarHeight
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package ani.dantotsu.media
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
@@ -15,25 +13,24 @@ import android.widget.ImageView
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.app.ActivityOptionsCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.util.Pair
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.blurImage
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.databinding.ItemMediaCompactBinding
|
||||
import ani.dantotsu.databinding.ItemMediaLargeBinding
|
||||
import ani.dantotsu.databinding.ItemMediaPageBinding
|
||||
import ani.dantotsu.databinding.ItemMediaPageSmallBinding
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.setSafeOnClickListener
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.flaviofaria.kenburnsview.RandomTransitionGenerator
|
||||
import jp.wasabeef.glide.transformations.BlurTransformation
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@ 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.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.util.TypedValue
|
||||
@@ -12,9 +10,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
|
||||
@@ -246,13 +242,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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ package ani.dantotsu.media
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.CountDownTimer
|
||||
import android.view.LayoutInflater
|
||||
@@ -22,10 +20,24 @@ import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.connections.anilist.GenresViewModel
|
||||
import ani.dantotsu.databinding.*
|
||||
import ani.dantotsu.copyToClipboard
|
||||
import ani.dantotsu.countDown
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.databinding.ActivityGenreBinding
|
||||
import ani.dantotsu.databinding.FragmentMediaInfoBinding
|
||||
import ani.dantotsu.databinding.ItemChipBinding
|
||||
import ani.dantotsu.databinding.ItemQuelsBinding
|
||||
import ani.dantotsu.databinding.ItemTitleChipgroupBinding
|
||||
import ani.dantotsu.databinding.ItemTitleRecyclerBinding
|
||||
import ani.dantotsu.databinding.ItemTitleTextBinding
|
||||
import ani.dantotsu.databinding.ItemTitleTrailerBinding
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.setSafeOnClickListener
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import io.noties.markwon.Markwon
|
||||
@@ -524,23 +536,21 @@ class MediaInfoFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
val cornerTop = ObjectAnimator.ofFloat(binding.root, "radius", 0f, 32f).setDuration(200)
|
||||
val cornerNotTop =
|
||||
ObjectAnimator.ofFloat(binding.root, "radius", 32f, 0f).setDuration(200)
|
||||
var cornered = true
|
||||
cornerTop.start()
|
||||
binding.mediaInfoScroll.setOnScrollChangeListener { v, _, _, _, _ ->
|
||||
if (!v.canScrollVertically(-1)) {
|
||||
if (!cornered) {
|
||||
cornered = true
|
||||
cornerTop.start()
|
||||
}
|
||||
} else {
|
||||
if (cornered) {
|
||||
cornered = false
|
||||
cornerNotTop.start()
|
||||
}
|
||||
val cornerTop = ObjectAnimator.ofFloat(binding.root, "radius", 0f, 32f).setDuration(200)
|
||||
val cornerNotTop =
|
||||
ObjectAnimator.ofFloat(binding.root, "radius", 32f, 0f).setDuration(200)
|
||||
var cornered = true
|
||||
cornerTop.start()
|
||||
binding.mediaInfoScroll.setOnScrollChangeListener { v, _, _, _, _ ->
|
||||
if (!v.canScrollVertically(-1)) {
|
||||
if (!cornered) {
|
||||
cornered = true
|
||||
cornerTop.start()
|
||||
}
|
||||
} else {
|
||||
if (cornered) {
|
||||
cornered = false
|
||||
cornerNotTop.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26
app/src/main/java/ani/dantotsu/media/MediaType.kt
Normal file
26
app/src/main/java/ani/dantotsu/media/MediaType.kt
Normal file
@@ -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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,17 +11,21 @@ import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.connections.anilist.AnilistSearch
|
||||
import ani.dantotsu.connections.anilist.SearchResults
|
||||
import ani.dantotsu.databinding.ActivitySearchBinding
|
||||
import ani.dantotsu.initActivity
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
import java.util.Timer
|
||||
import java.util.TimerTask
|
||||
|
||||
class SearchActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivitySearchBinding
|
||||
|
||||
@@ -15,7 +15,6 @@ import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.HORIZONTAL
|
||||
@@ -28,7 +27,9 @@ import ani.dantotsu.openLinkInBrowser
|
||||
import ani.dantotsu.others.imagesearch.ImageSearchActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import com.google.android.material.checkbox.MaterialCheckBox.*
|
||||
import com.google.android.material.checkbox.MaterialCheckBox.STATE_CHECKED
|
||||
import com.google.android.material.checkbox.MaterialCheckBox.STATE_INDETERMINATE
|
||||
import com.google.android.material.checkbox.MaterialCheckBox.STATE_UNCHECKED
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@@ -14,7 +14,7 @@ import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.settings.saving.SharedPreferenceStringSetLiveData
|
||||
import java.util.Locale
|
||||
|
||||
class SearchHistoryAdapter(private val type: String, private val searchClicked: (String) -> Unit) :
|
||||
class SearchHistoryAdapter(type: String, private val searchClicked: (String) -> Unit) :
|
||||
ListAdapter<String, SearchHistoryAdapter.SearchHistoryViewHolder>(
|
||||
DIFF_CALLBACK_INSTALLED
|
||||
) {
|
||||
|
||||
@@ -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!!]
|
||||
|
||||
@@ -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<NetworkHelper>()
|
||||
@@ -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()
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.util.regex.Pattern
|
||||
class AnimeNameAdapter {
|
||||
companion object {
|
||||
const val episodeRegex =
|
||||
"(episode|ep|e)[\\s:.\\-]*([\\d]+\\.?[\\d]*)[\\s:.\\-]*\\(?\\s*(sub|subbed|dub|dubbed)*\\s*\\)?\\s*"
|
||||
"(episode|ep|e)[\\s:.\\-]*(\\d+\\.?\\d*)[\\s:.\\-]*\\(?\\s*(sub|subbed|dub|dubbed)*\\s*\\)?\\s*"
|
||||
const val failedEpisodeNumberRegex =
|
||||
"(?<!part\\s)\\b(\\d+)\\b"
|
||||
const val seasonRegex = "(season|s)[\\s:.\\-]*(\\d+)[\\s:.\\-]*"
|
||||
@@ -114,7 +114,7 @@ class AnimeNameAdapter {
|
||||
val regexPattern = Regex(episodeRegex, RegexOption.IGNORE_CASE)
|
||||
val removedNumber = text.replace(regexPattern, "")
|
||||
return if (removedNumber.equals(text, true)) { // if nothing was removed
|
||||
val failedEpisodeNumberPattern: Regex =
|
||||
val failedEpisodeNumberPattern =
|
||||
Regex(failedEpisodeNumberRegex, RegexOption.IGNORE_CASE)
|
||||
failedEpisodeNumberPattern.replace(removedNumber) { mr ->
|
||||
mr.value.replaceFirst(mr.groupValues[1], "")
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import ani.dantotsu.settings.FAQActivity
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.ImageButton
|
||||
@@ -15,11 +14,15 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.connections.comments.CommentsAPI
|
||||
import ani.dantotsu.FileUrl
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.countDown
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.databinding.DialogLayoutBinding
|
||||
import ani.dantotsu.databinding.ItemAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.ItemChipBinding
|
||||
import ani.dantotsu.isOnline
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.SourceSearchDialogFragment
|
||||
@@ -28,10 +31,13 @@ import ani.dantotsu.others.webview.CookieCatcher
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.DynamicAnimeParser
|
||||
import ani.dantotsu.parsers.WatchSources
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.settings.FAQActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.subcriptions.Notifications.Companion.openSettings
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
|
||||
import ani.dantotsu.toast
|
||||
import com.google.android.material.chip.Chip
|
||||
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
|
||||
import eu.kanade.tachiyomi.util.system.WebViewUtil
|
||||
|
||||
@@ -27,29 +27,34 @@ 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
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.subcriptions.Notifications
|
||||
import ani.dantotsu.subcriptions.Notifications.Group.ANIME_GROUP
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
|
||||
import ani.dantotsu.subcriptions.SubscriptionHelper
|
||||
import ani.dantotsu.subcriptions.SubscriptionHelper.Companion.saveSubscription
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.navigationrail.NavigationRailView
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -448,7 +453,7 @@ class AnimeWatchFragment : Fragment() {
|
||||
DownloadedType(
|
||||
media.mainName(),
|
||||
i,
|
||||
DownloadedType.Type.ANIME
|
||||
MediaType.ANIME
|
||||
)
|
||||
)
|
||||
episodeAdapter.purgeDownload(i)
|
||||
@@ -460,7 +465,7 @@ class AnimeWatchFragment : Fragment() {
|
||||
DownloadedType(
|
||||
media.mainName(),
|
||||
i,
|
||||
DownloadedType.Type.ANIME
|
||||
MediaType.ANIME
|
||||
)
|
||||
)
|
||||
val taskName = AnimeDownloaderService.AnimeDownloadTask.getTaskName(media.mainName(), i)
|
||||
|
||||
@@ -12,14 +12,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
|
||||
@@ -429,7 +431,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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -941,7 +995,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||
episodeArr = episodes.keys.toList()
|
||||
currentEpisodeIndex = episodeArr.indexOf(media.anime!!.selectedEpisode!!)
|
||||
|
||||
episodeTitleArr = arrayListOf<String>()
|
||||
episodeTitleArr = arrayListOf()
|
||||
episodes.forEach {
|
||||
val episode = it.value
|
||||
val cleanedTitle = AnimeNameAdapter.removeEpisodeNumberCompletely(episode.title ?: "")
|
||||
@@ -1052,7 +1106,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)
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -1264,6 +1318,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||
media.anime!!.selectedEpisode!!
|
||||
)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val list = (PrefManager.getNullableCustomVal("continueAnimeList", listOf<Int>(), List::class.java) as List<Int>).toMutableList()
|
||||
if (list.contains(media.id)) list.remove(media.id)
|
||||
list.add(media.id)
|
||||
@@ -1301,9 +1356,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)
|
||||
@@ -1358,8 +1412,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) {
|
||||
@@ -1735,28 +1788,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)) {
|
||||
|
||||
@@ -17,20 +17,28 @@ import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.BottomSheetDialogFragment
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.copyToClipboard
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.databinding.BottomSheetSelectorBinding
|
||||
import ani.dantotsu.databinding.ItemStreamBinding
|
||||
import ani.dantotsu.databinding.ItemUrlBinding
|
||||
import ani.dantotsu.download.video.Helper
|
||||
import ani.dantotsu.hideSystemBars
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.others.Download.download
|
||||
import ani.dantotsu.parsers.Subtitle
|
||||
import ani.dantotsu.parsers.VideoExtractor
|
||||
import ani.dantotsu.parsers.VideoType
|
||||
import ani.dantotsu.setSafeOnClickListener
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.tryWith
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -336,7 +344,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
||||
.setSingleChoiceItems(
|
||||
subtitleNames.toTypedArray(),
|
||||
-1
|
||||
) { dialog, which ->
|
||||
) { _, which ->
|
||||
subtitleToDownload = subtitles[which]
|
||||
}
|
||||
.setPositiveButton("Download") { _, _ ->
|
||||
|
||||
@@ -28,9 +28,9 @@ 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.pow
|
||||
import kotlin.math.sqrt
|
||||
|
||||
class CommentItem(val comment: Comment,
|
||||
@@ -242,6 +242,7 @@ class CommentItem(val comment: Comment,
|
||||
|
||||
private fun removeSubCommentIds(){
|
||||
subCommentIds.forEach { id ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val parentComments = parentSection.groups as? List<CommentItem> ?: emptyList()
|
||||
val commentToRemove = parentComments.find { it.comment.commentId == id }
|
||||
commentToRemove?.let {
|
||||
@@ -273,7 +274,7 @@ class CommentItem(val comment: Comment,
|
||||
|
||||
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()
|
||||
@@ -297,7 +298,7 @@ class CommentItem(val comment: Comment,
|
||||
|
||||
companion object {
|
||||
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
|
||||
|
||||
@@ -13,7 +13,6 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
@@ -274,7 +273,7 @@ class CommentsFragment : Fragment() {
|
||||
|
||||
activity.binding.commentLabel.setOnClickListener {
|
||||
//alert dialog to enter a number, with a cancel and ok button
|
||||
val alertDialog = android.app.AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
.setTitle("Enter a chapter/episode number tag")
|
||||
.setView(R.layout.dialog_edittext)
|
||||
.setPositiveButton("OK") { dialog, _ ->
|
||||
@@ -542,7 +541,7 @@ class CommentsFragment : Fragment() {
|
||||
* Called when the user tries to comment for the first time
|
||||
*/
|
||||
private fun showCommentRulesDialog() {
|
||||
val alertDialog = android.app.AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
.setTitle("Commenting Rules")
|
||||
.setMessage(
|
||||
"I WILL BAN YOU WITHOUT HESITATION\n" +
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -17,11 +17,11 @@ import ani.dantotsu.databinding.ItemChapterListBinding
|
||||
import ani.dantotsu.databinding.ItemEpisodeCompactBinding
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.setAnimation
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MangaChapterAdapter(
|
||||
private var type: Int,
|
||||
|
||||
@@ -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 = "(?<!part\\s)\\b(\\d+)\\b"
|
||||
private const val chapterRegex = "(chapter|chap|ch|c)[\\s:.\\-]*(\\d+\\.?\\d*)[\\s:.\\-]*"
|
||||
private const val filedChapterNumberRegex = "(?<!part\\s)\\b(\\d+)\\b"
|
||||
fun findChapterNumber(text: String): Float? {
|
||||
val pattern: Pattern = Pattern.compile(chapterRegex, Pattern.CASE_INSENSITIVE)
|
||||
val matcher: Matcher = pattern.matcher(text)
|
||||
|
||||
@@ -13,14 +13,16 @@ import android.widget.LinearLayout
|
||||
import android.widget.NumberPicker
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.core.view.children
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.connections.comments.CommentsAPI
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.DialogLayoutBinding
|
||||
import ani.dantotsu.databinding.ItemAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.ItemChipBinding
|
||||
import ani.dantotsu.isOnline
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.SourceSearchDialogFragment
|
||||
@@ -30,11 +32,13 @@ import ani.dantotsu.others.webview.CookieCatcher
|
||||
import ani.dantotsu.parsers.DynamicMangaParser
|
||||
import ani.dantotsu.parsers.MangaReadSources
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.settings.FAQActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.subcriptions.Notifications.Companion.openSettings
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
|
||||
import ani.dantotsu.toast
|
||||
import com.google.android.material.chip.Chip
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.util.system.WebViewUtil
|
||||
@@ -226,7 +230,7 @@ class MangaReadAdapter(
|
||||
refresh = true
|
||||
val intent = Intent(fragment.requireContext(), CookieCatcher::class.java)
|
||||
.putExtra("url", url)
|
||||
ContextCompat.startActivity(fragment.requireContext(), intent, null)
|
||||
startActivity(fragment.requireContext(), intent, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,31 +28,35 @@ 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.R
|
||||
import ani.dantotsu.databinding.FragmentAnimeWatchBinding
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.manga.MangaDownloaderService
|
||||
import ani.dantotsu.download.manga.MangaServiceDataSingleton
|
||||
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.media.manga.mangareader.ChapterLoaderDialog
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.others.LanguageMapper
|
||||
import ani.dantotsu.parsers.DynamicMangaParser
|
||||
import ani.dantotsu.parsers.HMangaSources
|
||||
import ani.dantotsu.parsers.MangaParser
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
import ani.dantotsu.setNavigationTheme
|
||||
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.subcriptions.Notifications
|
||||
import ani.dantotsu.subcriptions.Notifications.Group.MANGA_GROUP
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
|
||||
import ani.dantotsu.subcriptions.SubscriptionHelper
|
||||
import ani.dantotsu.subcriptions.SubscriptionHelper.Companion.saveSubscription
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.navigationrail.NavigationRailView
|
||||
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -505,7 +509,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
||||
DownloadedType(
|
||||
media.mainName(),
|
||||
i,
|
||||
DownloadedType.Type.MANGA
|
||||
MediaType.MANGA
|
||||
)
|
||||
)
|
||||
chapterAdapter.deleteDownload(i)
|
||||
@@ -523,7 +527,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
||||
DownloadedType(
|
||||
media.mainName(),
|
||||
i,
|
||||
DownloadedType.Type.MANGA
|
||||
MediaType.MANGA
|
||||
)
|
||||
)
|
||||
chapterAdapter.purgeDownload(i)
|
||||
|
||||
@@ -13,10 +13,14 @@ import androidx.core.view.GestureDetectorCompat
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.FileUrl
|
||||
import ani.dantotsu.GesturesListener
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.media.manga.MangaCache
|
||||
import ani.dantotsu.media.manga.MangaChapter
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.settings.CurrentReaderSettings
|
||||
import ani.dantotsu.tryWithSuspend
|
||||
import com.alexvasilkov.gestures.views.GestureFrameLayout
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
@@ -118,13 +122,13 @@ abstract class BaseImageAdapter(
|
||||
abstract suspend fun loadImage(position: Int, parent: View): Boolean
|
||||
|
||||
companion object {
|
||||
suspend fun Context.loadBitmap_old(
|
||||
suspend fun Context.loadBitmapOld(
|
||||
link: FileUrl,
|
||||
transforms: List<BitmapTransformation>
|
||||
): 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)
|
||||
|
||||
@@ -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
|
||||
@@ -26,7 +37,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
|
||||
@@ -34,7 +47,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
|
||||
@@ -45,14 +63,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
|
||||
@@ -65,7 +94,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<Boolean>(PrefName.ShowSystemBars))
|
||||
if (PrefManager.getVal(PrefName.ShowSystemBars))
|
||||
showSystemBarsRetractView()
|
||||
else
|
||||
hideSystemBarsExtendView()
|
||||
@@ -355,7 +384,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)
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -727,12 +756,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
|
||||
@@ -742,23 +771,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..<y) {
|
||||
pressLocation = if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) {
|
||||
pressPos.RIGHT
|
||||
PressPos.RIGHT
|
||||
} else {
|
||||
pressPos.LEFT
|
||||
PressPos.LEFT
|
||||
}
|
||||
}
|
||||
//if in the last 1/5th of the screen width, right and lower than 1/5th of the screen height, right
|
||||
else if (x > 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
|
||||
@@ -769,7 +798,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) {
|
||||
@@ -947,7 +976,7 @@ class MangaReaderActivity : AppCompatActivity() {
|
||||
if (!incognito && PrefManager.getCustomVal(
|
||||
"${media.id}_save_progress",
|
||||
true
|
||||
) && if (media.isAdult) PrefManager.getVal<Boolean>(PrefName.UpdateForHReader) else true
|
||||
) && if (media.isAdult) PrefManager.getVal(PrefName.UpdateForHReader) else true
|
||||
)
|
||||
updateProgress(
|
||||
media,
|
||||
|
||||
@@ -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
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ani.dantotsu.media.novel
|
||||
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
||||
@@ -59,7 +59,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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -72,10 +71,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<ViewGroup.MarginLayoutParams> {
|
||||
topMargin = statusBarHeight
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -7,7 +7,6 @@ import java.net.URLEncoder
|
||||
|
||||
object AniSkip {
|
||||
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
suspend fun getResult(
|
||||
malId: Int,
|
||||
episodeNumber: Int,
|
||||
|
||||
@@ -25,7 +25,6 @@ import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
|
||||
object Download {
|
||||
@Suppress("DEPRECATION")
|
||||
private fun isPackageInstalled(packageName: String, packageManager: PackageManager): Boolean {
|
||||
return try {
|
||||
packageManager.getPackageInfo(packageName, 0)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@file:Suppress("UNCHECKED_CAST", "DEPRECATION")
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package ani.dantotsu.others
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -7,6 +7,7 @@ import kotlin.math.pow
|
||||
// https://github.com/cylonu87/JsUnpacker
|
||||
// https://github.com/recloudstream/cloudstream/blob/master/app/src/main/java/com/lagradost/cloudstream3/utils/JsUnpacker.kt
|
||||
|
||||
@Suppress("unused")
|
||||
class JsUnpacker(packedJS: String?) {
|
||||
private var packedJS: String? = null
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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<String, String> = intent.getSerializableExtra("headers") as? Map<String, String> ?: emptyMap()
|
||||
val url = intent.getStringExtra("url") ?: getString(R.string.cursed_yt)
|
||||
val headers: Map<String, String> = intent.getSerializableExtraCompat("headers") as? Map<String, String> ?: emptyMap()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
val process = Application.getProcessName()
|
||||
|
||||
@@ -37,7 +37,7 @@ object AnimeSources : WatchSources() {
|
||||
}
|
||||
|
||||
fun performReorderAnimeSources() {
|
||||
//remove the downloaded source from the list to avoid duplicates
|
||||
// remove the downloaded source from the list to avoid duplicates
|
||||
list = list.filter { it.name != "Downloaded" }
|
||||
list = sortPinnedAnimeSources(list, pinnedAnimeSources) + Lazier(
|
||||
{ OfflineAnimeParser() },
|
||||
@@ -68,8 +68,6 @@ object AnimeSources : WatchSources() {
|
||||
|
||||
|
||||
object HAnimeSources : WatchSources() {
|
||||
private val aList: List<Lazier<BaseParser>> = lazyList(
|
||||
)
|
||||
|
||||
private val aList: List<Lazier<BaseParser>> = lazyList()
|
||||
override val list = listOf(aList, AnimeSources.list).flatten()
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
@@ -186,7 +184,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
|
||||
@@ -203,7 +201,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")
|
||||
}
|
||||
@@ -238,7 +236,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()
|
||||
@@ -290,7 +288,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) {
|
||||
@@ -318,7 +316,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,
|
||||
@@ -357,7 +355,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}")
|
||||
@@ -376,7 +374,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
|
||||
sourceLanguage = 0
|
||||
extension.sources[sourceLanguage]
|
||||
} as? HttpSource ?: return emptyList()
|
||||
var imageDataList: List<ImageData> = listOf()
|
||||
val imageDataList: MutableList<ImageData> = mutableListOf()
|
||||
val ret = coroutineScope {
|
||||
try {
|
||||
Logger.log("source.name " + source.name)
|
||||
@@ -626,7 +624,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,
|
||||
@@ -670,8 +668,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)
|
||||
@@ -680,7 +678,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
|
||||
|
||||
@@ -783,9 +781,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)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package ani.dantotsu.parsers
|
||||
|
||||
import ani.dantotsu.Lazier
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.anime.Episode
|
||||
import ani.dantotsu.media.manga.MangaChapter
|
||||
import ani.dantotsu.tryWithSuspend
|
||||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ani.dantotsu.parsers
|
||||
|
||||
import android.util.Log
|
||||
import ani.dantotsu.Lazier
|
||||
import ani.dantotsu.parsers.novel.DynamicNovelParser
|
||||
import ani.dantotsu.parsers.novel.NovelExtension
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package ani.dantotsu.parsers
|
||||
import android.os.Environment
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.media.manga.MangaNameAdapter
|
||||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import me.xdrop.fuzzywuzzy.FuzzySearch
|
||||
|
||||
@@ -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
|
||||
@@ -2,9 +2,9 @@ package ani.dantotsu.parsers.novel
|
||||
|
||||
|
||||
import android.content.Context
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.tachiyomi.extension.ExtensionUpdateNotifier
|
||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeLoadResult
|
||||
|
||||
@@ -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<InstallStep> = Observable.defer {
|
||||
val pkgName = extension.pkgName
|
||||
|
||||
val oldDownload = activeDownloads[pkgName]
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -2,8 +2,8 @@ package ani.dantotsu.parsers.novel
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.tachiyomi.extension.InstallStep
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ani.dantotsu.profile
|
||||
|
||||
|
||||
import android.view.View
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.blurImage
|
||||
|
||||
@@ -28,6 +28,7 @@ import ani.dantotsu.media.user.ListActivity
|
||||
import ani.dantotsu.setSlideIn
|
||||
import ani.dantotsu.setSlideUp
|
||||
import ani.dantotsu.util.AniMarkdown.Companion.getFullAniHTML
|
||||
import eu.kanade.tachiyomi.util.system.getSerializableCompat
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -52,7 +53,7 @@ class ProfileFragment : Fragment() {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
activity = requireActivity() as ProfileActivity
|
||||
|
||||
user = arguments?.getSerializable("user") as Query.UserProfile
|
||||
user = arguments?.getSerializableCompat<Query.UserProfile>("user") as Query.UserProfile
|
||||
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
||||
model.setData(user.id)
|
||||
}
|
||||
|
||||
@@ -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<Query.UserProfile>("user") as Query.UserProfile
|
||||
|
||||
binding.statisticList.adapter = adapter
|
||||
binding.statisticList.setHasFixedSize(true)
|
||||
@@ -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)
|
||||
}
|
||||
@@ -439,6 +440,7 @@ class StatsFragment :
|
||||
}.toMutableList()
|
||||
chartPackets.clear()
|
||||
chartPackets.addAll(standardizedPackets)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val genreChart = ChartBuilder.buildChart(
|
||||
activity,
|
||||
ChartType.TwoDimensional,
|
||||
@@ -493,6 +495,7 @@ class StatsFragment :
|
||||
}.toMutableList()
|
||||
chartPackets.clear()
|
||||
chartPackets.addAll(standardizedPackets)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val tagChart = ChartBuilder.buildChart(
|
||||
activity,
|
||||
ChartType.TwoDimensional,
|
||||
@@ -547,6 +550,7 @@ class StatsFragment :
|
||||
}.toMutableList()
|
||||
chartPackets.clear()
|
||||
chartPackets.addAll(standardizedPackets)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val countryChart = ChartBuilder.buildChart(
|
||||
activity,
|
||||
ChartType.OneDimensional,
|
||||
@@ -603,6 +607,7 @@ class StatsFragment :
|
||||
}.toMutableList()
|
||||
chartPackets.clear()
|
||||
chartPackets.addAll(standardizedPackets)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val voiceActorsChart = ChartBuilder.buildChart(
|
||||
activity,
|
||||
ChartType.TwoDimensional,
|
||||
@@ -657,6 +662,7 @@ class StatsFragment :
|
||||
}.toMutableList()
|
||||
chartPackets.clear()
|
||||
chartPackets.addAll(standardizedPackets)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val studioChart = ChartBuilder.buildChart(
|
||||
activity,
|
||||
ChartType.TwoDimensional,
|
||||
@@ -714,6 +720,7 @@ class StatsFragment :
|
||||
}.toMutableList()
|
||||
chartPackets.clear()
|
||||
chartPackets.addAll(standardizedPackets)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val staffChart = ChartBuilder.buildChart(
|
||||
activity,
|
||||
ChartType.TwoDimensional,
|
||||
|
||||
@@ -8,7 +8,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import ani.dantotsu.BottomSheetDialogFragment
|
||||
import ani.dantotsu.databinding.BottomSheetUsersBinding
|
||||
import ani.dantotsu.profile.activity.UsersAdapter
|
||||
import ani.dantotsu.settings.DevelopersAdapter
|
||||
|
||||
|
||||
class UsersDialogFragment : BottomSheetDialogFragment() {
|
||||
|
||||
@@ -17,13 +17,8 @@ import ani.dantotsu.profile.UsersDialogFragment
|
||||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
import jp.wasabeef.glide.transformations.BlurTransformation
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
|
||||
@@ -57,7 +57,7 @@ class FeedActivity : AppCompatActivity() {
|
||||
}
|
||||
})
|
||||
binding.listBack.setOnClickListener {
|
||||
onBackPressed()
|
||||
onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,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)
|
||||
|
||||
@@ -2,26 +2,27 @@ package ani.dantotsu.settings
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.os.Build.*
|
||||
import android.os.Build.VERSION.*
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.AutoCompleteTextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.ActivityExtensionsBinding
|
||||
import ani.dantotsu.initActivity
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.others.AndroidBug5497Workaround
|
||||
import ani.dantotsu.others.LanguageMapper
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.app.AlertDialog
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -25,13 +24,13 @@ import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.others.LanguageMapper
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
|
||||
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.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
@@ -45,7 +44,6 @@ import uy.kohesive.injekt.api.get
|
||||
import java.util.Collections
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.app.AlertDialog
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.annotation.SuppressLint
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
@@ -3,7 +3,6 @@ package ani.dantotsu.settings
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
@@ -255,7 +255,7 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
||||
binding.playerResizeMode.setOnClickListener {
|
||||
val dialog = resizeDialog.setSingleChoiceItems(
|
||||
resizeModes,
|
||||
PrefManager.getVal<Int>(PrefName.Resize)
|
||||
PrefManager.getVal(PrefName.Resize)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.Resize, count)
|
||||
dialog.dismiss()
|
||||
|
||||
@@ -39,13 +39,12 @@ import ani.dantotsu.connections.mal.MAL
|
||||
import ani.dantotsu.copyToClipboard
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.ActivitySettingsBinding
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
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.CommentNotificationWorker
|
||||
import ani.dantotsu.notifications.anilist.AnilistNotificationWorker
|
||||
@@ -70,6 +69,7 @@ import ani.dantotsu.subcriptions.Subscription.Companion.startSubscription
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
|
||||
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
|
||||
@@ -124,13 +124,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")) {
|
||||
@@ -138,11 +138,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))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -227,7 +227,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)
|
||||
@@ -244,7 +244,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)
|
||||
binding.settingsDownloadManager.setOnClickListener {
|
||||
val dialog = downloadManagerDialog.setSingleChoiceItems(
|
||||
@@ -264,7 +264,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()
|
||||
@@ -315,11 +315,11 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
|
||||
binding.purgeAnimeDownloads.setOnClickListener {
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle("Purge Anime Downloads")
|
||||
.setMessage("Are you sure you want to purge all anime downloads?")
|
||||
.setPositiveButton("Yes") { dialog, _ ->
|
||||
.setTitle(R.string.purge_anime_downloads)
|
||||
.setMessage(getString(R.string.purge_anime_confirm))
|
||||
.setPositiveButton(R.string.yes) { dialog, _ ->
|
||||
val downloadsManager = Injekt.get<DownloadsManager>()
|
||||
downloadsManager.purgeDownloads(DownloadedType.Type.ANIME)
|
||||
downloadsManager.purgeDownloads(MediaType.ANIME)
|
||||
DownloadService.sendRemoveAllDownloads(
|
||||
this,
|
||||
ExoplayerDownloadService::class.java,
|
||||
@@ -327,7 +327,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("No") { dialog, _ ->
|
||||
.setNegativeButton(R.string.no) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
@@ -337,14 +337,14 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
|
||||
binding.purgeMangaDownloads.setOnClickListener {
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle("Purge Manga Downloads")
|
||||
.setMessage("Are you sure you want to purge all manga downloads?")
|
||||
.setPositiveButton("Yes") { dialog, _ ->
|
||||
.setTitle(R.string.purge_manga_downloads)
|
||||
.setMessage(getString(R.string.purge_manga_confirm))
|
||||
.setPositiveButton(R.string.yes) { dialog, _ ->
|
||||
val downloadsManager = Injekt.get<DownloadsManager>()
|
||||
downloadsManager.purgeDownloads(DownloadedType.Type.MANGA)
|
||||
downloadsManager.purgeDownloads(MediaType.MANGA)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("No") { dialog, _ ->
|
||||
.setNegativeButton(R.string.no) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
@@ -354,14 +354,14 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
|
||||
binding.purgeNovelDownloads.setOnClickListener {
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle("Purge Novel Downloads")
|
||||
.setMessage("Are you sure you want to purge all novel downloads?")
|
||||
.setPositiveButton("Yes") { dialog, _ ->
|
||||
.setTitle(R.string.purge_novel_downloads)
|
||||
.setMessage(getString(R.string.purge_novel_confirm))
|
||||
.setPositiveButton(R.string.yes) { dialog, _ ->
|
||||
val downloadsManager = Injekt.get<DownloadsManager>()
|
||||
downloadsManager.purgeDownloads(DownloadedType.Type.NOVEL)
|
||||
downloadsManager.purgeDownloads(MediaType.NOVEL)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("No") { dialog, _ ->
|
||||
.setNegativeButton(R.string.no) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
@@ -396,16 +396,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()
|
||||
@@ -436,7 +436,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
binding.settingsExtensionDns.setOnItemClickListener { _, _, i, _ ->
|
||||
PrefManager.setVal(PrefName.DohProvider, i)
|
||||
binding.settingsExtensionDns.clearFocus()
|
||||
Toast.makeText(this, "Restart app to apply changes", Toast.LENGTH_LONG).show()
|
||||
restartApp()
|
||||
}
|
||||
|
||||
binding.settingsDownloadInSd.isChecked = PrefManager.getVal(PrefName.SdDl)
|
||||
@@ -586,7 +586,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()
|
||||
@@ -617,7 +617,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
(binding.settingsLogo.drawable as Animatable).start()
|
||||
if (cursedCounter % 7 == 0) {
|
||||
Toast.makeText(this, "youwu have been cuwsed :pwayge:", Toast.LENGTH_LONG).show()
|
||||
val url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
||||
val url = getString(R.string.cursed_yt)
|
||||
openLinkInBrowser(url)
|
||||
//PrefManager.setVal(PrefName.ImageUrl, !PrefManager.getVal(PrefName.ImageUrl, false))
|
||||
} else {
|
||||
@@ -845,7 +845,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
if (MAL.token != null) {
|
||||
binding.settingsMALLogin.setText(R.string.logout)
|
||||
binding.settingsMALLogin.setOnClickListener {
|
||||
MAL.removeSavedToken(it.context)
|
||||
MAL.removeSavedToken()
|
||||
restartMainActivity.isEnabled = true
|
||||
reload()
|
||||
}
|
||||
@@ -1000,7 +1000,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, _ ->
|
||||
@@ -1016,7 +1016,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, _ ->
|
||||
@@ -1030,7 +1030,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
val subtitleTextView = dialogView.findViewById<TextView>(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)
|
||||
|
||||
@@ -10,7 +10,6 @@ import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
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
|
||||
@@ -23,13 +22,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
|
||||
|
||||
@@ -40,7 +41,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(
|
||||
|
||||
@@ -92,7 +92,7 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
|
||||
class InitialAnimeSourcePreferencesFragment(
|
||||
val sharedPreferences: SharedPreferences,
|
||||
private val sharedPreferences: SharedPreferences,
|
||||
val source: ConfigurableAnimeSource,
|
||||
val currContext: Context
|
||||
) : PreferenceFragmentCompat() {
|
||||
|
||||
@@ -42,6 +42,7 @@ import kotlinx.coroutines.withContext
|
||||
class AnimeExtensionsViewModelFactory(
|
||||
private val animeExtensionManager: AnimeExtensionManager
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return AnimeExtensionsViewModel(animeExtensionManager) as T
|
||||
}
|
||||
@@ -49,7 +50,7 @@ class AnimeExtensionsViewModelFactory(
|
||||
|
||||
|
||||
class AnimeExtensionsViewModel(
|
||||
private val animeExtensionManager: AnimeExtensionManager
|
||||
animeExtensionManager: AnimeExtensionManager
|
||||
) : ViewModel() {
|
||||
private val searchQuery = MutableStateFlow("")
|
||||
private var currentPagingSource: AnimeExtensionPagingSource? = null
|
||||
|
||||
@@ -41,13 +41,14 @@ import kotlinx.coroutines.withContext
|
||||
class MangaExtensionsViewModelFactory(
|
||||
private val mangaExtensionManager: MangaExtensionManager
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return MangaExtensionsViewModel(mangaExtensionManager) as T
|
||||
}
|
||||
}
|
||||
|
||||
class MangaExtensionsViewModel(
|
||||
private val mangaExtensionManager: MangaExtensionManager
|
||||
mangaExtensionManager: MangaExtensionManager
|
||||
) : ViewModel() {
|
||||
private val searchQuery = MutableStateFlow("")
|
||||
private var currentPagingSource: MangaExtensionPagingSource? = null
|
||||
|
||||
@@ -41,13 +41,14 @@ import kotlinx.coroutines.withContext
|
||||
class NovelExtensionsViewModelFactory(
|
||||
private val novelExtensionManager: NovelExtensionManager
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): 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)
|
||||
|
||||
@@ -10,7 +10,7 @@ abstract class SharedPreferenceLiveData<T>(
|
||||
) : LiveData<T>() {
|
||||
|
||||
private val preferenceChangeListener =
|
||||
SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
|
||||
SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
|
||||
if (key == this.key) {
|
||||
value = getValueFromPreferences(key, defValue)
|
||||
}
|
||||
|
||||
@@ -7,13 +7,13 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.isOnline
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.defaultTime
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.startSubscription
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
|
||||
import ani.dantotsu.tryWith
|
||||
import ani.dantotsu.util.Logger
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -18,7 +18,7 @@ import com.bumptech.glide.load.model.GlideUrl
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate", "unused")
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
class Notifications {
|
||||
enum class Group(val title: String, val icon: Int) {
|
||||
ANIME_GROUP("New Episodes", R.drawable.ic_round_movie_filter_24),
|
||||
@@ -50,11 +50,7 @@ class Notifications {
|
||||
}
|
||||
return PendingIntent.getActivity(
|
||||
context, 0, notifyIntent,
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_ONE_SHOT
|
||||
} else {
|
||||
PendingIntent.FLAG_ONE_SHOT
|
||||
}
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_ONE_SHOT
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,16 @@ import android.app.Notification
|
||||
import android.content.Context
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.App
|
||||
import ani.dantotsu.FileUrl
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.parsers.Episode
|
||||
import ani.dantotsu.parsers.MangaChapter
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.tryWithSuspend
|
||||
import ani.dantotsu.util.Logger
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -74,7 +79,7 @@ class Subscription {
|
||||
val media = it.second
|
||||
val text = if (media.isAnime) {
|
||||
val parser =
|
||||
SubscriptionHelper.getAnimeParser(context, media.isAdult, media.id)
|
||||
SubscriptionHelper.getAnimeParser(media.isAdult, media.id)
|
||||
progress(index[it.first]!!, parser.name, media.name)
|
||||
val ep: Episode? =
|
||||
SubscriptionHelper.getEpisode(context, parser, media.id, media.isAdult)
|
||||
@@ -86,10 +91,10 @@ class Subscription {
|
||||
else null
|
||||
} else {
|
||||
val parser =
|
||||
SubscriptionHelper.getMangaParser(context, media.isAdult, media.id)
|
||||
SubscriptionHelper.getMangaParser(media.isAdult, media.id)
|
||||
progress(index[it.first]!!, parser.name, media.name)
|
||||
val ep: MangaChapter? =
|
||||
SubscriptionHelper.getChapter(context, parser, media.id, media.isAdult)
|
||||
SubscriptionHelper.getChapter(parser, media.id, media.isAdult)
|
||||
if (ep != null) ep.number + " " + currActivity()!!.getString(R.string.just_released) to null
|
||||
else null
|
||||
} ?: return@map
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user