chore: lint performance optimization
This includes shadowed variables, unnecessary parameters, layouts with string literals, items that cause performance bottlenecks, and the merge of extension types into only the necessary separate classes.
This commit is contained in:
parent
958aa634b1
commit
37ec165319
111 changed files with 1561 additions and 2091 deletions
|
@ -86,7 +86,7 @@ class App : MultiDexApplication() {
|
|||
Thread.setDefaultUncaughtExceptionHandler(FinalExceptionHandler())
|
||||
Logger.log("App: Logging started")
|
||||
|
||||
initializeNetwork(baseContext)
|
||||
initializeNetwork()
|
||||
|
||||
setupNotificationChannels()
|
||||
if (!LogcatLogger.isInstalled) {
|
||||
|
|
|
@ -159,16 +159,16 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
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")
|
||||
|
@ -337,7 +337,7 @@ class MainActivity : AppCompatActivity() {
|
|||
startActivity(Intent(this, NoInternet::class.java))
|
||||
} else {
|
||||
val model: AnilistHomeViewModel by viewModels()
|
||||
model.genres.observe(this) { it ->
|
||||
model.genres.observe(this) {
|
||||
if (it != null) {
|
||||
if (it) {
|
||||
val navbar = binding.includedNavbar.navbar
|
||||
|
@ -362,7 +362,7 @@ class MainActivity : AppCompatActivity() {
|
|||
mainViewPager.setCurrentItem(newIndex, false)
|
||||
}
|
||||
})
|
||||
if (mainViewPager.getCurrentItem() != selectedOption) {
|
||||
if (mainViewPager.currentItem != selectedOption) {
|
||||
navbar.selectTabAt(selectedOption)
|
||||
mainViewPager.post {
|
||||
mainViewPager.setCurrentItem(
|
||||
|
|
|
@ -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>()
|
||||
|
||||
|
|
|
@ -387,6 +387,7 @@ class AnilistQueries {
|
|||
returnArray.addAll(map.values)
|
||||
return returnArray
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val list = PrefManager.getNullableCustomVal(
|
||||
"continueAnimeList",
|
||||
listOf<Int>(),
|
||||
|
@ -544,6 +545,7 @@ class AnilistQueries {
|
|||
returnMap["current$type"] = returnArray
|
||||
return
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val list = PrefManager.getNullableCustomVal(
|
||||
"continueAnimeList",
|
||||
listOf<Int>(),
|
||||
|
@ -573,6 +575,7 @@ class AnilistQueries {
|
|||
subMap[m.id] = m
|
||||
}
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val list = PrefManager.getNullableCustomVal(
|
||||
"continueAnimeList",
|
||||
listOf<Int>(),
|
||||
|
@ -734,7 +737,7 @@ class AnilistQueries {
|
|||
}
|
||||
|
||||
sorted["All"] = all
|
||||
val listSort: String = if (anime) PrefManager.getVal(PrefName.AnimeListSortOrder)
|
||||
val listSort: String? = if (anime) PrefManager.getVal(PrefName.AnimeListSortOrder)
|
||||
else PrefManager.getVal(PrefName.MangaListSortOrder)
|
||||
val sort = listSort ?: sortOrder ?: options?.rowOrder
|
||||
for (i in sorted.keys) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -242,7 +243,7 @@ class AnimeDownloaderService : Service() {
|
|||
DownloadedType(
|
||||
task.title,
|
||||
task.episode,
|
||||
DownloadedType.Type.ANIME,
|
||||
MediaType.ANIME,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -273,7 +274,7 @@ class AnimeDownloaderService : Service() {
|
|||
DownloadedType(
|
||||
task.title,
|
||||
task.episode,
|
||||
DownloadedType.Type.ANIME,
|
||||
MediaType.ANIME,
|
||||
)
|
||||
)
|
||||
Injekt.get<CrashlyticsInterface>().logException(
|
||||
|
@ -302,7 +303,7 @@ class AnimeDownloaderService : Service() {
|
|||
DownloadedType(
|
||||
task.title,
|
||||
task.episode,
|
||||
DownloadedType.Type.ANIME,
|
||||
MediaType.ANIME,
|
||||
)
|
||||
)
|
||||
currentTasks.removeAll { it.getTaskName() == task.getTaskName() }
|
||||
|
|
|
@ -34,15 +34,16 @@ import ani.dantotsu.currContext
|
|||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.initActivity
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.setSafeOnClickListener
|
||||
import ani.dantotsu.settings.SettingsDialogFragment
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.google.android.material.imageview.ShapeableImageView
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
|
@ -188,8 +189,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
|||
gridView.setOnItemLongClickListener { _, _, position, _ ->
|
||||
// Get the OfflineAnimeModel that was clicked
|
||||
val item = adapter.getItem(position) as OfflineAnimeModel
|
||||
val type: DownloadedType.Type =
|
||||
DownloadedType.Type.ANIME
|
||||
val type: MediaType = MediaType.ANIME
|
||||
|
||||
// Alert dialog to confirm deletion
|
||||
val builder =
|
||||
|
@ -293,11 +293,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
|||
}
|
||||
|
||||
private fun getMedia(downloadedType: DownloadedType): Media? {
|
||||
val type = when (downloadedType.type) {
|
||||
DownloadedType.Type.MANGA -> "Manga"
|
||||
DownloadedType.Type.ANIME -> "Anime"
|
||||
else -> "Novel"
|
||||
}
|
||||
val type = downloadedType.type.asText()
|
||||
val directory = File(
|
||||
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/$type/${downloadedType.title}"
|
||||
|
@ -327,11 +323,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
|||
}
|
||||
|
||||
private fun loadOfflineAnimeModel(downloadedType: DownloadedType): OfflineAnimeModel {
|
||||
val type = when (downloadedType.type) {
|
||||
DownloadedType.Type.MANGA -> "Manga"
|
||||
DownloadedType.Type.ANIME -> "Anime"
|
||||
else -> "Novel"
|
||||
}
|
||||
val type = downloadedType.type.asText()
|
||||
val directory = File(
|
||||
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/$type/${downloadedType.title}"
|
||||
|
|
|
@ -21,8 +21,8 @@ import ani.dantotsu.R
|
|||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.media.manga.ImageData
|
||||
import ani.dantotsu.media.manga.MangaReadFragment.Companion.ACTION_DOWNLOAD_FAILED
|
||||
import ani.dantotsu.media.manga.MangaReadFragment.Companion.ACTION_DOWNLOAD_FINISHED
|
||||
|
@ -30,6 +30,7 @@ import ani.dantotsu.media.manga.MangaReadFragment.Companion.ACTION_DOWNLOAD_PROG
|
|||
import ani.dantotsu.media.manga.MangaReadFragment.Companion.ACTION_DOWNLOAD_STARTED
|
||||
import ani.dantotsu.media.manga.MangaReadFragment.Companion.EXTRA_CHAPTER_NUMBER
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.InstanceCreator
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||
|
@ -211,8 +212,7 @@ class MangaDownloaderService : Service() {
|
|||
while (bitmap == null && retryCount < task.retries) {
|
||||
bitmap = image.fetchAndProcessImage(
|
||||
image.page,
|
||||
image.source,
|
||||
this@MangaDownloaderService
|
||||
image.source
|
||||
)
|
||||
retryCount++
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ class MangaDownloaderService : Service() {
|
|||
DownloadedType(
|
||||
task.title,
|
||||
task.chapter,
|
||||
DownloadedType.Type.MANGA
|
||||
MediaType.MANGA
|
||||
)
|
||||
)
|
||||
broadcastDownloadFinished(task.chapter)
|
||||
|
|
|
@ -31,15 +31,16 @@ import ani.dantotsu.currContext
|
|||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.initActivity
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.setSafeOnClickListener
|
||||
import ani.dantotsu.settings.SettingsDialogFragment
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.google.android.material.imageview.ShapeableImageView
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
|
@ -179,11 +180,11 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
gridView.setOnItemLongClickListener { _, _, position, _ ->
|
||||
// Get the OfflineMangaModel that was clicked
|
||||
val item = adapter.getItem(position) as OfflineMangaModel
|
||||
val type: DownloadedType.Type =
|
||||
val type: MediaType =
|
||||
if (downloadManager.mangaDownloadedTypes.any { it.title == item.title }) {
|
||||
DownloadedType.Type.MANGA
|
||||
MediaType.MANGA
|
||||
} else {
|
||||
DownloadedType.Type.NOVEL
|
||||
MediaType.NOVEL
|
||||
}
|
||||
// Alert dialog to confirm deletion
|
||||
val builder =
|
||||
|
@ -289,11 +290,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
}
|
||||
|
||||
private fun getMedia(downloadedType: DownloadedType): Media? {
|
||||
val type = when (downloadedType.type) {
|
||||
DownloadedType.Type.MANGA -> "Manga"
|
||||
DownloadedType.Type.ANIME -> "Anime"
|
||||
else -> "Novel"
|
||||
}
|
||||
val type = downloadedType.type.asText()
|
||||
val directory = File(
|
||||
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/$type/${downloadedType.title}"
|
||||
|
@ -317,11 +314,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
}
|
||||
|
||||
private fun loadOfflineMangaModel(downloadedType: DownloadedType): OfflineMangaModel {
|
||||
val type = when (downloadedType.type) {
|
||||
DownloadedType.Type.MANGA -> "Manga"
|
||||
DownloadedType.Type.ANIME -> "Anime"
|
||||
else -> "Novel"
|
||||
}
|
||||
val type = downloadedType.type.asText()
|
||||
val directory = File(
|
||||
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"Dantotsu/$type/${downloadedType.title}"
|
||||
|
|
|
@ -20,10 +20,11 @@ import ani.dantotsu.R
|
|||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.media.novel.NovelReadFragment
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.InstanceCreator
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
|
@ -335,7 +336,7 @@ class NovelDownloaderService : Service() {
|
|||
DownloadedType(
|
||||
task.title,
|
||||
task.chapter,
|
||||
DownloadedType.Type.NOVEL
|
||||
MediaType.NOVEL
|
||||
)
|
||||
)
|
||||
broadcastDownloadFinished(task.originalLink)
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -66,8 +66,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
|
||||
|
@ -73,10 +72,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
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package ani.dantotsu.media
|
|||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Rect
|
||||
import android.content.res.Configuration
|
||||
|
@ -13,9 +12,7 @@ import android.view.GestureDetector
|
|||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
@ -243,13 +240,13 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
|
|||
@SuppressLint("ResourceType")
|
||||
fun total() {
|
||||
val text = SpannableStringBuilder().apply {
|
||||
val typedValue = TypedValue()
|
||||
val mediaTypedValue = TypedValue()
|
||||
this@MediaDetailsActivity.theme.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorOnBackground,
|
||||
typedValue,
|
||||
mediaTypedValue,
|
||||
true
|
||||
)
|
||||
val white = typedValue.data
|
||||
val white = mediaTypedValue.data
|
||||
if (media.userStatus != null) {
|
||||
append(if (media.anime != null) getString(R.string.watched_num) else getString(R.string.read_num))
|
||||
val typedValue = TypedValue()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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|episodio|ep|e)[\\s:.\\-]*([\\d]+\\.?[\\d]*)[\\s:.\\-]*\\(?\\s*(sub|subbed|dub|dubbed)*\\s*\\)?\\s*"
|
||||
"(episode|episodio|ep|e)[\\s:.\\-]*(\\d+\\.?\\d*)[\\s:.\\-]*\\(?\\s*(sub|subbed|dub|dubbed)*\\s*\\)?\\s*"
|
||||
const val failedEpisodeNumberRegex =
|
||||
"(?<!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], "")
|
||||
|
|
|
@ -29,19 +29,24 @@ import androidx.recyclerview.widget.ConcatAdapter
|
|||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.FileUrl
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.FragmentAnimeWatchBinding
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.anime.AnimeDownloaderService
|
||||
import ani.dantotsu.download.video.ExoplayerDownloadService
|
||||
import ani.dantotsu.dp
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.others.LanguageMapper
|
||||
import ani.dantotsu.parsers.AnimeParser
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.HAnimeSources
|
||||
import ani.dantotsu.setNavigationTheme
|
||||
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
|
@ -433,7 +438,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
DownloadedType(
|
||||
media.mainName(),
|
||||
i,
|
||||
DownloadedType.Type.ANIME
|
||||
MediaType.ANIME
|
||||
)
|
||||
)
|
||||
episodeAdapter.purgeDownload(i)
|
||||
|
@ -445,7 +450,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
DownloadedType(
|
||||
media.mainName(),
|
||||
i,
|
||||
DownloadedType.Type.ANIME
|
||||
MediaType.ANIME
|
||||
)
|
||||
)
|
||||
val taskName = AnimeDownloaderService.AnimeDownloadTask.getTaskName(media.mainName(), i)
|
||||
|
|
|
@ -13,14 +13,16 @@ import androidx.lifecycle.coroutineScope
|
|||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.exoplayer.offline.DownloadIndex
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.updateProgress
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.ItemEpisodeCompactBinding
|
||||
import ani.dantotsu.databinding.ItemEpisodeGridBinding
|
||||
import ani.dantotsu.databinding.ItemEpisodeListBinding
|
||||
import ani.dantotsu.download.anime.AnimeDownloaderService
|
||||
import ani.dantotsu.download.video.Helper
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
|
@ -427,7 +429,7 @@ class EpisodeAdapter(
|
|||
if (bytes < 0) return null
|
||||
val unit = 1000
|
||||
if (bytes < unit) return "$bytes B"
|
||||
val exp = (Math.log(bytes.toDouble()) / ln(unit.toDouble())).toInt()
|
||||
val exp = (ln(bytes.toDouble()) / ln(unit.toDouble())).toInt()
|
||||
val pre = ("KMGTPE")[exp - 1]
|
||||
return String.format("%.1f %sB", bytes / unit.toDouble().pow(exp.toDouble()), pre)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,10 @@ import android.graphics.Color
|
|||
import android.graphics.drawable.Animatable
|
||||
import android.hardware.SensorManager
|
||||
import android.media.AudioManager
|
||||
import android.media.AudioManager.*
|
||||
import android.media.AudioManager.AUDIOFOCUS_GAIN
|
||||
import android.media.AudioManager.AUDIOFOCUS_LOSS
|
||||
import android.media.AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
|
||||
import android.media.AudioManager.STREAM_MUSIC
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
|
@ -27,8 +30,18 @@ import android.provider.Settings.System
|
|||
import android.util.AttributeSet
|
||||
import android.util.Rational
|
||||
import android.util.TypedValue
|
||||
import android.view.*
|
||||
import android.view.KeyEvent.*
|
||||
import android.view.GestureDetector
|
||||
import android.view.KeyEvent
|
||||
import android.view.KeyEvent.ACTION_UP
|
||||
import android.view.KeyEvent.KEYCODE_B
|
||||
import android.view.KeyEvent.KEYCODE_DPAD_LEFT
|
||||
import android.view.KeyEvent.KEYCODE_DPAD_RIGHT
|
||||
import android.view.KeyEvent.KEYCODE_N
|
||||
import android.view.KeyEvent.KEYCODE_SPACE
|
||||
import android.view.MotionEvent
|
||||
import android.view.OrientationEventListener
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ImageButton
|
||||
|
@ -46,27 +59,43 @@ import androidx.core.view.updateLayoutParams
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.media3.cast.CastPlayer
|
||||
import androidx.media3.cast.SessionAvailabilityListener
|
||||
import androidx.media3.common.*
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.C.AUDIO_CONTENT_TYPE_MOVIE
|
||||
import androidx.media3.common.C.TRACK_TYPE_VIDEO
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.MimeTypes
|
||||
import androidx.media3.common.PlaybackException
|
||||
import androidx.media3.common.PlaybackParameters
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.TrackSelectionOverride
|
||||
import androidx.media3.common.Tracks
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.common.util.Util
|
||||
import androidx.media3.datasource.DataSource
|
||||
import androidx.media3.datasource.DefaultDataSourceFactory
|
||||
import androidx.media3.datasource.DefaultDataSource
|
||||
import androidx.media3.datasource.HttpDataSource
|
||||
import androidx.media3.datasource.cache.CacheDataSource
|
||||
import androidx.media3.datasource.okhttp.OkHttpDataSource
|
||||
import androidx.media3.exoplayer.DefaultLoadControl
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
|
||||
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
|
||||
import androidx.media3.exoplayer.util.EventLogger
|
||||
import androidx.media3.session.MediaSession
|
||||
import androidx.media3.ui.*
|
||||
import androidx.media3.ui.CaptionStyleCompat.*
|
||||
import androidx.media3.exoplayer.DefaultLoadControl
|
||||
import androidx.media3.ui.AspectRatioFrameLayout
|
||||
import androidx.media3.ui.CaptionStyleCompat
|
||||
import androidx.media3.ui.CaptionStyleCompat.EDGE_TYPE_DEPRESSED
|
||||
import androidx.media3.ui.CaptionStyleCompat.EDGE_TYPE_DROP_SHADOW
|
||||
import androidx.media3.ui.CaptionStyleCompat.EDGE_TYPE_NONE
|
||||
import androidx.media3.ui.CaptionStyleCompat.EDGE_TYPE_OUTLINE
|
||||
import androidx.media3.ui.DefaultTimeBar
|
||||
import androidx.media3.ui.PlayerView
|
||||
import androidx.media3.ui.SubtitleView
|
||||
import androidx.mediarouter.app.MediaRouteButton
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.GesturesListener
|
||||
import ani.dantotsu.NoPaddingArrayAdapter
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.brightnessConverter
|
||||
import ani.dantotsu.circularReveal
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.connections.discord.Discord
|
||||
|
@ -75,19 +104,38 @@ import ani.dantotsu.connections.discord.DiscordServiceRunningSingleton
|
|||
import ani.dantotsu.connections.discord.RPC
|
||||
import ani.dantotsu.connections.updateProgress
|
||||
import ani.dantotsu.databinding.ActivityExoplayerBinding
|
||||
import ani.dantotsu.defaultHeaders
|
||||
import ani.dantotsu.download.video.Helper
|
||||
import ani.dantotsu.dp
|
||||
import ani.dantotsu.getCurrentBrightnessValue
|
||||
import ani.dantotsu.hideSystemBars
|
||||
import ani.dantotsu.hideSystemBarsExtendView
|
||||
import ani.dantotsu.isOnline
|
||||
import ani.dantotsu.logError
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.media.SubtitleDownloader
|
||||
import ani.dantotsu.okHttpClient
|
||||
import ani.dantotsu.others.AniSkip
|
||||
import ani.dantotsu.others.AniSkip.getType
|
||||
import ani.dantotsu.others.ResettableTimer
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.parsers.*
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.HAnimeSources
|
||||
import ani.dantotsu.parsers.Subtitle
|
||||
import ani.dantotsu.parsers.SubtitleType
|
||||
import ani.dantotsu.parsers.Video
|
||||
import ani.dantotsu.parsers.VideoExtractor
|
||||
import ani.dantotsu.parsers.VideoType
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.settings.PlayerSettingsActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.startMainActivity
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.tryWithSuspend
|
||||
import ani.dantotsu.util.Logger
|
||||
import com.bumptech.glide.Glide
|
||||
import com.google.android.gms.cast.framework.CastButtonFactory
|
||||
|
@ -103,8 +151,11 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.runBlocking
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.*
|
||||
import java.util.concurrent.*
|
||||
import java.util.Calendar
|
||||
import java.util.Timer
|
||||
import java.util.TimerTask
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.roundToInt
|
||||
|
@ -344,15 +395,14 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
isCastApiAvailable = GoogleApiAvailability.getInstance()
|
||||
.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS
|
||||
try {
|
||||
castContext = CastContext.getSharedInstance(this)
|
||||
castContext = CastContext.getSharedInstance(this, Executors.newSingleThreadExecutor()).result
|
||||
castPlayer = CastPlayer(castContext!!)
|
||||
castPlayer!!.setSessionAvailabilityListener(this)
|
||||
} catch (e: Exception) {
|
||||
isCastApiAvailable = false
|
||||
}
|
||||
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
hideSystemBars()
|
||||
hideSystemBarsExtendView()
|
||||
|
||||
onBackPressedDispatcher.addCallback(this) {
|
||||
finishAndRemoveTask()
|
||||
|
@ -397,21 +447,25 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
orientationListener =
|
||||
object : OrientationEventListener(this, SensorManager.SENSOR_DELAY_UI) {
|
||||
override fun onOrientationChanged(orientation: Int) {
|
||||
if (orientation in 45..135) {
|
||||
if (rotation != ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE) {
|
||||
exoRotate.visibility = View.VISIBLE
|
||||
when (orientation) {
|
||||
in 45..135 -> {
|
||||
if (rotation != ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE) {
|
||||
exoRotate.visibility = View.VISIBLE
|
||||
}
|
||||
rotation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
|
||||
}
|
||||
rotation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
|
||||
} else if (orientation in 225..315) {
|
||||
if (rotation != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
|
||||
exoRotate.visibility = View.VISIBLE
|
||||
in 225..315 -> {
|
||||
if (rotation != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
|
||||
exoRotate.visibility = View.VISIBLE
|
||||
}
|
||||
rotation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||
}
|
||||
rotation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||
} else if (orientation in 315..360 || orientation in 0..45) {
|
||||
if (rotation != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
|
||||
exoRotate.visibility = View.VISIBLE
|
||||
in 315..360, in 0..45 -> {
|
||||
if (rotation != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
|
||||
exoRotate.visibility = View.VISIBLE
|
||||
}
|
||||
rotation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||
}
|
||||
rotation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -943,7 +997,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
episodeArr = episodes.keys.toList()
|
||||
currentEpisodeIndex = episodeArr.indexOf(media.anime!!.selectedEpisode!!)
|
||||
|
||||
episodeTitleArr = arrayListOf<String>()
|
||||
episodeTitleArr = arrayListOf()
|
||||
episodes.forEach {
|
||||
val episode = it.value
|
||||
val cleanedTitle = AnimeNameAdapter.removeEpisodeNumberCompletely(episode.title ?: "")
|
||||
|
@ -1054,7 +1108,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""),
|
||||
RPC.Link(
|
||||
"Stream on Dantotsu",
|
||||
"https://github.com/rebelonion/Dantotsu/"
|
||||
getString(R.string.github)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -1266,6 +1320,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
media.anime!!.selectedEpisode!!
|
||||
)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val list = (PrefManager.getNullableCustomVal("continueAnimeList", listOf<Int>(), List::class.java) as List<Int>).toMutableList()
|
||||
if (list.contains(media.id)) list.remove(media.id)
|
||||
list.add(media.id)
|
||||
|
@ -1303,9 +1358,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
if (subtitle != null) {
|
||||
//var localFile: String? = null
|
||||
if (subtitle?.type == SubtitleType.UNKNOWN) {
|
||||
val context = this
|
||||
runBlocking {
|
||||
val type = SubtitleDownloader.loadSubtitleType(context, subtitle!!.file.url)
|
||||
val type = SubtitleDownloader.loadSubtitleType(subtitle!!.file.url)
|
||||
val fileUri = Uri.parse(subtitle!!.file.url)
|
||||
sub = MediaItem.SubtitleConfiguration
|
||||
.Builder(fileUri)
|
||||
|
@ -1360,8 +1414,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
}
|
||||
dataSource
|
||||
}
|
||||
val dafuckDataSourceFactory =
|
||||
DefaultDataSourceFactory(this, Util.getUserAgent(this, R.string.app_name.toString()))
|
||||
val dafuckDataSourceFactory = DefaultDataSource.Factory(this)
|
||||
cacheFactory = CacheDataSource.Factory().apply {
|
||||
setCache(Helper.getSimpleCache(this@ExoplayerView))
|
||||
if (ext.server.offline) {
|
||||
|
@ -1737,28 +1790,26 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
timer = null
|
||||
return
|
||||
}
|
||||
if (timer == null) {
|
||||
timer = object : CountDownTimer(5000, 1000) {
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
if (new == null){
|
||||
skipTimeButton.visibility = View.GONE
|
||||
exoSkip.visibility = View.VISIBLE
|
||||
disappeared = false
|
||||
functionstarted = false
|
||||
cancelTimer()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
timer = object : CountDownTimer(5000, 1000) {
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
if (new == null) {
|
||||
skipTimeButton.visibility = View.GONE
|
||||
exoSkip.visibility = View.VISIBLE
|
||||
disappeared = true
|
||||
disappeared = false
|
||||
functionstarted = false
|
||||
cancelTimer()
|
||||
}
|
||||
}
|
||||
timer?.start()
|
||||
|
||||
override fun onFinish() {
|
||||
skipTimeButton.visibility = View.GONE
|
||||
exoSkip.visibility = View.VISIBLE
|
||||
disappeared = true
|
||||
functionstarted = false
|
||||
cancelTimer()
|
||||
}
|
||||
}
|
||||
timer?.start()
|
||||
|
||||
}
|
||||
if (PrefManager.getVal(PrefName.ShowTimeStampButton)) {
|
||||
|
|
|
@ -29,6 +29,7 @@ import kotlinx.coroutines.SupervisorJob
|
|||
import kotlinx.coroutines.launch
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.sqrt
|
||||
|
@ -258,6 +259,7 @@ class CommentItem(val comment: Comment,
|
|||
|
||||
private fun removeSubCommentIds(){
|
||||
subCommentIds.forEach { id ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val parentComments = parentSection.groups as? List<CommentItem> ?: emptyList()
|
||||
val commentToRemove = parentComments.find { it.comment.commentId == id }
|
||||
commentToRemove?.let {
|
||||
|
@ -290,7 +292,7 @@ class CommentItem(val comment: Comment,
|
|||
@SuppressLint("SimpleDateFormat")
|
||||
private fun formatTimestamp(timestamp: String): String {
|
||||
return try {
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT)
|
||||
dateFormat.timeZone = TimeZone.getTimeZone("UTC")
|
||||
val parsedDate = dateFormat.parse(timestamp)
|
||||
val currentDate = Date()
|
||||
|
@ -315,7 +317,7 @@ class CommentItem(val comment: Comment,
|
|||
companion object {
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
fun timestampToMillis(timestamp: String): Long {
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT)
|
||||
dateFormat.timeZone = TimeZone.getTimeZone("UTC")
|
||||
val parsedDate = dateFormat.parse(timestamp)
|
||||
return parsedDate?.time ?: 0
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -30,21 +30,25 @@ 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
|
||||
|
@ -492,7 +496,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
DownloadedType(
|
||||
media.mainName(),
|
||||
i,
|
||||
DownloadedType.Type.MANGA
|
||||
MediaType.MANGA
|
||||
)
|
||||
)
|
||||
chapterAdapter.deleteDownload(i)
|
||||
|
@ -510,7 +514,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
|
||||
|
@ -27,7 +38,9 @@ import androidx.lifecycle.lifecycleScope
|
|||
import androidx.recyclerview.widget.PagerSnapHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.GesturesListener
|
||||
import ani.dantotsu.NoPaddingArrayAdapter
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.connections.discord.Discord
|
||||
|
@ -35,7 +48,12 @@ import ani.dantotsu.connections.discord.DiscordService
|
|||
import ani.dantotsu.connections.discord.DiscordServiceRunningSingleton
|
||||
import ani.dantotsu.connections.discord.RPC
|
||||
import ani.dantotsu.connections.updateProgress
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.ActivityMangaReaderBinding
|
||||
import ani.dantotsu.dp
|
||||
import ani.dantotsu.hideSystemBarsExtendView
|
||||
import ani.dantotsu.isOnline
|
||||
import ani.dantotsu.logError
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.media.MediaSingleton
|
||||
|
@ -46,14 +64,25 @@ import ani.dantotsu.others.ImageViewDialog
|
|||
import ani.dantotsu.parsers.HMangaSources
|
||||
import ani.dantotsu.parsers.MangaImage
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.setSafeOnClickListener
|
||||
import ani.dantotsu.settings.CurrentReaderSettings
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.Companion.applyWebtoon
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.Directions.*
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.DualPageModes.*
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.Layouts.*
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.Directions.BOTTOM_TO_TOP
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.Directions.LEFT_TO_RIGHT
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.Directions.RIGHT_TO_LEFT
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.Directions.TOP_TO_BOTTOM
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.DualPageModes.Automatic
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.DualPageModes.Force
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.DualPageModes.No
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.Layouts.CONTINUOUS_PAGED
|
||||
import ani.dantotsu.settings.CurrentReaderSettings.Layouts.PAGED
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.showSystemBarsRetractView
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.tryWith
|
||||
import com.alexvasilkov.gestures.views.GestureFrameLayout
|
||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
|
@ -66,7 +95,8 @@ import java.io.FileInputStream
|
|||
import java.io.FileOutputStream
|
||||
import java.io.ObjectInputStream
|
||||
import java.io.ObjectOutputStream
|
||||
import java.util.*
|
||||
import java.util.Timer
|
||||
import java.util.TimerTask
|
||||
import kotlin.math.min
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
|
@ -88,7 +118,6 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
|
||||
private var isContVisible = false
|
||||
private var showProgressDialog = true
|
||||
private var hidescrollbar = false
|
||||
|
||||
private var maxChapterPage = 0L
|
||||
private var currentChapterPage = 0L
|
||||
|
@ -123,7 +152,7 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun hideSystemBars() {
|
||||
if (PrefManager.getVal<Boolean>(PrefName.ShowSystemBars))
|
||||
if (PrefManager.getVal(PrefName.ShowSystemBars))
|
||||
showSystemBarsRetractView()
|
||||
else
|
||||
hideSystemBarsExtendView()
|
||||
|
@ -368,7 +397,7 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
RPC.Link(getString(R.string.view_manga), media.shareLink ?: ""),
|
||||
RPC.Link(
|
||||
"Stream on Dantotsu",
|
||||
"https://github.com/rebelonion/Dantotsu/"
|
||||
getString(R.string.github)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -740,12 +769,12 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
goneTimer.schedule(timerTask, controllerDuration)
|
||||
}
|
||||
|
||||
enum class pressPos {
|
||||
enum class PressPos {
|
||||
LEFT, RIGHT, CENTER
|
||||
}
|
||||
|
||||
fun handleController(shouldShow: Boolean? = null, event: MotionEvent? = null) {
|
||||
var pressLocation = pressPos.CENTER
|
||||
var pressLocation = PressPos.CENTER
|
||||
if (!sliding) {
|
||||
if (event != null && defaultSettings.layout == PAGED) {
|
||||
if (event.action != MotionEvent.ACTION_UP) return
|
||||
|
@ -755,23 +784,23 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
//if in the 1st 1/5th of the screen width, left and lower than 1/5th of the screen height, left
|
||||
if (screenWidth / 5 in x + 1..<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
|
||||
|
@ -782,7 +811,7 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
return
|
||||
}
|
||||
|
||||
} else if (pressLocation == pressPos.RIGHT) {
|
||||
} else if (pressLocation == PressPos.RIGHT) {
|
||||
if (binding.mangaReaderPager.currentItem < maxChapterPage - 1) {
|
||||
//if the current images zoomed in, go back to normal before going to next page
|
||||
if (imageAdapter?.isZoomed() == true) {
|
||||
|
@ -960,7 +989,7 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
if (!incognito && PrefManager.getCustomVal(
|
||||
"${media.id}_save_progress",
|
||||
true
|
||||
) && if (media.isAdult) PrefManager.getVal<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
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import android.util.TypedValue
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
|
@ -17,7 +16,7 @@ import androidx.lifecycle.lifecycleScope
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.Refresh
|
||||
import ani.dantotsu.databinding.ActivityListBinding
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.hideSystemBarsExtendView
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.statusBarHeight
|
||||
|
@ -71,10 +70,7 @@ class ListActivity : AppCompatActivity() {
|
|||
} else {
|
||||
binding.root.fitsSystemWindows = false
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
window.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
)
|
||||
hideSystemBarsExtendView()
|
||||
binding.settingsContainer.updateLayoutParams<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
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -11,11 +11,11 @@ import android.os.Environment
|
|||
import android.provider.MediaStore
|
||||
import ani.dantotsu.FileUrl
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.media.anime.AnimeNameAdapter
|
||||
import ani.dantotsu.media.manga.ImageData
|
||||
import ani.dantotsu.media.manga.MangaCache
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||
|
@ -59,8 +59,6 @@ class AniyomiAdapter {
|
|||
fun aniyomiToAnimeParser(extension: AnimeExtension.Installed): DynamicAnimeParser {
|
||||
return DynamicAnimeParser(extension)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
||||
|
@ -192,7 +190,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
|||
// Group by season, sort within each season, and then renumber while keeping episode number 0 as is
|
||||
val seasonGroups =
|
||||
res.groupBy { AnimeNameAdapter.findSeasonNumber(it.name) ?: 0 }
|
||||
seasonGroups.keys.sortedBy { it.toInt() }
|
||||
seasonGroups.keys.sortedBy { it }
|
||||
.flatMap { season ->
|
||||
seasonGroups[season]?.sortedBy { it.episode_number }?.map { episode ->
|
||||
if (episode.episode_number != 0f) { // Skip renumbering for episode number 0
|
||||
|
@ -209,7 +207,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
|||
} ?: emptyList()
|
||||
}
|
||||
}
|
||||
return sortedEpisodes.map { SEpisodeToEpisode(it) }
|
||||
return sortedEpisodes.map { sEpisodeToEpisode(it) }
|
||||
} catch (e: Exception) {
|
||||
Logger.log("Exception: $e")
|
||||
}
|
||||
|
@ -244,7 +242,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
|||
|
||||
return try {
|
||||
val videos = source.getVideoList(sEpisode)
|
||||
videos.map { VideoToVideoServer(it) }
|
||||
videos.map { videoToVideoServer(it) }
|
||||
} catch (e: Exception) {
|
||||
Logger.log("Exception occurred: ${e.message}")
|
||||
emptyList()
|
||||
|
@ -296,7 +294,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun SEpisodeToEpisode(sEpisode: SEpisode): Episode {
|
||||
private fun sEpisodeToEpisode(sEpisode: SEpisode): Episode {
|
||||
//if the float episode number is a whole number, convert it to an int
|
||||
val episodeNumberInt =
|
||||
if (sEpisode.episode_number % 1 == 0f) {
|
||||
|
@ -324,7 +322,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
|||
)
|
||||
}
|
||||
|
||||
private fun VideoToVideoServer(video: Video): VideoServer {
|
||||
private fun videoToVideoServer(video: Video): VideoServer {
|
||||
return VideoServer(
|
||||
video.quality,
|
||||
video.url,
|
||||
|
@ -363,7 +361,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
|
|||
return try {
|
||||
val res = source.getChapterList(sManga)
|
||||
val reversedRes = res.reversed()
|
||||
val chapterList = reversedRes.map { SChapterToMangaChapter(it) }
|
||||
val chapterList = reversedRes.map { sChapterToMangaChapter(it) }
|
||||
Logger.log("chapterList size: ${chapterList.size}")
|
||||
Logger.log("chapterList: ${chapterList[1].title}")
|
||||
Logger.log("chapterList: ${chapterList[1].description}")
|
||||
|
@ -382,7 +380,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
|
|||
sourceLanguage = 0
|
||||
extension.sources[sourceLanguage]
|
||||
} as? HttpSource ?: return emptyList()
|
||||
var imageDataList: List<ImageData> = listOf()
|
||||
val imageDataList: MutableList<ImageData> = mutableListOf()
|
||||
val ret = coroutineScope {
|
||||
try {
|
||||
Logger.log("source.name " + source.name)
|
||||
|
@ -632,7 +630,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
|
|||
}
|
||||
|
||||
|
||||
private fun SChapterToMangaChapter(sChapter: SChapter): MangaChapter {
|
||||
private fun sChapterToMangaChapter(sChapter: SChapter): MangaChapter {
|
||||
return MangaChapter(
|
||||
sChapter.name,
|
||||
sChapter.url,
|
||||
|
@ -676,8 +674,8 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() {
|
|||
get() = videoServer
|
||||
|
||||
override suspend fun extract(): VideoContainer {
|
||||
val vidList = listOfNotNull(videoServer.video?.let { AniVideoToSaiVideo(it) })
|
||||
val subList = videoServer.video?.subtitleTracks?.map { TrackToSubtitle(it) } ?: emptyList()
|
||||
val vidList = listOfNotNull(videoServer.video?.let { aniVideoToSaiVideo(it) })
|
||||
val subList = videoServer.video?.subtitleTracks?.map { trackToSubtitle(it) } ?: emptyList()
|
||||
|
||||
return if (vidList.isNotEmpty()) {
|
||||
VideoContainer(vidList, subList)
|
||||
|
@ -686,7 +684,7 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun AniVideoToSaiVideo(aniVideo: Video): ani.dantotsu.parsers.Video {
|
||||
private fun aniVideoToSaiVideo(aniVideo: Video): ani.dantotsu.parsers.Video {
|
||||
// Find the number value from the .quality string
|
||||
val number = Regex("""\d+""").find(aniVideo.quality)?.value?.toInt() ?: 0
|
||||
|
||||
|
@ -789,9 +787,9 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() {
|
|||
|
||||
}
|
||||
|
||||
private fun TrackToSubtitle(track: Track): Subtitle {
|
||||
private fun trackToSubtitle(track: Track): Subtitle {
|
||||
//use Dispatchers.IO to make a HTTP request to determine the subtitle type
|
||||
var type: SubtitleType? = null
|
||||
var type: SubtitleType?
|
||||
runBlocking {
|
||||
type = findSubtitleType(track.url)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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) {
|
||||
|
|
|
@ -34,6 +34,7 @@ import ani.dantotsu.setSlideIn
|
|||
import ani.dantotsu.setSlideUp
|
||||
import ani.dantotsu.util.AniMarkdown.Companion.getFullAniHTML
|
||||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.tachiyomi.util.system.getSerializableCompat
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
@ -58,7 +59,7 @@ class ProfileFragment : Fragment() {
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
activity = requireActivity() as ProfileActivity
|
||||
|
||||
user = arguments?.getSerializable("user") as Query.UserProfile
|
||||
user = arguments?.getSerializableCompat<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.recycledViewPool.setMaxRecycledViews(0, 0)
|
||||
|
@ -95,7 +96,7 @@ class StatsFragment :
|
|||
}
|
||||
} else {
|
||||
stats.removeAll(
|
||||
stats.filter { it?.id == Anilist.userid }
|
||||
stats.filter { it?.id == Anilist.userid }.toSet()
|
||||
)
|
||||
loadStats(type == MediaType.ANIME)
|
||||
}
|
||||
|
@ -445,6 +446,7 @@ class StatsFragment :
|
|||
}.toMutableList()
|
||||
chartPackets.clear()
|
||||
chartPackets.addAll(standardizedPackets)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val genreChart = ChartBuilder.buildChart(
|
||||
activity,
|
||||
ChartType.TwoDimensional,
|
||||
|
@ -499,6 +501,7 @@ class StatsFragment :
|
|||
}.toMutableList()
|
||||
chartPackets.clear()
|
||||
chartPackets.addAll(standardizedPackets)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val tagChart = ChartBuilder.buildChart(
|
||||
activity,
|
||||
ChartType.TwoDimensional,
|
||||
|
@ -553,6 +556,7 @@ class StatsFragment :
|
|||
}.toMutableList()
|
||||
chartPackets.clear()
|
||||
chartPackets.addAll(standardizedPackets)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val countryChart = ChartBuilder.buildChart(
|
||||
activity,
|
||||
ChartType.OneDimensional,
|
||||
|
@ -609,6 +613,7 @@ class StatsFragment :
|
|||
}.toMutableList()
|
||||
chartPackets.clear()
|
||||
chartPackets.addAll(standardizedPackets)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val voiceActorsChart = ChartBuilder.buildChart(
|
||||
activity,
|
||||
ChartType.TwoDimensional,
|
||||
|
@ -663,6 +668,7 @@ class StatsFragment :
|
|||
}.toMutableList()
|
||||
chartPackets.clear()
|
||||
chartPackets.addAll(standardizedPackets)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val studioChart = ChartBuilder.buildChart(
|
||||
activity,
|
||||
ChartType.TwoDimensional,
|
||||
|
@ -720,6 +726,7 @@ class StatsFragment :
|
|||
}.toMutableList()
|
||||
chartPackets.clear()
|
||||
chartPackets.addAll(standardizedPackets)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val staffChart = ChartBuilder.buildChart(
|
||||
activity,
|
||||
ChartType.TwoDimensional,
|
||||
|
|
|
@ -61,7 +61,7 @@ class FeedActivity : AppCompatActivity() {
|
|||
}
|
||||
})
|
||||
binding.listBack.setOnClickListener {
|
||||
onBackPressed()
|
||||
onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ class NotificationActivity : AppCompatActivity() {
|
|||
binding.followerGrid.visibility = ViewGroup.GONE
|
||||
binding.followerList.visibility = ViewGroup.GONE
|
||||
binding.listBack.setOnClickListener {
|
||||
onBackPressed()
|
||||
onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
binding.listProgressBar.visibility = ViewGroup.VISIBLE
|
||||
val activityId = intent.getIntExtra("activityId", -1)
|
||||
|
|
|
@ -46,7 +46,6 @@ import ani.dantotsu.databinding.ActivitySettingsAboutBinding
|
|||
import ani.dantotsu.databinding.ActivitySettingsAccountsBinding
|
||||
import ani.dantotsu.databinding.ActivitySettingsAnimeBinding
|
||||
import ani.dantotsu.databinding.ActivitySettingsBinding
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.databinding.ActivitySettingsCommonBinding
|
||||
import ani.dantotsu.databinding.ActivitySettingsExtensionsBinding
|
||||
import ani.dantotsu.databinding.ActivitySettingsMangaBinding
|
||||
|
@ -57,7 +56,7 @@ import ani.dantotsu.download.video.ExoplayerDownloadService
|
|||
import ani.dantotsu.downloadsPermission
|
||||
import ani.dantotsu.initActivity
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.notifications.TaskScheduler
|
||||
import ani.dantotsu.notifications.anilist.AnilistNotificationWorker
|
||||
|
@ -81,6 +80,7 @@ import ani.dantotsu.startMainActivity
|
|||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.Logger
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import eltos.simpledialogfragment.SimpleDialog
|
||||
|
@ -151,13 +151,13 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
salt
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
toast("Incorrect password")
|
||||
toast(getString(R.string.incorrect_password))
|
||||
return@passwordAlertDialog
|
||||
}
|
||||
if (PreferencePackager.unpack(decryptedJson))
|
||||
restartApp()
|
||||
} else {
|
||||
toast("Password cannot be empty")
|
||||
toast(getString(R.string.password_cannot_be_empty))
|
||||
}
|
||||
}
|
||||
} else if (name.endsWith(".ani")) {
|
||||
|
@ -165,11 +165,11 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
if (PreferencePackager.unpack(decryptedJson))
|
||||
restartApp()
|
||||
} else {
|
||||
toast("Unknown file type")
|
||||
toast(getString(R.string.unknown_file_type))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
toast("Error importing settings")
|
||||
toast(getString(R.string.error_importing_settings))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
}
|
||||
|
||||
val tag = "colorPicker"
|
||||
CustomColorDialog().title("Custom Theme")
|
||||
CustomColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(originalColor)
|
||||
.colors(this, SimpleColorDialog.MATERIAL_COLOR_PALLET)
|
||||
.allowCustom(true)
|
||||
|
@ -271,7 +271,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
|
||||
val managers = arrayOf("Default", "1DM", "ADM")
|
||||
val downloadManagerDialog =
|
||||
AlertDialog.Builder(this, R.style.MyPopup).setTitle("Download Manager")
|
||||
AlertDialog.Builder(this, R.style.MyPopup).setTitle(R.string.download_manager)
|
||||
var downloadManager: Int = PrefManager.getVal(PrefName.DownloadManager)
|
||||
bindingCommon.settingsDownloadManager.setOnClickListener {
|
||||
val dialog = downloadManagerDialog.setSingleChoiceItems(
|
||||
|
@ -291,7 +291,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
val filteredLocations = Location.entries.filter { it.exportable }
|
||||
selectedArray.addAll(List(filteredLocations.size - 1) { false })
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle("Import/Export Settings")
|
||||
.setTitle(R.string.import_export_settings)
|
||||
.setMultiChoiceItems(
|
||||
filteredLocations.map { it.name }.toTypedArray(),
|
||||
selectedArray.toBooleanArray()
|
||||
|
@ -346,7 +346,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
.setMessage(getString(R.string.purge_confirm, getString(R.string.anime)))
|
||||
.setPositiveButton(R.string.yes) { dialog, _ ->
|
||||
val downloadsManager = Injekt.get<DownloadsManager>()
|
||||
downloadsManager.purgeDownloads(DownloadedType.Type.ANIME)
|
||||
downloadsManager.purgeDownloads(MediaType.ANIME)
|
||||
DownloadService.sendRemoveAllDownloads(
|
||||
this,
|
||||
ExoplayerDownloadService::class.java,
|
||||
|
@ -354,7 +354,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("No") { dialog, _ ->
|
||||
.setNegativeButton(R.string.no) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
|
@ -368,10 +368,10 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
.setMessage(getString(R.string.purge_confirm, getString(R.string.manga)))
|
||||
.setPositiveButton(R.string.yes) { dialog, _ ->
|
||||
val downloadsManager = Injekt.get<DownloadsManager>()
|
||||
downloadsManager.purgeDownloads(DownloadedType.Type.MANGA)
|
||||
downloadsManager.purgeDownloads(MediaType.MANGA)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("No") { dialog, _ ->
|
||||
.setNegativeButton(R.string.no) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
|
@ -385,10 +385,10 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
.setMessage(getString(R.string.purge_confirm, getString(R.string.novels)))
|
||||
.setPositiveButton(R.string.yes) { dialog, _ ->
|
||||
val downloadsManager = Injekt.get<DownloadsManager>()
|
||||
downloadsManager.purgeDownloads(DownloadedType.Type.NOVEL)
|
||||
downloadsManager.purgeDownloads(MediaType.NOVEL)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("No") { dialog, _ ->
|
||||
.setNegativeButton(R.string.no) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
|
@ -423,16 +423,16 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
val alertDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle("User Agent")
|
||||
.setView(dialogView)
|
||||
.setPositiveButton("OK") { dialog, _ ->
|
||||
.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
PrefManager.setVal(PrefName.DefaultUserAgent, editText.text.toString())
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton("Reset") { dialog, _ ->
|
||||
.setNeutralButton(getString(R.string.reset)) { dialog, _ ->
|
||||
PrefManager.removeVal(PrefName.DefaultUserAgent)
|
||||
editText.setText("")
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
|
@ -613,7 +613,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
lifecycleScope.launch {
|
||||
it.pop()
|
||||
}
|
||||
openLinkInBrowser("https://www.buymeacoffee.com/rebelonion")
|
||||
openLinkInBrowser(getString(R.string.coffee))
|
||||
}
|
||||
lifecycleScope.launch {
|
||||
binding.settingBuyMeCoffee.pop()
|
||||
|
@ -905,7 +905,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
if (MAL.token != null) {
|
||||
bindingAccounts.settingsMALLogin.setText(R.string.logout)
|
||||
bindingAccounts.settingsMALLogin.setOnClickListener {
|
||||
MAL.removeSavedToken(it.context)
|
||||
MAL.removeSavedToken()
|
||||
restartMainActivity.isEnabled = true
|
||||
reload()
|
||||
}
|
||||
|
@ -1060,7 +1060,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
box?.setSingleLine()
|
||||
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle("Enter Password")
|
||||
.setTitle(getString(R.string.enter_password))
|
||||
.setView(dialogView)
|
||||
.setPositiveButton("OK", null)
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
|
@ -1076,7 +1076,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
dialog.dismiss()
|
||||
callback(password)
|
||||
} else {
|
||||
toast("Password cannot be empty")
|
||||
toast(getString(R.string.password_cannot_be_empty))
|
||||
}
|
||||
}
|
||||
box?.setOnEditorActionListener { _, actionId, _ ->
|
||||
|
@ -1090,7 +1090,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
val subtitleTextView = dialogView.findViewById<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)
|
||||
|
|
|
@ -12,7 +12,6 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.core.view.isVisible
|
||||
import ani.dantotsu.BottomSheetDialogFragment
|
||||
import ani.dantotsu.MainActivity
|
||||
import ani.dantotsu.profile.ProfileActivity
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.databinding.BottomSheetSettingsBinding
|
||||
|
@ -25,13 +24,15 @@ import ani.dantotsu.home.MangaFragment
|
|||
import ani.dantotsu.home.NoInternet
|
||||
import ani.dantotsu.incognitoNotification
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.profile.activity.NotificationActivity
|
||||
import ani.dantotsu.offline.OfflineFragment
|
||||
import ani.dantotsu.profile.ProfileActivity
|
||||
import ani.dantotsu.profile.activity.FeedActivity
|
||||
import ani.dantotsu.profile.activity.NotificationActivity
|
||||
import ani.dantotsu.setSafeOnClickListener
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.startMainActivity
|
||||
import eu.kanade.tachiyomi.util.system.getSerializableCompat
|
||||
import java.util.Timer
|
||||
import kotlin.concurrent.schedule
|
||||
|
||||
|
@ -42,7 +43,7 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
private lateinit var pageType: PageType
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
pageType = arguments?.getSerializable("pageType") as? PageType ?: PageType.HOME
|
||||
pageType = arguments?.getSerializableCompat("pageType") as? PageType ?: PageType.HOME
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -6,7 +6,7 @@ import ani.dantotsu.util.ColorEditor.Companion.toHexColor
|
|||
class AniMarkdown { //istg anilist has the worst api
|
||||
companion object {
|
||||
private fun convertNestedImageToHtml(markdown: String): String {
|
||||
val regex = """\[\!\[(.*?)\]\((.*?)\)\]\((.*?)\)""".toRegex()
|
||||
val regex = """\[!\[(.*?)]\((.*?)\)]\((.*?)\)""".toRegex()
|
||||
return regex.replace(markdown) { matchResult ->
|
||||
val altText = matchResult.groupValues[1]
|
||||
val imageUrl = matchResult.groupValues[2]
|
||||
|
@ -16,7 +16,7 @@ class AniMarkdown { //istg anilist has the worst api
|
|||
}
|
||||
|
||||
private fun convertImageToHtml(markdown: String): String {
|
||||
val regex = """\!\[(.*?)\]\((.*?)\)""".toRegex()
|
||||
val regex = """!\[(.*?)]\((.*?)\)""".toRegex()
|
||||
return regex.replace(markdown) { matchResult ->
|
||||
val altText = matchResult.groupValues[1]
|
||||
val imageUrl = matchResult.groupValues[2]
|
||||
|
@ -25,7 +25,7 @@ class AniMarkdown { //istg anilist has the worst api
|
|||
}
|
||||
|
||||
private fun convertLinkToHtml(markdown: String): String {
|
||||
val regex = """\[(.*?)\]\((.*?)\)""".toRegex()
|
||||
val regex = """\[(.*?)]\((.*?)\)""".toRegex()
|
||||
return regex.replace(markdown) { matchResult ->
|
||||
val linkText = matchResult.groupValues[1]
|
||||
val linkUrl = matchResult.groupValues[2]
|
||||
|
@ -50,7 +50,7 @@ class AniMarkdown { //istg anilist has the worst api
|
|||
private fun underlineToHtml(html: String): String {
|
||||
return html.replace("(?s)___(.*?)___".toRegex(), "<br><em><strong>$1</strong></em><br>")
|
||||
.replace("(?s)__(.*?)__".toRegex(), "<br><strong>$1</strong><br>")
|
||||
.replace("(?s)[\\s]+_([^_]+)_[\\s]+".toRegex(), "<em>$1</em>")
|
||||
.replace("(?s)\\s+_([^_]+)_\\s+".toRegex(), "<em>$1</em>")
|
||||
}
|
||||
|
||||
fun getBasicAniHTML(html: String): String {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ani.dantotsu.widgets
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.widget.RemoteViews
|
||||
|
@ -12,7 +11,7 @@ import java.io.InputStream
|
|||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
|
||||
class CurrentlyAiringRemoteViewsFactory(private val context: Context, intent: Intent) :
|
||||
class CurrentlyAiringRemoteViewsFactory(private val context: Context) :
|
||||
RemoteViewsService.RemoteViewsFactory {
|
||||
private var widgetItems = mutableListOf<WidgetItem>()
|
||||
|
||||
|
|
|
@ -7,6 +7,6 @@ import ani.dantotsu.util.Logger
|
|||
class CurrentlyAiringRemoteViewsService : RemoteViewsService() {
|
||||
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
|
||||
Logger.log("CurrentlyAiringRemoteViewsFactory onGetViewFactory")
|
||||
return CurrentlyAiringRemoteViewsFactory(applicationContext, intent)
|
||||
return CurrentlyAiringRemoteViewsFactory(applicationContext)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue