commit
f606bef2a5
106 changed files with 951 additions and 612 deletions
|
@ -18,7 +18,9 @@ import ani.dantotsu.Mapper
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.buildMarkwon
|
import ani.dantotsu.buildMarkwon
|
||||||
import ani.dantotsu.client
|
import ani.dantotsu.client
|
||||||
|
import ani.dantotsu.connections.comments.CommentsAPI
|
||||||
import ani.dantotsu.currContext
|
import ani.dantotsu.currContext
|
||||||
|
import ani.dantotsu.decodeBase64ToString
|
||||||
import ani.dantotsu.logError
|
import ani.dantotsu.logError
|
||||||
import ani.dantotsu.openLinkInBrowser
|
import ani.dantotsu.openLinkInBrowser
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
|
@ -37,26 +39,88 @@ import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
object AppUpdater {
|
object AppUpdater {
|
||||||
|
private val fallbackStableUrl: String
|
||||||
|
get() = "aHR0cHM6Ly9hcGkuZGFudG90c3UuYXBwL3VwZGF0ZXMvc3RhYmxl".decodeBase64ToString()
|
||||||
|
private val fallbackBetaUrl: String
|
||||||
|
get() = "aHR0cHM6Ly9hcGkuZGFudG90c3UuYXBwL3VwZGF0ZXMvYmV0YQ==".decodeBase64ToString()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class FallbackResponse(
|
||||||
|
val version: String,
|
||||||
|
val changelog: String,
|
||||||
|
val downloadUrl: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
private suspend fun fetchUpdateInfo(repo: String, isDebug: Boolean): Pair<String, String>? {
|
||||||
|
return try {
|
||||||
|
fetchFromGithub(repo, isDebug)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.log("Github fetch failed, trying fallback: ${e.message}")
|
||||||
|
try {
|
||||||
|
fetchFromFallback(isDebug)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.log("Fallback fetch failed: ${e.message}")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun fetchFromGithub(repo: String, isDebug: Boolean): Pair<String, String> {
|
||||||
|
return if (isDebug) {
|
||||||
|
val res = client.get("https://api.github.com/repos/$repo/releases")
|
||||||
|
.parsed<JsonArray>().map {
|
||||||
|
Mapper.json.decodeFromJsonElement<GithubResponse>(it)
|
||||||
|
}
|
||||||
|
val r = res.filter { it.prerelease }.filter { !it.tagName.contains("fdroid") }
|
||||||
|
.maxByOrNull {
|
||||||
|
it.timeStamp()
|
||||||
|
} ?: throw Exception("No Pre Release Found")
|
||||||
|
val v = r.tagName.substringAfter("v", "")
|
||||||
|
(r.body ?: "") to v.ifEmpty { throw Exception("Weird Version : ${r.tagName}") }
|
||||||
|
} else {
|
||||||
|
val res = client.get("https://raw.githubusercontent.com/$repo/main/stable.md").text
|
||||||
|
res to res.substringAfter("# ").substringBefore("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun fetchFromFallback(isDebug: Boolean): Pair<String, String> {
|
||||||
|
val url = if (isDebug) fallbackBetaUrl else fallbackStableUrl
|
||||||
|
val response = CommentsAPI.requestBuilder().get(url).parsed<FallbackResponse>()
|
||||||
|
return response.changelog to response.version
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun fetchApkUrl(repo: String, version: String, isDebug: Boolean): String? {
|
||||||
|
return try {
|
||||||
|
fetchApkUrlFromGithub(repo, version)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.log("Github APK fetch failed, trying fallback: ${e.message}")
|
||||||
|
try {
|
||||||
|
fetchApkUrlFromFallback(version, isDebug)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.log("Fallback APK fetch failed: ${e.message}")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun fetchApkUrlFromGithub(repo: String, version: String): String? {
|
||||||
|
val apks = client.get("https://api.github.com/repos/$repo/releases/tags/v$version")
|
||||||
|
.parsed<GithubResponse>().assets?.filter {
|
||||||
|
it.browserDownloadURL.endsWith(".apk")
|
||||||
|
}
|
||||||
|
return apks?.firstOrNull()?.browserDownloadURL
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun fetchApkUrlFromFallback(version: String, isDebug: Boolean): String? {
|
||||||
|
val url = if (isDebug) fallbackBetaUrl else fallbackStableUrl
|
||||||
|
return CommentsAPI.requestBuilder().get("$url/$version").parsed<FallbackResponse>().downloadUrl
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun check(activity: FragmentActivity, post: Boolean = false) {
|
suspend fun check(activity: FragmentActivity, post: Boolean = false) {
|
||||||
if (post) snackString(currContext()?.getString(R.string.checking_for_update))
|
if (post) snackString(currContext()?.getString(R.string.checking_for_update))
|
||||||
val repo = activity.getString(R.string.repo)
|
val repo = activity.getString(R.string.repo)
|
||||||
tryWithSuspend {
|
tryWithSuspend {
|
||||||
val (md, version) = if (BuildConfig.DEBUG) {
|
val (md, version) = fetchUpdateInfo(repo, BuildConfig.DEBUG) ?: return@tryWithSuspend
|
||||||
val res = client.get("https://api.github.com/repos/$repo/releases")
|
|
||||||
.parsed<JsonArray>().map {
|
|
||||||
Mapper.json.decodeFromJsonElement<GithubResponse>(it)
|
|
||||||
}
|
|
||||||
val r = res.filter { it.prerelease }.filter { !it.tagName.contains("fdroid") }
|
|
||||||
.maxByOrNull {
|
|
||||||
it.timeStamp()
|
|
||||||
} ?: throw Exception("No Pre Release Found")
|
|
||||||
val v = r.tagName.substringAfter("v", "")
|
|
||||||
(r.body ?: "") to v.ifEmpty { throw Exception("Weird Version : ${r.tagName}") }
|
|
||||||
} else {
|
|
||||||
val res =
|
|
||||||
client.get("https://raw.githubusercontent.com/$repo/main/stable.md").text
|
|
||||||
res to res.substringAfter("# ").substringBefore("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.log("Git Version : $version")
|
Logger.log("Git Version : $version")
|
||||||
val dontShow = PrefManager.getCustomVal("dont_ask_for_update_$version", false)
|
val dontShow = PrefManager.getCustomVal("dont_ask_for_update_$version", false)
|
||||||
|
@ -69,7 +133,7 @@ object AppUpdater {
|
||||||
)
|
)
|
||||||
addView(
|
addView(
|
||||||
TextView(activity).apply {
|
TextView(activity).apply {
|
||||||
val markWon = try { //slower phones can destroy the activity before this is done
|
val markWon = try {
|
||||||
buildMarkwon(activity, false)
|
buildMarkwon(activity, false)
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
return@runOnUiThread
|
return@runOnUiThread
|
||||||
|
@ -89,17 +153,11 @@ object AppUpdater {
|
||||||
setPositiveButton(currContext()!!.getString(R.string.lets_go)) {
|
setPositiveButton(currContext()!!.getString(R.string.lets_go)) {
|
||||||
MainScope().launch(Dispatchers.IO) {
|
MainScope().launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val apks =
|
val apkUrl = fetchApkUrl(repo, version, BuildConfig.DEBUG)
|
||||||
client.get("https://api.github.com/repos/$repo/releases/tags/v$version")
|
if (apkUrl != null) {
|
||||||
.parsed<GithubResponse>().assets?.filter {
|
activity.downloadUpdate(version, apkUrl)
|
||||||
it.browserDownloadURL.endsWith(
|
} else {
|
||||||
".apk"
|
openLinkInBrowser("https://github.com/repos/$repo/releases/tag/v$version")
|
||||||
)
|
|
||||||
}
|
|
||||||
val apkToDownload = apks?.first()
|
|
||||||
apkToDownload?.browserDownloadURL.apply {
|
|
||||||
if (this != null) activity.downloadUpdate(version, this)
|
|
||||||
else openLinkInBrowser("https://github.com/repos/$repo/releases/tag/v$version")
|
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logError(e)
|
logError(e)
|
||||||
|
@ -112,8 +170,7 @@ object AppUpdater {
|
||||||
}
|
}
|
||||||
show(activity.supportFragmentManager, "dialog")
|
show(activity.supportFragmentManager, "dialog")
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (post) snackString(currContext()?.getString(R.string.no_update_found))
|
if (post) snackString(currContext()?.getString(R.string.no_update_found))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,8 +201,7 @@ object AppUpdater {
|
||||||
|
|
||||||
|
|
||||||
//Blatantly kanged from https://github.com/LagradOst/CloudStream-3/blob/master/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt
|
//Blatantly kanged from https://github.com/LagradOst/CloudStream-3/blob/master/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt
|
||||||
private fun Activity.downloadUpdate(version: String, url: String): Boolean {
|
private fun Activity.downloadUpdate(version: String, url: String) {
|
||||||
|
|
||||||
toast(getString(R.string.downloading_update, version))
|
toast(getString(R.string.downloading_update, version))
|
||||||
|
|
||||||
val downloadManager = this.getSystemService<DownloadManager>()!!
|
val downloadManager = this.getSystemService<DownloadManager>()!!
|
||||||
|
@ -167,7 +223,7 @@ object AppUpdater {
|
||||||
logError(e)
|
logError(e)
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
if (id == -1L) return true
|
if (id == -1L) return
|
||||||
ContextCompat.registerReceiver(
|
ContextCompat.registerReceiver(
|
||||||
this,
|
this,
|
||||||
object : BroadcastReceiver() {
|
object : BroadcastReceiver() {
|
||||||
|
@ -188,7 +244,6 @@ object AppUpdater {
|
||||||
}, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE),
|
}, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE),
|
||||||
ContextCompat.RECEIVER_EXPORTED
|
ContextCompat.RECEIVER_EXPORTED
|
||||||
)
|
)
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openApk(context: Context, uri: Uri) {
|
private fun openApk(context: Context, uri: Uri) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
`<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
@ -113,10 +113,8 @@
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
<data android:host="*"/>
|
|
||||||
<data android:mimeType="application/epub+zip"/>
|
<data android:mimeType="application/epub+zip"/>
|
||||||
<data android:mimeType="application/x-mobipocket-ebook" />
|
<data android:mimeType="application/x-mobipocket-ebook" />
|
||||||
<data android:mimeType="application/vnd.amazon.ebook" />
|
<data android:mimeType="application/vnd.amazon.ebook" />
|
||||||
|
@ -385,10 +383,10 @@
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<data android:scheme="content" />
|
<data android:scheme="content" />
|
||||||
|
<data android:scheme="file" />
|
||||||
<data android:mimeType="*/*" />
|
<data android:mimeType="*/*" />
|
||||||
<data android:pathPattern=".*\\.ani" />
|
<data android:pathPattern=".*\\.ani" />
|
||||||
<data android:pathPattern=".*\\.sani" />
|
<data android:pathPattern=".*\\.sani" />
|
||||||
<data android:host="*" />
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
|
@ -107,9 +107,9 @@ class App : MultiDexApplication() {
|
||||||
|
|
||||||
if (PrefManager.getVal<Int>(PrefName.CommentsEnabled) == 0) {
|
if (PrefManager.getVal<Int>(PrefName.CommentsEnabled) == 0) {
|
||||||
if (BuildConfig.FLAVOR.contains("fdroid")) {
|
if (BuildConfig.FLAVOR.contains("fdroid")) {
|
||||||
PrefManager.setVal(PrefName.CommentsEnabled, 2)
|
PrefManager.setVal(PrefName.CommentsEnabled, 2)
|
||||||
} else {
|
} else {
|
||||||
PrefManager.setVal(PrefName.CommentsEnabled, 1)
|
PrefManager.setVal(PrefName.CommentsEnabled, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ class App : MultiDexApplication() {
|
||||||
downloadAddonManager.init()
|
downloadAddonManager.init()
|
||||||
if (PrefManager.getVal<Int>(PrefName.CommentsEnabled) == 1) {
|
if (PrefManager.getVal<Int>(PrefName.CommentsEnabled) == 1) {
|
||||||
CommentsAPI.fetchAuthToken(this@App)
|
CommentsAPI.fetchAuthToken(this@App)
|
||||||
}
|
}
|
||||||
|
|
||||||
val useAlarmManager = PrefManager.getVal<Boolean>(PrefName.UseAlarmManager)
|
val useAlarmManager = PrefManager.getVal<Boolean>(PrefName.UseAlarmManager)
|
||||||
val scheduler = TaskScheduler.create(this@App, useAlarmManager)
|
val scheduler = TaskScheduler.create(this@App, useAlarmManager)
|
||||||
|
|
|
@ -117,7 +117,6 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withC
|
||||||
import com.bumptech.glide.load.resource.gif.GifDrawable
|
import com.bumptech.glide.load.resource.gif.GifDrawable
|
||||||
import com.bumptech.glide.request.RequestListener
|
import com.bumptech.glide.request.RequestListener
|
||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
import com.bumptech.glide.request.target.CustomTarget
|
|
||||||
import com.bumptech.glide.request.target.Target
|
import com.bumptech.glide.request.target.Target
|
||||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
|
@ -138,12 +137,9 @@ import io.noties.markwon.html.TagHandlerNoOp
|
||||||
import io.noties.markwon.image.AsyncDrawable
|
import io.noties.markwon.image.AsyncDrawable
|
||||||
import io.noties.markwon.image.glide.GlideImagesPlugin
|
import io.noties.markwon.image.glide.GlideImagesPlugin
|
||||||
import jp.wasabeef.glide.transformations.BlurTransformation
|
import jp.wasabeef.glide.transformations.BlurTransformation
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import nl.joery.animatedbottombar.AnimatedBottomBar
|
import nl.joery.animatedbottombar.AnimatedBottomBar
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
@ -157,6 +153,8 @@ import java.util.TimeZone
|
||||||
import java.util.Timer
|
import java.util.Timer
|
||||||
import java.util.TimerTask
|
import java.util.TimerTask
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
|
import kotlin.io.encoding.Base64
|
||||||
|
import kotlin.io.encoding.ExperimentalEncodingApi
|
||||||
import kotlin.math.log2
|
import kotlin.math.log2
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
@ -854,6 +852,7 @@ fun savePrefsToDownloads(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("StringFormatMatches")
|
@SuppressLint("StringFormatMatches")
|
||||||
fun savePrefs(serialized: String, path: String, title: String, context: Context): File? {
|
fun savePrefs(serialized: String, path: String, title: String, context: Context): File? {
|
||||||
var file = File(path, "$title.ani")
|
var file = File(path, "$title.ani")
|
||||||
|
@ -921,6 +920,7 @@ fun shareImage(title: String, bitmap: Bitmap, context: Context) {
|
||||||
intent.putExtra(Intent.EXTRA_STREAM, contentUri)
|
intent.putExtra(Intent.EXTRA_STREAM, contentUri)
|
||||||
context.startActivity(Intent.createChooser(intent, "Share $title"))
|
context.startActivity(Intent.createChooser(intent, "Share $title"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("StringFormatMatches")
|
@SuppressLint("StringFormatMatches")
|
||||||
fun saveImage(image: Bitmap, path: String, imageFileName: String): File? {
|
fun saveImage(image: Bitmap, path: String, imageFileName: String): File? {
|
||||||
val imageFile = File(path, "$imageFileName.png")
|
val imageFile = File(path, "$imageFileName.png")
|
||||||
|
@ -1467,6 +1467,7 @@ fun buildMarkwon(
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLoadFailed(
|
override fun onLoadFailed(
|
||||||
e: GlideException?,
|
e: GlideException?,
|
||||||
model: Any?,
|
model: Any?,
|
||||||
|
@ -1495,9 +1496,9 @@ fun buildMarkwon(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun getYoutubeId(url: String): String {
|
fun getYoutubeId(url: String): String {
|
||||||
val regex = """(?:youtube\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|(?:youtu\.be|youtube\.com)/)([^"&?/\s]{11})|youtube\.com/""".toRegex()
|
val regex =
|
||||||
|
"""(?:youtube\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|(?:youtu\.be|youtube\.com)/)([^"&?/\s]{11})|youtube\.com/""".toRegex()
|
||||||
val matchResult = regex.find(url)
|
val matchResult = regex.find(url)
|
||||||
return matchResult?.groupValues?.getOrNull(1) ?: ""
|
return matchResult?.groupValues?.getOrNull(1) ?: ""
|
||||||
}
|
}
|
||||||
|
@ -1524,3 +1525,13 @@ fun getLanguageName(language: String): String? {
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalEncodingApi::class)
|
||||||
|
fun String.decodeBase64ToString(): String {
|
||||||
|
return try {
|
||||||
|
String(Base64.decode(this), Charsets.UTF_8)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.log(e)
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,9 +26,17 @@ interface DownloadAddonApiV2 {
|
||||||
statCallback: (Double) -> Unit
|
statCallback: (Double) -> Unit
|
||||||
): Long
|
): Long
|
||||||
|
|
||||||
suspend fun customFFMpeg(command: String, videoUrls: List<String>, logCallback: (String) -> Unit): Long
|
suspend fun customFFMpeg(
|
||||||
|
command: String,
|
||||||
|
videoUrls: List<String>,
|
||||||
|
logCallback: (String) -> Unit
|
||||||
|
): Long
|
||||||
|
|
||||||
suspend fun customFFProbe(command: String, videoUrls: List<String>, logCallback: (String) -> Unit)
|
suspend fun customFFProbe(
|
||||||
|
command: String,
|
||||||
|
videoUrls: List<String>,
|
||||||
|
logCallback: (String) -> Unit
|
||||||
|
)
|
||||||
|
|
||||||
fun getState(sessionId: Long): String
|
fun getState(sessionId: Long): String
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,11 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.addons.AddonDownloader.Companion.hasUpdate
|
import ani.dantotsu.addons.AddonDownloader.Companion.hasUpdate
|
||||||
|
import ani.dantotsu.addons.AddonInstallReceiver
|
||||||
import ani.dantotsu.addons.AddonListener
|
import ani.dantotsu.addons.AddonListener
|
||||||
import ani.dantotsu.addons.AddonLoader
|
import ani.dantotsu.addons.AddonLoader
|
||||||
import ani.dantotsu.addons.AddonManager
|
import ani.dantotsu.addons.AddonManager
|
||||||
import ani.dantotsu.addons.LoadResult
|
import ani.dantotsu.addons.LoadResult
|
||||||
import ani.dantotsu.addons.AddonInstallReceiver
|
|
||||||
import ani.dantotsu.media.AddonType
|
import ani.dantotsu.media.AddonType
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
|
|
|
@ -41,7 +41,8 @@ class TorrentServerService : Service() {
|
||||||
flags: Int,
|
flags: Int,
|
||||||
startId: Int,
|
startId: Int,
|
||||||
): Int {
|
): Int {
|
||||||
extension = Injekt.get<TorrentAddonManager>().extension?.extension ?: return START_NOT_STICKY
|
extension =
|
||||||
|
Injekt.get<TorrentAddonManager>().extension?.extension ?: return START_NOT_STICKY
|
||||||
intent?.let {
|
intent?.let {
|
||||||
if (it.action != null) {
|
if (it.action != null) {
|
||||||
when (it.action) {
|
when (it.action) {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.database.StandaloneDatabaseProvider
|
import androidx.media3.database.StandaloneDatabaseProvider
|
||||||
import ani.dantotsu.addons.download.DownloadAddonManager
|
import ani.dantotsu.addons.download.DownloadAddonManager
|
||||||
import ani.dantotsu.addons.torrent.TorrentAddonManager
|
import ani.dantotsu.addons.torrent.TorrentAddonManager
|
||||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
|
||||||
import ani.dantotsu.download.DownloadsManager
|
import ani.dantotsu.download.DownloadsManager
|
||||||
import ani.dantotsu.media.manga.MangaCache
|
import ani.dantotsu.media.manga.MangaCache
|
||||||
import ani.dantotsu.parsers.novel.NovelExtensionManager
|
import ani.dantotsu.parsers.novel.NovelExtensionManager
|
||||||
|
|
|
@ -145,7 +145,10 @@ class AnilistMutations {
|
||||||
return result?.get("errors") == null
|
return result?.get("errors") == null
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateCustomLists(animeCustomLists: List<String>?, mangaCustomLists: List<String>?): Boolean {
|
suspend fun updateCustomLists(
|
||||||
|
animeCustomLists: List<String>?,
|
||||||
|
mangaCustomLists: List<String>?
|
||||||
|
): Boolean {
|
||||||
val query = """
|
val query = """
|
||||||
mutation (${"$"}animeListOptions: MediaListOptionsInput, ${"$"}mangaListOptions: MediaListOptionsInput) {
|
mutation (${"$"}animeListOptions: MediaListOptionsInput, ${"$"}mangaListOptions: MediaListOptionsInput) {
|
||||||
UpdateUser(animeListOptions: ${"$"}animeListOptions, mangaListOptions: ${"$"}mangaListOptions) {
|
UpdateUser(animeListOptions: ${"$"}animeListOptions, mangaListOptions: ${"$"}mangaListOptions) {
|
||||||
|
@ -291,7 +294,8 @@ class AnilistMutations {
|
||||||
isFollower
|
isFollower
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
""".trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun toggleLike(id: Int, type: String): ToggleLike? {
|
suspend fun toggleLike(id: Int, type: String): ToggleLike? {
|
||||||
|
@ -302,7 +306,8 @@ class AnilistMutations {
|
||||||
__typename
|
__typename
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
""".trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun postActivity(text: String, edit: Int? = null): String {
|
suspend fun postActivity(text: String, edit: Int? = null): String {
|
||||||
|
@ -316,10 +321,16 @@ class AnilistMutations {
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val result = executeQuery<JsonObject>(query)
|
val result = executeQuery<JsonObject>(query)
|
||||||
val errors = result?.get("errors")
|
val errors = result?.get("errors")
|
||||||
return errors?.toString() ?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
|
return errors?.toString() ?: (currContext()?.getString(ani.dantotsu.R.string.success)
|
||||||
|
?: "Success")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun postMessage(userId: Int, text: String, edit: Int? = null, isPrivate: Boolean = false): String {
|
suspend fun postMessage(
|
||||||
|
userId: Int,
|
||||||
|
text: String,
|
||||||
|
edit: Int? = null,
|
||||||
|
isPrivate: Boolean = false
|
||||||
|
): String {
|
||||||
val encodedText = text.replace("", "").stringSanitizer()
|
val encodedText = text.replace("", "").stringSanitizer()
|
||||||
val query = """
|
val query = """
|
||||||
mutation {
|
mutation {
|
||||||
|
@ -335,7 +346,8 @@ class AnilistMutations {
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val result = executeQuery<JsonObject>(query)
|
val result = executeQuery<JsonObject>(query)
|
||||||
val errors = result?.get("errors")
|
val errors = result?.get("errors")
|
||||||
return errors?.toString() ?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
|
return errors?.toString() ?: (currContext()?.getString(ani.dantotsu.R.string.success)
|
||||||
|
?: "Success")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun postReply(activityId: Int, text: String, edit: Int? = null): String {
|
suspend fun postReply(activityId: Int, text: String, edit: Int? = null): String {
|
||||||
|
@ -353,7 +365,8 @@ class AnilistMutations {
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val result = executeQuery<JsonObject>(query)
|
val result = executeQuery<JsonObject>(query)
|
||||||
val errors = result?.get("errors")
|
val errors = result?.get("errors")
|
||||||
return errors?.toString() ?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
|
return errors?.toString() ?: (currContext()?.getString(ani.dantotsu.R.string.success)
|
||||||
|
?: "Success")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun postReview(summary: String, body: String, mediaId: Int, score: Int): String {
|
suspend fun postReview(summary: String, body: String, mediaId: Int, score: Int): String {
|
||||||
|
@ -373,7 +386,8 @@ class AnilistMutations {
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val result = executeQuery<JsonObject>(query)
|
val result = executeQuery<JsonObject>(query)
|
||||||
val errors = result?.get("errors")
|
val errors = result?.get("errors")
|
||||||
return errors?.toString() ?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
|
return errors?.toString() ?: (currContext()?.getString(ani.dantotsu.R.string.success)
|
||||||
|
?: "Success")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteActivityReply(activityId: Int): Boolean {
|
suspend fun deleteActivityReply(activityId: Int): Boolean {
|
||||||
|
|
|
@ -359,19 +359,24 @@ class AnilistSearch : ViewModel() {
|
||||||
var searched = false
|
var searched = false
|
||||||
var notSet = true
|
var notSet = true
|
||||||
lateinit var aniMangaSearchResults: AniMangaSearchResults
|
lateinit var aniMangaSearchResults: AniMangaSearchResults
|
||||||
private val aniMangaResult: MutableLiveData<AniMangaSearchResults?> = MutableLiveData<AniMangaSearchResults?>(null)
|
private val aniMangaResult: MutableLiveData<AniMangaSearchResults?> =
|
||||||
|
MutableLiveData<AniMangaSearchResults?>(null)
|
||||||
|
|
||||||
lateinit var characterSearchResults: CharacterSearchResults
|
lateinit var characterSearchResults: CharacterSearchResults
|
||||||
private val characterResult: MutableLiveData<CharacterSearchResults?> = MutableLiveData<CharacterSearchResults?>(null)
|
private val characterResult: MutableLiveData<CharacterSearchResults?> =
|
||||||
|
MutableLiveData<CharacterSearchResults?>(null)
|
||||||
|
|
||||||
lateinit var studioSearchResults: StudioSearchResults
|
lateinit var studioSearchResults: StudioSearchResults
|
||||||
private val studioResult: MutableLiveData<StudioSearchResults?> = MutableLiveData<StudioSearchResults?>(null)
|
private val studioResult: MutableLiveData<StudioSearchResults?> =
|
||||||
|
MutableLiveData<StudioSearchResults?>(null)
|
||||||
|
|
||||||
lateinit var staffSearchResults: StaffSearchResults
|
lateinit var staffSearchResults: StaffSearchResults
|
||||||
private val staffResult: MutableLiveData<StaffSearchResults?> = MutableLiveData<StaffSearchResults?>(null)
|
private val staffResult: MutableLiveData<StaffSearchResults?> =
|
||||||
|
MutableLiveData<StaffSearchResults?>(null)
|
||||||
|
|
||||||
lateinit var userSearchResults: UserSearchResults
|
lateinit var userSearchResults: UserSearchResults
|
||||||
private val userResult: MutableLiveData<UserSearchResults?> = MutableLiveData<UserSearchResults?>(null)
|
private val userResult: MutableLiveData<UserSearchResults?> =
|
||||||
|
MutableLiveData<UserSearchResults?>(null)
|
||||||
|
|
||||||
fun <T> getSearch(type: SearchType): MutableLiveData<T?> {
|
fun <T> getSearch(type: SearchType): MutableLiveData<T?> {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
|
@ -517,12 +522,13 @@ class AnilistSearch : ViewModel() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
private suspend fun loadNextCharacterPage(r: CharacterSearchResults) = characterResult.postValue(
|
private suspend fun loadNextCharacterPage(r: CharacterSearchResults) =
|
||||||
Anilist.query.searchCharacters(
|
characterResult.postValue(
|
||||||
r.page + 1,
|
Anilist.query.searchCharacters(
|
||||||
r.search,
|
r.page + 1,
|
||||||
|
r.search,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
private suspend fun loadNextStudiosPage(r: StudioSearchResults) = studioResult.postValue(
|
private suspend fun loadNextStudiosPage(r: StudioSearchResults) = studioResult.postValue(
|
||||||
Anilist.query.searchStudios(
|
Anilist.query.searchStudios(
|
||||||
|
|
|
@ -34,7 +34,8 @@ fun characterInformation(includeMediaInfo: Boolean) = """
|
||||||
month
|
month
|
||||||
day
|
day
|
||||||
}
|
}
|
||||||
${if (includeMediaInfo) """
|
${
|
||||||
|
if (includeMediaInfo) """
|
||||||
media(page: 0,sort:[POPULARITY_DESC,SCORE_DESC]) {
|
media(page: 0,sort:[POPULARITY_DESC,SCORE_DESC]) {
|
||||||
$standardPageInformation
|
$standardPageInformation
|
||||||
edges {
|
edges {
|
||||||
|
@ -79,7 +80,8 @@ fun characterInformation(includeMediaInfo: Boolean) = """
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}""".prepare() else ""}
|
}""".prepare() else ""
|
||||||
|
}
|
||||||
""".prepare()
|
""".prepare()
|
||||||
|
|
||||||
fun studioInformation(page: Int, perPage: Int) = """
|
fun studioInformation(page: Int, perPage: Int) = """
|
||||||
|
|
|
@ -14,6 +14,7 @@ data class FeedResponse(
|
||||||
val page: ActivityPage
|
val page: ActivityPage
|
||||||
) : java.io.Serializable
|
) : java.io.Serializable
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class ActivityPage(
|
data class ActivityPage(
|
||||||
@SerialName("activities")
|
@SerialName("activities")
|
||||||
|
|
|
@ -189,7 +189,7 @@ data class MediaTitle(
|
||||||
|
|
||||||
// The currently authenticated users preferred title language. Default romaji for non-authenticated
|
// The currently authenticated users preferred title language. Default romaji for non-authenticated
|
||||||
@SerialName("userPreferred") var userPreferred: String,
|
@SerialName("userPreferred") var userPreferred: String,
|
||||||
): java.io.Serializable
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
enum class MediaType {
|
enum class MediaType {
|
||||||
|
@ -239,6 +239,7 @@ data class AiringSchedule(
|
||||||
// The associate media of the airing episode
|
// The associate media of the airing episode
|
||||||
@SerialName("media") var media: Media?,
|
@SerialName("media") var media: Media?,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MediaStreamingEpisode(
|
data class MediaStreamingEpisode(
|
||||||
// The title of the episode
|
// The title of the episode
|
||||||
|
@ -253,6 +254,7 @@ data class MediaStreamingEpisode(
|
||||||
// The site location of the streaming episode
|
// The site location of the streaming episode
|
||||||
@SerialName("site") var site: String?,
|
@SerialName("site") var site: String?,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MediaCoverImage(
|
data class MediaCoverImage(
|
||||||
// The cover image url of the media at its largest size. If this size isn't available, large will be provided instead.
|
// The cover image url of the media at its largest size. If this size isn't available, large will be provided instead.
|
||||||
|
|
|
@ -69,7 +69,7 @@ data class User(
|
||||||
// The user's previously used names.
|
// The user's previously used names.
|
||||||
// @SerialName("previousNames") var previousNames: List<UserPreviousName>?,
|
// @SerialName("previousNames") var previousNames: List<UserPreviousName>?,
|
||||||
|
|
||||||
): java.io.Serializable
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class UserOptions(
|
data class UserOptions(
|
||||||
|
@ -123,8 +123,10 @@ data class UserStatisticTypes(
|
||||||
enum class UserTitleLanguage {
|
enum class UserTitleLanguage {
|
||||||
@SerialName("ENGLISH")
|
@SerialName("ENGLISH")
|
||||||
ENGLISH,
|
ENGLISH,
|
||||||
|
|
||||||
@SerialName("ROMAJI")
|
@SerialName("ROMAJI")
|
||||||
ROMAJI,
|
ROMAJI,
|
||||||
|
|
||||||
@SerialName("NATIVE")
|
@SerialName("NATIVE")
|
||||||
NATIVE
|
NATIVE
|
||||||
}
|
}
|
||||||
|
@ -133,8 +135,10 @@ enum class UserTitleLanguage {
|
||||||
enum class UserStaffNameLanguage {
|
enum class UserStaffNameLanguage {
|
||||||
@SerialName("ROMAJI_WESTERN")
|
@SerialName("ROMAJI_WESTERN")
|
||||||
ROMAJI_WESTERN,
|
ROMAJI_WESTERN,
|
||||||
|
|
||||||
@SerialName("ROMAJI")
|
@SerialName("ROMAJI")
|
||||||
ROMAJI,
|
ROMAJI,
|
||||||
|
|
||||||
@SerialName("NATIVE")
|
@SerialName("NATIVE")
|
||||||
NATIVE
|
NATIVE
|
||||||
}
|
}
|
||||||
|
@ -143,12 +147,16 @@ enum class UserStaffNameLanguage {
|
||||||
enum class ScoreFormat {
|
enum class ScoreFormat {
|
||||||
@SerialName("POINT_100")
|
@SerialName("POINT_100")
|
||||||
POINT_100,
|
POINT_100,
|
||||||
|
|
||||||
@SerialName("POINT_10_DECIMAL")
|
@SerialName("POINT_10_DECIMAL")
|
||||||
POINT_10_DECIMAL,
|
POINT_10_DECIMAL,
|
||||||
|
|
||||||
@SerialName("POINT_10")
|
@SerialName("POINT_10")
|
||||||
POINT_10,
|
POINT_10,
|
||||||
|
|
||||||
@SerialName("POINT_5")
|
@SerialName("POINT_5")
|
||||||
POINT_5,
|
POINT_5,
|
||||||
|
|
||||||
@SerialName("POINT_3")
|
@SerialName("POINT_3")
|
||||||
POINT_3,
|
POINT_3,
|
||||||
}
|
}
|
||||||
|
|
|
@ -372,6 +372,7 @@ object CommentsAPI {
|
||||||
}
|
}
|
||||||
errorMessage("Failed to login after multiple attempts")
|
errorMessage("Failed to login after multiple attempts")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun errorMessage(reason: String) {
|
private fun errorMessage(reason: String) {
|
||||||
if (commentsEnabled) Logger.log(reason)
|
if (commentsEnabled) Logger.log(reason)
|
||||||
if (isOnline && commentsEnabled) snackString(reason)
|
if (isOnline && commentsEnabled) snackString(reason)
|
||||||
|
@ -410,7 +411,7 @@ object CommentsAPI {
|
||||||
return map
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requestBuilder(client: OkHttpClient = Injekt.get<NetworkHelper>().client): Requests {
|
fun requestBuilder(client: OkHttpClient = Injekt.get<NetworkHelper>().client): Requests {
|
||||||
return Requests(
|
return Requests(
|
||||||
client,
|
client,
|
||||||
headerBuilder()
|
headerBuilder()
|
||||||
|
|
|
@ -8,8 +8,8 @@ import ani.dantotsu.settings.saving.PrefName
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
import java.util.concurrent.TimeUnit.SECONDS
|
import java.util.concurrent.TimeUnit.SECONDS
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
open class RPC(val token: String, val coroutineContext: CoroutineContext) {
|
open class RPC(val token: String, val coroutineContext: CoroutineContext) {
|
||||||
|
@ -34,6 +34,7 @@ open class RPC(val token: String, val coroutineContext: CoroutineContext) {
|
||||||
val stopTimestamp: Long? = null,
|
val stopTimestamp: Long? = null,
|
||||||
val buttons: MutableList<Link> = mutableListOf()
|
val buttons: MutableList<Link> = mutableListOf()
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun createPresence(data: RPCData): String {
|
suspend fun createPresence(data: RPCData): String {
|
||||||
val json = Json {
|
val json = Json {
|
||||||
encodeDefaults = true
|
encodeDefaults = true
|
||||||
|
|
|
@ -30,7 +30,6 @@ import ani.dantotsu.bottomBar
|
||||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||||
import ani.dantotsu.currActivity
|
import ani.dantotsu.currActivity
|
||||||
import ani.dantotsu.currContext
|
import ani.dantotsu.currContext
|
||||||
import ani.dantotsu.download.DownloadCompat
|
|
||||||
import ani.dantotsu.download.DownloadCompat.Companion.loadMediaCompat
|
import ani.dantotsu.download.DownloadCompat.Companion.loadMediaCompat
|
||||||
import ani.dantotsu.download.DownloadCompat.Companion.loadOfflineAnimeModelCompat
|
import ani.dantotsu.download.DownloadCompat.Companion.loadOfflineAnimeModelCompat
|
||||||
import ani.dantotsu.download.DownloadedType
|
import ani.dantotsu.download.DownloadedType
|
||||||
|
@ -209,7 +208,9 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
||||||
setMessage("Are you sure you want to delete ${item.title}?")
|
setMessage("Are you sure you want to delete ${item.title}?")
|
||||||
setPosButton(R.string.yes) {
|
setPosButton(R.string.yes) {
|
||||||
downloadManager.removeMedia(item.title, type)
|
downloadManager.removeMedia(item.title, type)
|
||||||
val mediaIds = PrefManager.getAnimeDownloadPreferences().all?.filter { it.key.contains(item.title) }?.values ?: emptySet()
|
val mediaIds =
|
||||||
|
PrefManager.getAnimeDownloadPreferences().all?.filter { it.key.contains(item.title) }?.values
|
||||||
|
?: emptySet()
|
||||||
if (mediaIds.isEmpty()) {
|
if (mediaIds.isEmpty()) {
|
||||||
snackString("No media found") // if this happens, terrible things have happened
|
snackString("No media found") // if this happens, terrible things have happened
|
||||||
}
|
}
|
||||||
|
@ -287,10 +288,12 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
||||||
}
|
}
|
||||||
downloadsJob = Job()
|
downloadsJob = Job()
|
||||||
CoroutineScope(Dispatchers.IO + downloadsJob).launch {
|
CoroutineScope(Dispatchers.IO + downloadsJob).launch {
|
||||||
val animeTitles = downloadManager.animeDownloadedTypes.map { it.titleName.findValidName() }.distinct()
|
val animeTitles =
|
||||||
|
downloadManager.animeDownloadedTypes.map { it.titleName.findValidName() }.distinct()
|
||||||
val newAnimeDownloads = mutableListOf<OfflineAnimeModel>()
|
val newAnimeDownloads = mutableListOf<OfflineAnimeModel>()
|
||||||
for (title in animeTitles) {
|
for (title in animeTitles) {
|
||||||
val tDownloads = downloadManager.animeDownloadedTypes.filter { it.titleName.findValidName() == title }
|
val tDownloads =
|
||||||
|
downloadManager.animeDownloadedTypes.filter { it.titleName.findValidName() == title }
|
||||||
val download = tDownloads.firstOrNull() ?: continue
|
val download = tDownloads.firstOrNull() ?: continue
|
||||||
val offlineAnimeModel = loadOfflineAnimeModel(download)
|
val offlineAnimeModel = loadOfflineAnimeModel(download)
|
||||||
if (offlineAnimeModel.title == "unknown") offlineAnimeModel.title = title
|
if (offlineAnimeModel.title == "unknown") offlineAnimeModel.title = title
|
||||||
|
|
|
@ -177,6 +177,7 @@ object Helper {
|
||||||
downloadManager
|
downloadManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("exoplayer download manager is no longer used")
|
@Deprecated("exoplayer download manager is no longer used")
|
||||||
@OptIn(UnstableApi::class)
|
@OptIn(UnstableApi::class)
|
||||||
fun getSimpleCache(context: Context): SimpleCache {
|
fun getSimpleCache(context: Context): SimpleCache {
|
||||||
|
@ -189,6 +190,7 @@ object Helper {
|
||||||
simpleCache!!
|
simpleCache!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@Deprecated("exoplayer download manager is no longer used")
|
@Deprecated("exoplayer download manager is no longer used")
|
||||||
private fun getDownloadDirectory(context: Context): File {
|
private fun getDownloadDirectory(context: Context): File {
|
||||||
|
@ -200,12 +202,16 @@ object Helper {
|
||||||
}
|
}
|
||||||
return downloadDirectory!!
|
return downloadDirectory!!
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("exoplayer download manager is no longer used")
|
@Deprecated("exoplayer download manager is no longer used")
|
||||||
private var download: DownloadManager? = null
|
private var download: DownloadManager? = null
|
||||||
|
|
||||||
@Deprecated("exoplayer download manager is no longer used")
|
@Deprecated("exoplayer download manager is no longer used")
|
||||||
private const val DOWNLOAD_CONTENT_DIRECTORY = "Anime_Downloads"
|
private const val DOWNLOAD_CONTENT_DIRECTORY = "Anime_Downloads"
|
||||||
|
|
||||||
@Deprecated("exoplayer download manager is no longer used")
|
@Deprecated("exoplayer download manager is no longer used")
|
||||||
private var simpleCache: SimpleCache? = null
|
private var simpleCache: SimpleCache? = null
|
||||||
|
|
||||||
@Deprecated("exoplayer download manager is no longer used")
|
@Deprecated("exoplayer download manager is no longer used")
|
||||||
private var downloadDirectory: File? = null
|
private var downloadDirectory: File? = null
|
||||||
}
|
}
|
|
@ -22,9 +22,9 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.Refresh
|
import ani.dantotsu.Refresh
|
||||||
import ani.dantotsu.bottomBar
|
import ani.dantotsu.bottomBar
|
||||||
|
import ani.dantotsu.connections.anilist.AniMangaSearchResults
|
||||||
import ani.dantotsu.connections.anilist.Anilist
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.connections.anilist.AnilistAnimeViewModel
|
import ani.dantotsu.connections.anilist.AnilistAnimeViewModel
|
||||||
import ani.dantotsu.connections.anilist.AniMangaSearchResults
|
|
||||||
import ani.dantotsu.connections.anilist.getUserId
|
import ani.dantotsu.connections.anilist.getUserId
|
||||||
import ani.dantotsu.databinding.FragmentAnimeBinding
|
import ani.dantotsu.databinding.FragmentAnimeBinding
|
||||||
import ani.dantotsu.media.MediaAdaptor
|
import ani.dantotsu.media.MediaAdaptor
|
||||||
|
@ -277,8 +277,9 @@ class AnimeFragment : Fragment() {
|
||||||
running = true
|
running = true
|
||||||
scope.launch {
|
scope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
Anilist.userid = PrefManager.getNullableVal<String>(PrefName.AnilistUserId, null)
|
Anilist.userid =
|
||||||
?.toIntOrNull()
|
PrefManager.getNullableVal<String>(PrefName.AnilistUserId, null)
|
||||||
|
?.toIntOrNull()
|
||||||
if (Anilist.userid == null) {
|
if (Anilist.userid == null) {
|
||||||
getUserId(requireContext()) {
|
getUserId(requireContext()) {
|
||||||
load()
|
load()
|
||||||
|
|
|
@ -20,7 +20,6 @@ import androidx.viewpager2.widget.ViewPager2
|
||||||
import ani.dantotsu.MediaPageTransformer
|
import ani.dantotsu.MediaPageTransformer
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.connections.anilist.Anilist
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.connections.anilist.AnilistSearch.SearchType.Companion.toAnilistString
|
|
||||||
import ani.dantotsu.databinding.ItemAnimePageBinding
|
import ani.dantotsu.databinding.ItemAnimePageBinding
|
||||||
import ani.dantotsu.databinding.LayoutTrendingBinding
|
import ani.dantotsu.databinding.LayoutTrendingBinding
|
||||||
import ani.dantotsu.getAppString
|
import ani.dantotsu.getAppString
|
||||||
|
@ -266,7 +265,15 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun init(adaptor: MediaAdaptor, recyclerView: RecyclerView, progress: View, title: View , more: View , string: String, media : MutableList<Media>) {
|
fun init(
|
||||||
|
adaptor: MediaAdaptor,
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
progress: View,
|
||||||
|
title: View,
|
||||||
|
more: View,
|
||||||
|
string: String,
|
||||||
|
media: MutableList<Media>
|
||||||
|
) {
|
||||||
progress.visibility = View.GONE
|
progress.visibility = View.GONE
|
||||||
recyclerView.adapter = adaptor
|
recyclerView.adapter = adaptor
|
||||||
recyclerView.layoutManager =
|
recyclerView.layoutManager =
|
||||||
|
|
|
@ -469,7 +469,9 @@ class HomeFragment : Fragment() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
// Get user data first
|
// Get user data first
|
||||||
Anilist.userid = PrefManager.getNullableVal<String>(PrefName.AnilistUserId, null)?.toIntOrNull()
|
Anilist.userid =
|
||||||
|
PrefManager.getNullableVal<String>(PrefName.AnilistUserId, null)
|
||||||
|
?.toIntOrNull()
|
||||||
if (Anilist.userid == null) {
|
if (Anilist.userid == null) {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
getUserId(requireContext()) {
|
getUserId(requireContext()) {
|
||||||
|
|
|
@ -102,7 +102,7 @@ class LoginFragment : Fragment() {
|
||||||
requireActivity().customAlertDialog().apply {
|
requireActivity().customAlertDialog().apply {
|
||||||
setTitle("Enter Password")
|
setTitle("Enter Password")
|
||||||
setCustomView(dialogView.root)
|
setCustomView(dialogView.root)
|
||||||
setPosButton(R.string.ok){
|
setPosButton(R.string.ok) {
|
||||||
val editText = dialogView.userAgentTextBox
|
val editText = dialogView.userAgentTextBox
|
||||||
if (editText.text?.isNotBlank() == true) {
|
if (editText.text?.isNotBlank() == true) {
|
||||||
editText.text?.toString()?.trim()?.toCharArray(password)
|
editText.text?.toString()?.trim()?.toCharArray(password)
|
||||||
|
|
|
@ -20,9 +20,9 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.Refresh
|
import ani.dantotsu.Refresh
|
||||||
import ani.dantotsu.bottomBar
|
import ani.dantotsu.bottomBar
|
||||||
|
import ani.dantotsu.connections.anilist.AniMangaSearchResults
|
||||||
import ani.dantotsu.connections.anilist.Anilist
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.connections.anilist.AnilistMangaViewModel
|
import ani.dantotsu.connections.anilist.AnilistMangaViewModel
|
||||||
import ani.dantotsu.connections.anilist.AniMangaSearchResults
|
|
||||||
import ani.dantotsu.connections.anilist.getUserId
|
import ani.dantotsu.connections.anilist.getUserId
|
||||||
import ani.dantotsu.databinding.FragmentMangaBinding
|
import ani.dantotsu.databinding.FragmentMangaBinding
|
||||||
import ani.dantotsu.media.MediaAdaptor
|
import ani.dantotsu.media.MediaAdaptor
|
||||||
|
@ -169,7 +169,10 @@ class MangaFragment : Fragment() {
|
||||||
}
|
}
|
||||||
model.getPopularManga().observe(viewLifecycleOwner) {
|
model.getPopularManga().observe(viewLifecycleOwner) {
|
||||||
if (it != null) {
|
if (it != null) {
|
||||||
mangaPageAdapter.updateTrendingManga(MediaAdaptor(0, it, requireActivity()), it)
|
mangaPageAdapter.updateTrendingManga(
|
||||||
|
MediaAdaptor(0, it, requireActivity()),
|
||||||
|
it
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
model.getPopularManhwa().observe(viewLifecycleOwner) {
|
model.getPopularManhwa().observe(viewLifecycleOwner) {
|
||||||
|
@ -262,8 +265,9 @@ class MangaFragment : Fragment() {
|
||||||
running = true
|
running = true
|
||||||
scope.launch {
|
scope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
Anilist.userid = PrefManager.getNullableVal<String>(PrefName.AnilistUserId, null)
|
Anilist.userid =
|
||||||
?.toIntOrNull()
|
PrefManager.getNullableVal<String>(PrefName.AnilistUserId, null)
|
||||||
|
?.toIntOrNull()
|
||||||
if (Anilist.userid == null) {
|
if (Anilist.userid == null) {
|
||||||
getUserId(requireContext()) {
|
getUserId(requireContext()) {
|
||||||
load()
|
load()
|
||||||
|
|
|
@ -266,10 +266,10 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
|
||||||
adaptor: MediaAdaptor,
|
adaptor: MediaAdaptor,
|
||||||
recyclerView: RecyclerView,
|
recyclerView: RecyclerView,
|
||||||
progress: View,
|
progress: View,
|
||||||
title: View ,
|
title: View,
|
||||||
more: View ,
|
more: View,
|
||||||
string: String,
|
string: String,
|
||||||
media : MutableList<Media>
|
media: MutableList<Media>
|
||||||
) {
|
) {
|
||||||
progress.visibility = View.GONE
|
progress.visibility = View.GONE
|
||||||
recyclerView.adapter = adaptor
|
recyclerView.adapter = adaptor
|
||||||
|
|
|
@ -38,7 +38,7 @@ class CircleView(context: Context, attrs: AttributeSet?) : View(context, attrs)
|
||||||
|
|
||||||
fun setColor(int: Int) {
|
fun setColor(int: Int) {
|
||||||
paint.color = if (int < booleanList.size && booleanList[int]) {
|
paint.color = if (int < booleanList.size && booleanList[int]) {
|
||||||
Color.GRAY
|
Color.GRAY
|
||||||
} else {
|
} else {
|
||||||
if (isUser) secondColor else primaryColor
|
if (isUser) secondColor else primaryColor
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ class CircleView(context: Context, attrs: AttributeSet?) : View(context, attrs)
|
||||||
} else {
|
} else {
|
||||||
val effectiveAngle = totalAngle / parts
|
val effectiveAngle = totalAngle / parts
|
||||||
for (i in 0 until parts) {
|
for (i in 0 until parts) {
|
||||||
val startAngle = i * (effectiveAngle + gapAngle) -90f
|
val startAngle = i * (effectiveAngle + gapAngle) - 90f
|
||||||
path.reset()
|
path.reset()
|
||||||
path.addArc(
|
path.addArc(
|
||||||
centerX - radius,
|
centerX - radius,
|
||||||
|
@ -74,7 +74,7 @@ class CircleView(context: Context, attrs: AttributeSet?) : View(context, attrs)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setParts(parts: Int, list : List<Boolean> = mutableListOf(), isUser: Boolean) {
|
fun setParts(parts: Int, list: List<Boolean> = mutableListOf(), isUser: Boolean) {
|
||||||
this.parts = parts
|
this.parts = parts
|
||||||
this.booleanList = list
|
this.booleanList = list
|
||||||
this.isUser = isUser
|
this.isUser = isUser
|
||||||
|
|
|
@ -46,8 +46,8 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
|
||||||
val key = "activities"
|
val key = "activities"
|
||||||
val watchedActivity = PrefManager.getCustomVal<Set<Int>>(key, setOf())
|
val watchedActivity = PrefManager.getCustomVal<Set<Int>>(key, setOf())
|
||||||
if (activity.getOrNull(position) != null) {
|
if (activity.getOrNull(position) != null) {
|
||||||
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity )
|
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity)
|
||||||
val startIndex = if ( startFrom > 0) startFrom else 0
|
val startIndex = if (startFrom > 0) startFrom else 0
|
||||||
binding.stories.setStoriesList(
|
binding.stories.setStoriesList(
|
||||||
activityList = activity[position].activity,
|
activityList = activity[position].activity,
|
||||||
startIndex = startIndex + 1
|
startIndex = startIndex + 1
|
||||||
|
@ -58,6 +58,7 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findFirstNonMatch(watchedActivity: Set<Int>, activity: List<Activity>): Int {
|
private fun findFirstNonMatch(watchedActivity: Set<Int>, activity: List<Activity>): Int {
|
||||||
for (activityItem in activity) {
|
for (activityItem in activity) {
|
||||||
if (activityItem.id !in watchedActivity) {
|
if (activityItem.id !in watchedActivity) {
|
||||||
|
@ -86,13 +87,14 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
|
||||||
binding.stories.pause()
|
binding.stories.pause()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStoriesEnd() {
|
override fun onStoriesEnd() {
|
||||||
position += 1
|
position += 1
|
||||||
if (position < activity.size) {
|
if (position < activity.size) {
|
||||||
val key = "activities"
|
val key = "activities"
|
||||||
val watchedActivity = PrefManager.getCustomVal<Set<Int>>(key, setOf())
|
val watchedActivity = PrefManager.getCustomVal<Set<Int>>(key, setOf())
|
||||||
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity )
|
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity)
|
||||||
val startIndex= if ( startFrom > 0) startFrom else 0
|
val startIndex = if (startFrom > 0) startFrom else 0
|
||||||
binding.stories.startAnimation(slideOutLeft)
|
binding.stories.startAnimation(slideOutLeft)
|
||||||
binding.stories.setStoriesList(activity[position].activity, startIndex + 1)
|
binding.stories.setStoriesList(activity[position].activity, startIndex + 1)
|
||||||
binding.stories.startAnimation(slideInRight)
|
binding.stories.startAnimation(slideInRight)
|
||||||
|
@ -106,15 +108,16 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
|
||||||
if (position >= 0 && activity[position].activity.isNotEmpty()) {
|
if (position >= 0 && activity[position].activity.isNotEmpty()) {
|
||||||
val key = "activities"
|
val key = "activities"
|
||||||
val watchedActivity = PrefManager.getCustomVal<Set<Int>>(key, setOf())
|
val watchedActivity = PrefManager.getCustomVal<Set<Int>>(key, setOf())
|
||||||
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity )
|
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity)
|
||||||
val startIndex = if ( startFrom > 0) startFrom else 0
|
val startIndex = if (startFrom > 0) startFrom else 0
|
||||||
binding.stories.startAnimation(slideOutRight)
|
binding.stories.startAnimation(slideOutRight)
|
||||||
binding.stories.setStoriesList(activity[position].activity,startIndex + 1)
|
binding.stories.setStoriesList(activity[position].activity, startIndex + 1)
|
||||||
binding.stories.startAnimation(slideInLeft)
|
binding.stories.startAnimation(slideInLeft)
|
||||||
} else {
|
} else {
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
var user: ArrayList<User> = arrayListOf()
|
var user: ArrayList<User> = arrayListOf()
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,8 +262,6 @@ class Stories @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun rightPanelTouch() {
|
private fun rightPanelTouch() {
|
||||||
Logger.log("rightPanelTouch: $storyIndex")
|
Logger.log("rightPanelTouch: $storyIndex")
|
||||||
if (storyIndex == activityList.size) {
|
if (storyIndex == activityList.size) {
|
||||||
|
@ -366,8 +364,8 @@ class Stories @JvmOverloads constructor(
|
||||||
if (
|
if (
|
||||||
story.status?.contains("completed") == false &&
|
story.status?.contains("completed") == false &&
|
||||||
!story.status.contains("plans") &&
|
!story.status.contains("plans") &&
|
||||||
!story.status.contains("repeating")&&
|
!story.status.contains("repeating") &&
|
||||||
!story.status.contains("paused")&&
|
!story.status.contains("paused") &&
|
||||||
!story.status.contains("dropped")
|
!story.status.contains("dropped")
|
||||||
) {
|
) {
|
||||||
"of ${story.media?.title?.userPreferred}"
|
"of ${story.media?.title?.userPreferred}"
|
||||||
|
@ -469,6 +467,7 @@ class Stories @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var startClickTime = 0L
|
private var startClickTime = 0L
|
||||||
private var startX = 0f
|
private var startX = 0f
|
||||||
private var startY = 0f
|
private var startY = 0f
|
||||||
|
@ -478,7 +477,8 @@ class Stories @JvmOverloads constructor(
|
||||||
onTouchView(view, event)
|
onTouchView(view, event)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
private fun onTouchView(view: View, event: MotionEvent, isText: Boolean = false){
|
|
||||||
|
private fun onTouchView(view: View, event: MotionEvent, isText: Boolean = false) {
|
||||||
val maxClickDuration = 200
|
val maxClickDuration = 200
|
||||||
val screenWidth = view.width
|
val screenWidth = view.width
|
||||||
val leftHalf = screenWidth / 2
|
val leftHalf = screenWidth / 2
|
||||||
|
@ -492,6 +492,7 @@ class Stories @JvmOverloads constructor(
|
||||||
pause()
|
pause()
|
||||||
isLongPress = false
|
isLongPress = false
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionEvent.ACTION_MOVE -> {
|
MotionEvent.ACTION_MOVE -> {
|
||||||
val deltaX = event.x - startX
|
val deltaX = event.x - startX
|
||||||
val deltaY = event.y - startY
|
val deltaY = event.y - startY
|
||||||
|
@ -499,6 +500,7 @@ class Stories @JvmOverloads constructor(
|
||||||
isLongPress = true
|
isLongPress = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionEvent.ACTION_UP -> {
|
MotionEvent.ACTION_UP -> {
|
||||||
val clickDuration = Calendar.getInstance().timeInMillis - startClickTime
|
val clickDuration = Calendar.getInstance().timeInMillis - startClickTime
|
||||||
if (isText) {
|
if (isText) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ class UserStatusAdapter(private val user: ArrayList<User>) :
|
||||||
.putExtra("type", "activity"),
|
.putExtra("type", "activity"),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
}else{
|
} else {
|
||||||
ContextCompat.startActivity(
|
ContextCompat.startActivity(
|
||||||
itemView.context,
|
itemView.context,
|
||||||
Intent(
|
Intent(
|
||||||
|
@ -76,10 +76,15 @@ class UserStatusAdapter(private val user: ArrayList<User>) :
|
||||||
setAnimation(b.root.context, b.root)
|
setAnimation(b.root.context, b.root)
|
||||||
val user = user[position]
|
val user = user[position]
|
||||||
b.profileUserAvatar.loadImage(user.pfp)
|
b.profileUserAvatar.loadImage(user.pfp)
|
||||||
b.profileUserName.text = if (Anilist.userid == user.id) getAppString(R.string.your_story) else user.name
|
b.profileUserName.text =
|
||||||
|
if (Anilist.userid == user.id) getAppString(R.string.your_story) else user.name
|
||||||
val watchedActivity = PrefManager.getCustomVal<Set<Int>>("activities", setOf())
|
val watchedActivity = PrefManager.getCustomVal<Set<Int>>("activities", setOf())
|
||||||
val booleanList = user.activity.map { watchedActivity.contains(it.id) }
|
val booleanList = user.activity.map { watchedActivity.contains(it.id) }
|
||||||
b.profileUserStatusIndicator.setParts(user.activity.size, booleanList, user.id == Anilist.userid)
|
b.profileUserStatusIndicator.setParts(
|
||||||
|
user.activity.size,
|
||||||
|
booleanList,
|
||||||
|
user.id == Anilist.userid
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,11 @@ class CharacterAdapter(
|
||||||
).toBundle()
|
).toBundle()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
itemView.setOnLongClickListener { copyToClipboard(characterList[bindingAdapterPosition].name ?: ""); true }
|
itemView.setOnLongClickListener {
|
||||||
|
copyToClipboard(
|
||||||
|
characterList[bindingAdapterPosition].name ?: ""
|
||||||
|
); true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,11 +7,9 @@ import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
|
import ani.dantotsu.buildMarkwon
|
||||||
import ani.dantotsu.currActivity
|
import ani.dantotsu.currActivity
|
||||||
import ani.dantotsu.databinding.ItemCharacterDetailsBinding
|
import ani.dantotsu.databinding.ItemCharacterDetailsBinding
|
||||||
import ani.dantotsu.others.SpoilerPlugin
|
|
||||||
import io.noties.markwon.Markwon
|
|
||||||
import io.noties.markwon.SoftBreakAddsNewLinePlugin
|
|
||||||
|
|
||||||
class CharacterDetailsAdapter(private val character: Character, private val activity: Activity) :
|
class CharacterDetailsAdapter(private val character: Character, private val activity: Activity) :
|
||||||
RecyclerView.Adapter<CharacterDetailsAdapter.GenreViewHolder>() {
|
RecyclerView.Adapter<CharacterDetailsAdapter.GenreViewHolder>() {
|
||||||
|
@ -24,7 +22,9 @@ class CharacterDetailsAdapter(private val character: Character, private val acti
|
||||||
override fun onBindViewHolder(holder: GenreViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: GenreViewHolder, position: Int) {
|
||||||
val binding = holder.binding
|
val binding = holder.binding
|
||||||
val desc =
|
val desc =
|
||||||
(if (character.age != "null") "${currActivity()!!.getString(R.string.age)} ${character.age}" else "") +
|
(if (character.id == 4004)
|
||||||
|
" \n" else "") +
|
||||||
|
(if (character.age != "null") "${currActivity()!!.getString(R.string.age)} ${character.age}" else "") +
|
||||||
(if (character.dateOfBirth.toString() != "")
|
(if (character.dateOfBirth.toString() != "")
|
||||||
"${currActivity()!!.getString(R.string.birthday)} ${character.dateOfBirth.toString()}" else "") +
|
"${currActivity()!!.getString(R.string.birthday)} ${character.dateOfBirth.toString()}" else "") +
|
||||||
(if (character.gender != "null")
|
(if (character.gender != "null")
|
||||||
|
@ -41,8 +41,7 @@ class CharacterDetailsAdapter(private val character: Character, private val acti
|
||||||
} else "") + "\n" + character.description
|
} else "") + "\n" + character.description
|
||||||
|
|
||||||
binding.characterDesc.isTextSelectable
|
binding.characterDesc.isTextSelectable
|
||||||
val markWon = Markwon.builder(activity).usePlugin(SoftBreakAddsNewLinePlugin.create())
|
val markWon = buildMarkwon(activity)
|
||||||
.usePlugin(SpoilerPlugin()).build()
|
|
||||||
markWon.setMarkdown(binding.characterDesc, desc.replace("~!", "||").replace("!~", "||"))
|
markWon.setMarkdown(binding.characterDesc, desc.replace("~!", "||").replace("!~", "||"))
|
||||||
binding.voiceActorRecycler.adapter = AuthorAdapter(character.voiceActor ?: arrayListOf())
|
binding.voiceActorRecycler.adapter = AuthorAdapter(character.voiceActor ?: arrayListOf())
|
||||||
binding.voiceActorRecycler.layoutManager = LinearLayoutManager(
|
binding.voiceActorRecycler.layoutManager = LinearLayoutManager(
|
||||||
|
|
|
@ -9,7 +9,7 @@ import android.view.animation.Animation
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import ani.dantotsu.databinding.ItemSearchHeaderBinding
|
import ani.dantotsu.databinding.ItemSearchHeaderBinding
|
||||||
|
|
||||||
abstract class HeaderInterface: RecyclerView.Adapter<HeaderInterface.SearchHeaderViewHolder>() {
|
abstract class HeaderInterface : RecyclerView.Adapter<HeaderInterface.SearchHeaderViewHolder>() {
|
||||||
private val itemViewType = 6969
|
private val itemViewType = 6969
|
||||||
var search: Runnable? = null
|
var search: Runnable? = null
|
||||||
var requestFocus: Runnable? = null
|
var requestFocus: Runnable? = null
|
||||||
|
|
|
@ -147,7 +147,7 @@ fun Media?.deleteFromList(
|
||||||
scope.launch {
|
scope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
this@deleteFromList?.let { media ->
|
this@deleteFromList?.let { media ->
|
||||||
val _id = id ?: Anilist.query.userMediaDetails(media).userListId;
|
val _id = id ?: Anilist.query.userMediaDetails(media).userListId
|
||||||
_id?.let { listId ->
|
_id?.let { listId ->
|
||||||
try {
|
try {
|
||||||
Anilist.mutation.deleteList(listId)
|
Anilist.mutation.deleteList(listId)
|
||||||
|
|
|
@ -251,10 +251,12 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
|
||||||
fun total() {
|
fun total() {
|
||||||
val text = SpannableStringBuilder().apply {
|
val text = SpannableStringBuilder().apply {
|
||||||
|
|
||||||
val white = this@MediaDetailsActivity.getThemeColor(com.google.android.material.R.attr.colorOnBackground)
|
val white =
|
||||||
|
this@MediaDetailsActivity.getThemeColor(com.google.android.material.R.attr.colorOnBackground)
|
||||||
if (media.userStatus != null) {
|
if (media.userStatus != null) {
|
||||||
append(if (media.anime != null) getString(R.string.watched_num) else getString(R.string.read_num))
|
append(if (media.anime != null) getString(R.string.watched_num) else getString(R.string.read_num))
|
||||||
val colorSecondary = getThemeColor(com.google.android.material.R.attr.colorSecondary)
|
val colorSecondary =
|
||||||
|
getThemeColor(com.google.android.material.R.attr.colorSecondary)
|
||||||
bold { color(colorSecondary) { append("${media.userProgress}") } }
|
bold { color(colorSecondary) { append("${media.userProgress}") } }
|
||||||
append(
|
append(
|
||||||
if (media.anime != null) getString(R.string.episodes_out_of) else getString(
|
if (media.anime != null) getString(R.string.episodes_out_of) else getString(
|
||||||
|
|
|
@ -100,6 +100,7 @@ class MediaDetailsViewModel : ViewModel() {
|
||||||
if (kitsuEpisodes.value == null) kitsuEpisodes.postValue(Kitsu.getKitsuEpisodesDetails(s))
|
if (kitsuEpisodes.value == null) kitsuEpisodes.postValue(Kitsu.getKitsuEpisodesDetails(s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val anifyEpisodes: MutableLiveData<Map<String, Episode>> =
|
private val anifyEpisodes: MutableLiveData<Map<String, Episode>> =
|
||||||
MutableLiveData<Map<String, Episode>>(null)
|
MutableLiveData<Map<String, Episode>>(null)
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,8 @@ import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.statusBarHeight
|
import ani.dantotsu.statusBarHeight
|
||||||
import ani.dantotsu.themes.ThemeManager
|
import ani.dantotsu.themes.ThemeManager
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
class MediaListViewActivity: AppCompatActivity() {
|
class MediaListViewActivity : AppCompatActivity() {
|
||||||
private lateinit var binding: ActivityMediaListViewBinding
|
private lateinit var binding: ActivityMediaListViewBinding
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -52,7 +51,8 @@ class MediaListViewActivity: AppCompatActivity() {
|
||||||
binding.listAppBar.setBackgroundColor(primaryColor)
|
binding.listAppBar.setBackgroundColor(primaryColor)
|
||||||
binding.listTitle.setTextColor(primaryTextColor)
|
binding.listTitle.setTextColor(primaryTextColor)
|
||||||
val screenWidth = resources.displayMetrics.run { widthPixels / density }
|
val screenWidth = resources.displayMetrics.run { widthPixels / density }
|
||||||
val mediaList = passedMedia ?: intent.getSerialized("media") as? ArrayList<Media> ?: ArrayList()
|
val mediaList =
|
||||||
|
passedMedia ?: intent.getSerialized("media") as? ArrayList<Media> ?: ArrayList()
|
||||||
if (passedMedia != null) passedMedia = null
|
if (passedMedia != null) passedMedia = null
|
||||||
val view = PrefManager.getCustomVal("mediaView", 0)
|
val view = PrefManager.getCustomVal("mediaView", 0)
|
||||||
var mediaView: View = when (view) {
|
var mediaView: View = when (view) {
|
||||||
|
|
|
@ -44,7 +44,10 @@ class MediaSocialAdapter(
|
||||||
profileUserName.text = user.name
|
profileUserName.text = user.name
|
||||||
profileInfo.apply {
|
profileInfo.apply {
|
||||||
text = when (user.status) {
|
text = when (user.status) {
|
||||||
"CURRENT" -> if (type == "ANIME") getAppString(R.string.watching) else getAppString(R.string.reading)
|
"CURRENT" -> if (type == "ANIME") getAppString(R.string.watching) else getAppString(
|
||||||
|
R.string.reading
|
||||||
|
)
|
||||||
|
|
||||||
else -> user.status ?: ""
|
else -> user.status ?: ""
|
||||||
}
|
}
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
|
@ -63,10 +66,12 @@ class MediaSocialAdapter(
|
||||||
profileCompactProgressContainer.visibility = View.VISIBLE
|
profileCompactProgressContainer.visibility = View.VISIBLE
|
||||||
|
|
||||||
profileUserAvatar.setOnClickListener {
|
profileUserAvatar.setOnClickListener {
|
||||||
ContextCompat.startActivity(root.context,
|
ContextCompat.startActivity(
|
||||||
|
root.context,
|
||||||
Intent(root.context, ProfileActivity::class.java)
|
Intent(root.context, ProfileActivity::class.java)
|
||||||
.putExtra("userId", user.id),
|
.putExtra("userId", user.id),
|
||||||
null)
|
null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
profileUserAvatarContainer.setOnLongClickListener {
|
profileUserAvatarContainer.setOnLongClickListener {
|
||||||
ImageViewDialog.newInstance(
|
ImageViewDialog.newInstance(
|
||||||
|
|
|
@ -1,23 +1,15 @@
|
||||||
package ani.dantotsu.media
|
package ani.dantotsu.media
|
||||||
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.core.app.ActivityOptionsCompat
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.util.Pair
|
|
||||||
import androidx.core.view.ViewCompat
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import androidx.fragment.app.FragmentActivity
|
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.connections.anilist.Anilist
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.connections.anilist.api.Query
|
import ani.dantotsu.connections.anilist.api.Query
|
||||||
import ani.dantotsu.databinding.ItemReviewsBinding
|
import ani.dantotsu.databinding.ItemReviewsBinding
|
||||||
import ani.dantotsu.loadImage
|
import ani.dantotsu.loadImage
|
||||||
import ani.dantotsu.openImage
|
import ani.dantotsu.openImage
|
||||||
import ani.dantotsu.others.ImageViewDialog
|
|
||||||
import ani.dantotsu.profile.ProfileActivity
|
import ani.dantotsu.profile.ProfileActivity
|
||||||
import ani.dantotsu.profile.activity.ActivityItemBuilder
|
import ani.dantotsu.profile.activity.ActivityItemBuilder
|
||||||
import ani.dantotsu.toast
|
import ani.dantotsu.toast
|
||||||
|
@ -40,7 +32,7 @@ class ReviewAdapter(
|
||||||
binding.reviewUserAvatar.loadImage(review.user?.avatar?.medium)
|
binding.reviewUserAvatar.loadImage(review.user?.avatar?.medium)
|
||||||
binding.reviewText.text = review.summary
|
binding.reviewText.text = review.summary
|
||||||
binding.reviewPostTime.text = ActivityItemBuilder.getDateTime(review.createdAt)
|
binding.reviewPostTime.text = ActivityItemBuilder.getDateTime(review.createdAt)
|
||||||
val text = "[${review.score/ 10.0f}]"
|
val text = "[${review.score / 10.0f}]"
|
||||||
binding.reviewTag.text = text
|
binding.reviewTag.text = text
|
||||||
binding.root.setOnClickListener {
|
binding.root.setOnClickListener {
|
||||||
ContextCompat.startActivity(
|
ContextCompat.startActivity(
|
||||||
|
@ -85,6 +77,7 @@ class ReviewAdapter(
|
||||||
override fun initializeViewBinding(view: View): ItemReviewsBinding {
|
override fun initializeViewBinding(view: View): ItemReviewsBinding {
|
||||||
return ItemReviewsBinding.bind(view)
|
return ItemReviewsBinding.bind(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun userVote(type: String) {
|
private fun userVote(type: String) {
|
||||||
when (type) {
|
when (type) {
|
||||||
"NO_VOTE" -> {
|
"NO_VOTE" -> {
|
||||||
|
|
|
@ -20,7 +20,6 @@ import ani.dantotsu.initActivity
|
||||||
import ani.dantotsu.loadImage
|
import ani.dantotsu.loadImage
|
||||||
import ani.dantotsu.navBarHeight
|
import ani.dantotsu.navBarHeight
|
||||||
import ani.dantotsu.openImage
|
import ani.dantotsu.openImage
|
||||||
import ani.dantotsu.others.ImageViewDialog
|
|
||||||
import ani.dantotsu.profile.ProfileActivity
|
import ani.dantotsu.profile.ProfileActivity
|
||||||
import ani.dantotsu.profile.activity.ActivityItemBuilder
|
import ani.dantotsu.profile.activity.ActivityItemBuilder
|
||||||
import ani.dantotsu.statusBarHeight
|
import ani.dantotsu.statusBarHeight
|
||||||
|
@ -52,8 +51,9 @@ class ReviewViewActivity : AppCompatActivity() {
|
||||||
binding.userAvatar.loadImage(review.user?.avatar?.medium)
|
binding.userAvatar.loadImage(review.user?.avatar?.medium)
|
||||||
binding.userTime.text = ActivityItemBuilder.getDateTime(review.createdAt)
|
binding.userTime.text = ActivityItemBuilder.getDateTime(review.createdAt)
|
||||||
binding.userContainer.setOnClickListener {
|
binding.userContainer.setOnClickListener {
|
||||||
startActivity(Intent(this, ProfileActivity::class.java)
|
startActivity(
|
||||||
.putExtra("userId", review.user?.id)
|
Intent(this, ProfileActivity::class.java)
|
||||||
|
.putExtra("userId", review.user?.id)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
binding.userAvatar.openImage(
|
binding.userAvatar.openImage(
|
||||||
|
@ -61,8 +61,9 @@ class ReviewViewActivity : AppCompatActivity() {
|
||||||
review.user?.avatar?.medium ?: ""
|
review.user?.avatar?.medium ?: ""
|
||||||
)
|
)
|
||||||
binding.userAvatar.setOnClickListener {
|
binding.userAvatar.setOnClickListener {
|
||||||
startActivity(Intent(this, ProfileActivity::class.java)
|
startActivity(
|
||||||
.putExtra("userId", review.user?.id)
|
Intent(this, ProfileActivity::class.java)
|
||||||
|
.putExtra("userId", review.user?.id)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
binding.profileUserBio.settings.loadWithOverviewMode = true
|
binding.profileUserBio.settings.loadWithOverviewMode = true
|
||||||
|
|
|
@ -13,10 +13,10 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.ConcatAdapter
|
import androidx.recyclerview.widget.ConcatAdapter
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import ani.dantotsu.connections.anilist.AniMangaSearchResults
|
||||||
import ani.dantotsu.connections.anilist.Anilist
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.connections.anilist.AnilistSearch
|
import ani.dantotsu.connections.anilist.AnilistSearch
|
||||||
import ani.dantotsu.connections.anilist.AnilistSearch.SearchType
|
import ani.dantotsu.connections.anilist.AnilistSearch.SearchType
|
||||||
import ani.dantotsu.connections.anilist.AniMangaSearchResults
|
|
||||||
import ani.dantotsu.connections.anilist.CharacterSearchResults
|
import ani.dantotsu.connections.anilist.CharacterSearchResults
|
||||||
import ani.dantotsu.connections.anilist.StaffSearchResults
|
import ani.dantotsu.connections.anilist.StaffSearchResults
|
||||||
import ani.dantotsu.connections.anilist.StudioSearchResults
|
import ani.dantotsu.connections.anilist.StudioSearchResults
|
||||||
|
@ -377,7 +377,10 @@ class SearchActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchType.CHARACTER -> {
|
SearchType.CHARACTER -> {
|
||||||
characterAdaptor.notifyItemRangeRemoved(0, model.characterSearchResults.results.size)
|
characterAdaptor.notifyItemRangeRemoved(
|
||||||
|
0,
|
||||||
|
model.characterSearchResults.results.size
|
||||||
|
)
|
||||||
model.characterSearchResults.results.clear()
|
model.characterSearchResults.results.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Sear
|
||||||
|
|
||||||
searchHistoryAdapter = SearchHistoryAdapter(type) {
|
searchHistoryAdapter = SearchHistoryAdapter(type) {
|
||||||
binding.searchBarText.setText(it)
|
binding.searchBarText.setText(it)
|
||||||
|
binding.searchBarText.setSelection(it.length)
|
||||||
}
|
}
|
||||||
binding.searchHistoryList.layoutManager = LinearLayoutManager(binding.root.context)
|
binding.searchHistoryList.layoutManager = LinearLayoutManager(binding.root.context)
|
||||||
binding.searchHistoryList.adapter = searchHistoryAdapter
|
binding.searchHistoryList.adapter = searchHistoryAdapter
|
||||||
|
|
|
@ -346,7 +346,9 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() {
|
||||||
binding.searchGenresGrid.isChecked = false
|
binding.searchGenresGrid.isChecked = false
|
||||||
|
|
||||||
binding.searchFilterTags.adapter =
|
binding.searchFilterTags.adapter =
|
||||||
FilterChipAdapter(Anilist.tags?.get(activity.aniMangaResult.isAdult) ?: listOf()) { chip ->
|
FilterChipAdapter(
|
||||||
|
Anilist.tags?.get(activity.aniMangaResult.isAdult) ?: listOf()
|
||||||
|
) { chip ->
|
||||||
val tag = chip.text.toString()
|
val tag = chip.text.toString()
|
||||||
chip.isChecked = selectedTags.contains(tag)
|
chip.isChecked = selectedTags.contains(tag)
|
||||||
chip.isCloseIconVisible = exTags.contains(tag)
|
chip.isCloseIconVisible = exTags.contains(tag)
|
||||||
|
|
|
@ -55,7 +55,11 @@ class StudioAdapter(
|
||||||
).toBundle()
|
).toBundle()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
itemView.setOnLongClickListener { copyToClipboard(studioList[bindingAdapterPosition].name ?: ""); true }
|
itemView.setOnLongClickListener {
|
||||||
|
copyToClipboard(
|
||||||
|
studioList[bindingAdapterPosition].name
|
||||||
|
); true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -31,6 +31,7 @@ class SupportingSearchAdapter(private val activity: SearchActivity, private val
|
||||||
|
|
||||||
searchHistoryAdapter = SearchHistoryAdapter(type) {
|
searchHistoryAdapter = SearchHistoryAdapter(type) {
|
||||||
binding.searchBarText.setText(it)
|
binding.searchBarText.setText(it)
|
||||||
|
binding.searchBarText.setSelection(it.length)
|
||||||
}
|
}
|
||||||
binding.searchHistoryList.layoutManager = LinearLayoutManager(binding.root.context)
|
binding.searchHistoryList.layoutManager = LinearLayoutManager(binding.root.context)
|
||||||
binding.searchHistoryList.adapter = searchHistoryAdapter
|
binding.searchHistoryList.adapter = searchHistoryAdapter
|
||||||
|
|
|
@ -20,8 +20,8 @@ import ani.dantotsu.R
|
||||||
import ani.dantotsu.currActivity
|
import ani.dantotsu.currActivity
|
||||||
import ani.dantotsu.currContext
|
import ani.dantotsu.currContext
|
||||||
import ani.dantotsu.databinding.DialogLayoutBinding
|
import ani.dantotsu.databinding.DialogLayoutBinding
|
||||||
import ani.dantotsu.databinding.ItemMediaSourceBinding
|
|
||||||
import ani.dantotsu.databinding.ItemChipBinding
|
import ani.dantotsu.databinding.ItemChipBinding
|
||||||
|
import ani.dantotsu.databinding.ItemMediaSourceBinding
|
||||||
import ani.dantotsu.displayTimer
|
import ani.dantotsu.displayTimer
|
||||||
import ani.dantotsu.isOnline
|
import ani.dantotsu.isOnline
|
||||||
import ani.dantotsu.loadImage
|
import ani.dantotsu.loadImage
|
||||||
|
@ -61,7 +61,8 @@ class AnimeWatchAdapter(
|
||||||
private var _binding: ItemMediaSourceBinding? = null
|
private var _binding: ItemMediaSourceBinding? = null
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
val bind = ItemMediaSourceBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
val bind =
|
||||||
|
ItemMediaSourceBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
return ViewHolder(bind)
|
return ViewHolder(bind)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +286,7 @@ class AnimeWatchAdapter(
|
||||||
fragment.requireContext().customAlertDialog().apply {
|
fragment.requireContext().customAlertDialog().apply {
|
||||||
setTitle(" Delete Progress for all episodes of ${media.nameRomaji}")
|
setTitle(" Delete Progress for all episodes of ${media.nameRomaji}")
|
||||||
setMessage("This will delete all the locally stored progress for all episodes")
|
setMessage("This will delete all the locally stored progress for all episodes")
|
||||||
setPosButton(R.string.ok){
|
setPosButton(R.string.ok) {
|
||||||
val prefix = "${media.id}_"
|
val prefix = "${media.id}_"
|
||||||
val regex = Regex("^${prefix}\\d+$")
|
val regex = Regex("^${prefix}\\d+$")
|
||||||
|
|
||||||
|
@ -300,7 +301,7 @@ class AnimeWatchAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resetProgressDef.text = getString(currContext()!!,R.string.clear_stored_episode)
|
resetProgressDef.text = getString(currContext()!!, R.string.clear_stored_episode)
|
||||||
|
|
||||||
// Hidden
|
// Hidden
|
||||||
mangaScanlatorContainer.visibility = View.GONE
|
mangaScanlatorContainer.visibility = View.GONE
|
||||||
|
@ -327,7 +328,7 @@ class AnimeWatchAdapter(
|
||||||
fragment.requireContext().customAlertDialog().apply {
|
fragment.requireContext().customAlertDialog().apply {
|
||||||
setTitle(" Delete Progress for all episodes of ${media.nameRomaji}")
|
setTitle(" Delete Progress for all episodes of ${media.nameRomaji}")
|
||||||
setMessage("This will delete all the locally stored progress for all episodes")
|
setMessage("This will delete all the locally stored progress for all episodes")
|
||||||
setPosButton(R.string.ok){
|
setPosButton(R.string.ok) {
|
||||||
val prefix = "${media.id}_"
|
val prefix = "${media.id}_"
|
||||||
val regex = Regex("^${prefix}\\d+$")
|
val regex = Regex("^${prefix}\\d+$")
|
||||||
|
|
||||||
|
@ -478,7 +479,8 @@ class AnimeWatchAdapter(
|
||||||
binding.sourceProgressBar.visibility = View.GONE
|
binding.sourceProgressBar.visibility = View.GONE
|
||||||
|
|
||||||
val sourceFound = media.anime.episodes!!.isNotEmpty()
|
val sourceFound = media.anime.episodes!!.isNotEmpty()
|
||||||
val isDownloadedSource = watchSources[media.selected!!.sourceIndex] is OfflineAnimeParser
|
val isDownloadedSource =
|
||||||
|
watchSources[media.selected!!.sourceIndex] is OfflineAnimeParser
|
||||||
|
|
||||||
if (isDownloadedSource) {
|
if (isDownloadedSource) {
|
||||||
binding.sourceNotFound.text = if (sourceFound) {
|
binding.sourceNotFound.text = if (sourceFound) {
|
||||||
|
@ -487,7 +489,8 @@ class AnimeWatchAdapter(
|
||||||
currActivity()!!.getString(R.string.download_not_found)
|
currActivity()!!.getString(R.string.download_not_found)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
binding.sourceNotFound.text = currActivity()!!.getString(R.string.source_not_found)
|
binding.sourceNotFound.text =
|
||||||
|
currActivity()!!.getString(R.string.source_not_found)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.sourceNotFound.isGone = sourceFound
|
binding.sourceNotFound.isGone = sourceFound
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package ani.dantotsu.media.anime
|
package ani.dantotsu.media.anime
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
@ -28,10 +27,8 @@ import androidx.recyclerview.widget.ConcatAdapter
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import ani.dantotsu.FileUrl
|
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.addons.download.DownloadAddonManager
|
import ani.dantotsu.addons.download.DownloadAddonManager
|
||||||
import ani.dantotsu.connections.anilist.api.MediaStreamingEpisode
|
|
||||||
import ani.dantotsu.databinding.FragmentMediaSourceBinding
|
import ani.dantotsu.databinding.FragmentMediaSourceBinding
|
||||||
import ani.dantotsu.download.DownloadedType
|
import ani.dantotsu.download.DownloadedType
|
||||||
import ani.dantotsu.download.DownloadsManager
|
import ani.dantotsu.download.DownloadsManager
|
||||||
|
@ -49,7 +46,6 @@ import ani.dantotsu.media.MediaType
|
||||||
import ani.dantotsu.navBarHeight
|
import ani.dantotsu.navBarHeight
|
||||||
import ani.dantotsu.notifications.subscription.SubscriptionHelper
|
import ani.dantotsu.notifications.subscription.SubscriptionHelper
|
||||||
import ani.dantotsu.notifications.subscription.SubscriptionHelper.Companion.saveSubscription
|
import ani.dantotsu.notifications.subscription.SubscriptionHelper.Companion.saveSubscription
|
||||||
import ani.dantotsu.others.Anify
|
|
||||||
import ani.dantotsu.others.LanguageMapper
|
import ani.dantotsu.others.LanguageMapper
|
||||||
import ani.dantotsu.parsers.AnimeParser
|
import ani.dantotsu.parsers.AnimeParser
|
||||||
import ani.dantotsu.parsers.AnimeSources
|
import ani.dantotsu.parsers.AnimeSources
|
||||||
|
@ -236,13 +232,16 @@ class AnimeWatchFragment : Fragment() {
|
||||||
episodes.forEach { (i, episode) ->
|
episodes.forEach { (i, episode) ->
|
||||||
if (media.anime?.anifyEpisodes != null) {
|
if (media.anime?.anifyEpisodes != null) {
|
||||||
if (media.anime!!.anifyEpisodes!!.containsKey(i)) {
|
if (media.anime!!.anifyEpisodes!!.containsKey(i)) {
|
||||||
episode.desc = media.anime!!.anifyEpisodes!![i]?.desc ?: episode.desc
|
episode.desc =
|
||||||
|
media.anime!!.anifyEpisodes!![i]?.desc ?: episode.desc
|
||||||
episode.title = if (MediaNameAdapter.removeEpisodeNumberCompletely(
|
episode.title = if (MediaNameAdapter.removeEpisodeNumberCompletely(
|
||||||
episode.title ?: ""
|
episode.title ?: ""
|
||||||
).isBlank()
|
).isBlank()
|
||||||
) media.anime!!.anifyEpisodes!![i]?.title ?: episode.title else episode.title
|
) media.anime!!.anifyEpisodes!![i]?.title
|
||||||
|
?: episode.title else episode.title
|
||||||
?: media.anime!!.anifyEpisodes!![i]?.title ?: episode.title
|
?: media.anime!!.anifyEpisodes!![i]?.title ?: episode.title
|
||||||
episode.thumb = media.anime!!.anifyEpisodes!![i]?.thumb ?: episode.thumb
|
episode.thumb =
|
||||||
|
media.anime!!.anifyEpisodes!![i]?.thumb ?: episode.thumb
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,13 +254,16 @@ class AnimeWatchFragment : Fragment() {
|
||||||
}
|
}
|
||||||
if (media.anime?.kitsuEpisodes != null) {
|
if (media.anime?.kitsuEpisodes != null) {
|
||||||
if (media.anime!!.kitsuEpisodes!!.containsKey(i)) {
|
if (media.anime!!.kitsuEpisodes!!.containsKey(i)) {
|
||||||
episode.desc = media.anime!!.kitsuEpisodes!![i]?.desc ?: episode.desc
|
episode.desc =
|
||||||
|
media.anime!!.kitsuEpisodes!![i]?.desc ?: episode.desc
|
||||||
episode.title = if (MediaNameAdapter.removeEpisodeNumberCompletely(
|
episode.title = if (MediaNameAdapter.removeEpisodeNumberCompletely(
|
||||||
episode.title ?: ""
|
episode.title ?: ""
|
||||||
).isBlank()
|
).isBlank()
|
||||||
) media.anime!!.kitsuEpisodes!![i]?.title ?: episode.title else episode.title
|
) media.anime!!.kitsuEpisodes!![i]?.title
|
||||||
?: media.anime!!.kitsuEpisodes!![i]?.title ?: episode.title
|
?: episode.title else episode.title
|
||||||
episode.thumb = media.anime!!.kitsuEpisodes!![i]?.thumb ?: episode.thumb
|
?: media.anime!!.kitsuEpisodes!![i]?.title ?: episode.title
|
||||||
|
episode.thumb =
|
||||||
|
media.anime!!.kitsuEpisodes!![i]?.thumb ?: episode.thumb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,29 +402,30 @@ class AnimeWatchFragment : Fragment() {
|
||||||
requireContext()
|
requireContext()
|
||||||
.customAlertDialog()
|
.customAlertDialog()
|
||||||
.apply {
|
.apply {
|
||||||
setTitle("Select a Source")
|
setTitle("Select a Source")
|
||||||
singleChoiceItems(names) { which ->
|
singleChoiceItems(names) { which ->
|
||||||
selectedSetting = allSettings[which]
|
selectedSetting = allSettings[which]
|
||||||
itemSelected = true
|
itemSelected = true
|
||||||
requireActivity().runOnUiThread {
|
requireActivity().runOnUiThread {
|
||||||
val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
val fragment =
|
||||||
changeUIVisibility(true)
|
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||||
loadEpisodes(media.selected!!.sourceIndex, true)
|
changeUIVisibility(true)
|
||||||
|
loadEpisodes(media.selected!!.sourceIndex, true)
|
||||||
|
}
|
||||||
|
parentFragmentManager.beginTransaction()
|
||||||
|
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||||
|
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||||
|
.addToBackStack(null)
|
||||||
|
.commit()
|
||||||
}
|
}
|
||||||
parentFragmentManager.beginTransaction()
|
|
||||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
|
||||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
|
||||||
.addToBackStack(null)
|
|
||||||
.commit()
|
|
||||||
}
|
}
|
||||||
}
|
onDismiss {
|
||||||
onDismiss {
|
if (!itemSelected) {
|
||||||
if (!itemSelected) {
|
changeUIVisibility(true)
|
||||||
changeUIVisibility(true)
|
}
|
||||||
}
|
}
|
||||||
|
show()
|
||||||
}
|
}
|
||||||
show()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// If there's only one setting, proceed with the fragment transaction
|
// If there's only one setting, proceed with the fragment transaction
|
||||||
requireActivity().runOnUiThread {
|
requireActivity().runOnUiThread {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package ani.dantotsu.media.anime
|
package ani.dantotsu.media.anime
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -13,7 +12,6 @@ import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.connections.updateProgress
|
import ani.dantotsu.connections.updateProgress
|
||||||
import ani.dantotsu.currContext
|
|
||||||
import ani.dantotsu.databinding.ItemEpisodeCompactBinding
|
import ani.dantotsu.databinding.ItemEpisodeCompactBinding
|
||||||
import ani.dantotsu.databinding.ItemEpisodeGridBinding
|
import ani.dantotsu.databinding.ItemEpisodeGridBinding
|
||||||
import ani.dantotsu.databinding.ItemEpisodeListBinding
|
import ani.dantotsu.databinding.ItemEpisodeListBinding
|
||||||
|
|
|
@ -12,8 +12,6 @@ import android.content.Intent
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.content.res.Resources
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.drawable.Animatable
|
import android.graphics.drawable.Animatable
|
||||||
import android.hardware.SensorManager
|
import android.hardware.SensorManager
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
|
@ -72,12 +70,10 @@ import androidx.media3.common.MimeTypes
|
||||||
import androidx.media3.common.PlaybackException
|
import androidx.media3.common.PlaybackException
|
||||||
import androidx.media3.common.PlaybackParameters
|
import androidx.media3.common.PlaybackParameters
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import androidx.media3.common.text.Cue
|
|
||||||
import androidx.media3.common.text.CueGroup
|
|
||||||
import androidx.media3.common.TrackGroup
|
import androidx.media3.common.TrackGroup
|
||||||
import androidx.media3.common.TrackSelectionOverride
|
import androidx.media3.common.TrackSelectionOverride
|
||||||
import androidx.media3.common.Tracks
|
import androidx.media3.common.Tracks
|
||||||
import androidx.media3.common.util.Util
|
import androidx.media3.common.text.CueGroup
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.datasource.DataSource
|
import androidx.media3.datasource.DataSource
|
||||||
import androidx.media3.datasource.DefaultDataSource
|
import androidx.media3.datasource.DefaultDataSource
|
||||||
|
@ -137,11 +133,11 @@ import ani.dantotsu.others.AniSkip
|
||||||
import ani.dantotsu.others.AniSkip.getType
|
import ani.dantotsu.others.AniSkip.getType
|
||||||
import ani.dantotsu.others.LanguageMapper
|
import ani.dantotsu.others.LanguageMapper
|
||||||
import ani.dantotsu.others.ResettableTimer
|
import ani.dantotsu.others.ResettableTimer
|
||||||
|
import ani.dantotsu.others.Xubtitle
|
||||||
import ani.dantotsu.others.getSerialized
|
import ani.dantotsu.others.getSerialized
|
||||||
import ani.dantotsu.parsers.AnimeSources
|
import ani.dantotsu.parsers.AnimeSources
|
||||||
import ani.dantotsu.parsers.HAnimeSources
|
import ani.dantotsu.parsers.HAnimeSources
|
||||||
import ani.dantotsu.parsers.Subtitle
|
import ani.dantotsu.parsers.Subtitle
|
||||||
import ani.dantotsu.others.Xubtitle
|
|
||||||
import ani.dantotsu.parsers.SubtitleType
|
import ani.dantotsu.parsers.SubtitleType
|
||||||
import ani.dantotsu.parsers.Video
|
import ani.dantotsu.parsers.Video
|
||||||
import ani.dantotsu.parsers.VideoExtractor
|
import ani.dantotsu.parsers.VideoExtractor
|
||||||
|
@ -164,6 +160,7 @@ import com.google.android.gms.common.ConnectionResult
|
||||||
import com.google.android.gms.common.GoogleApiAvailability
|
import com.google.android.gms.common.GoogleApiAvailability
|
||||||
import com.google.android.material.slider.Slider
|
import com.google.android.material.slider.Slider
|
||||||
import com.lagradost.nicehttp.ignoreAllSSLErrors
|
import com.lagradost.nicehttp.ignoreAllSSLErrors
|
||||||
|
import io.github.anilbeesetti.nextlib.media3ext.ffdecoder.NextRenderersFactory
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
@ -171,7 +168,6 @@ import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import io.github.anilbeesetti.nextlib.media3ext.ffdecoder.NextRenderersFactory
|
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.Timer
|
import java.util.Timer
|
||||||
|
@ -237,7 +233,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||||
|
|
||||||
private var downloadId: String? = null
|
private var downloadId: String? = null
|
||||||
private var hasExtSubtitles = false
|
private var hasExtSubtitles = false
|
||||||
private var audioLanguages = mutableListOf<Pair<String,String>>()
|
private var audioLanguages = mutableListOf<Pair<String, String>>()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
var initialized = false
|
var initialized = false
|
||||||
|
@ -408,14 +404,14 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSize)
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSize)
|
||||||
|
|
||||||
textView.apply {
|
textView.apply {
|
||||||
when (PrefManager.getVal<Int>(PrefName.Outline)) {
|
when (PrefManager.getVal<Int>(PrefName.Outline)) {
|
||||||
0 -> applyOutline(secondaryColor, subStroke)
|
0 -> applyOutline(secondaryColor, subStroke)
|
||||||
1 -> applyShineEffect(secondaryColor)
|
1 -> applyShineEffect(secondaryColor)
|
||||||
2 -> applyDropShadow(secondaryColor, subStroke)
|
2 -> applyDropShadow(secondaryColor, subStroke)
|
||||||
3 -> {}
|
3 -> {}
|
||||||
else -> applyOutline(secondaryColor, subStroke)
|
else -> applyOutline(secondaryColor, subStroke)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
textView.alpha =
|
textView.alpha =
|
||||||
when (PrefManager.getVal<Boolean>(PrefName.Subtitles)) {
|
when (PrefManager.getVal<Boolean>(PrefName.Subtitles)) {
|
||||||
|
@ -423,8 +419,9 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||||
false -> 0f
|
false -> 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
val textElevation = PrefManager.getVal<Float>(PrefName.SubBottomMargin) / 50 * resources.displayMetrics.heightPixels
|
val textElevation =
|
||||||
textView.translationY = -textElevation
|
PrefManager.getVal<Float>(PrefName.SubBottomMargin) / 50 * resources.displayMetrics.heightPixels
|
||||||
|
textView.translationY = -textElevation
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -1309,13 +1306,13 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun discordRPC(){
|
private fun discordRPC() {
|
||||||
val context = this
|
val context = this
|
||||||
val ep = episode
|
val ep = episode
|
||||||
val offline: Boolean = PrefManager.getVal(PrefName.OfflineMode)
|
val offline: Boolean = PrefManager.getVal(PrefName.OfflineMode)
|
||||||
val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
|
val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
|
||||||
val rpcenabled: Boolean = PrefManager.getVal(PrefName.rpcEnabled)
|
val rpcenabled: Boolean = PrefManager.getVal(PrefName.rpcEnabled)
|
||||||
if ((isOnline(context) && !offline) && Discord.token != null && !incognito && rpcenabled) {
|
if ((isOnline(context) && !offline) && Discord.token != null && !incognito && rpcenabled) {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val discordMode = PrefManager.getCustomVal("discord_mode", "dantotsu")
|
val discordMode = PrefManager.getCustomVal("discord_mode", "dantotsu")
|
||||||
val buttons = when (discordMode) {
|
val buttons = when (discordMode) {
|
||||||
|
@ -1340,7 +1337,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||||
else -> mutableListOf()
|
else -> mutableListOf()
|
||||||
}
|
}
|
||||||
val startTimestamp = Calendar.getInstance()
|
val startTimestamp = Calendar.getInstance()
|
||||||
val durationInSeconds = if (exoPlayer.duration != C.TIME_UNSET) (exoPlayer.duration / 1000).toInt() else 1440
|
val durationInSeconds =
|
||||||
|
if (exoPlayer.duration != C.TIME_UNSET) (exoPlayer.duration / 1000).toInt() else 1440
|
||||||
|
|
||||||
val endTimestamp = Calendar.getInstance().apply {
|
val endTimestamp = Calendar.getInstance().apply {
|
||||||
timeInMillis = startTimestamp.timeInMillis
|
timeInMillis = startTimestamp.timeInMillis
|
||||||
|
@ -1376,6 +1374,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initPlayer() {
|
private fun initPlayer() {
|
||||||
checkNotch()
|
checkNotch()
|
||||||
|
|
||||||
|
@ -1451,7 +1450,13 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||||
null -> {
|
null -> {
|
||||||
when (episode.selectedSubtitle) {
|
when (episode.selectedSubtitle) {
|
||||||
null -> null
|
null -> null
|
||||||
-1 -> ext.subtitles.find { it.language.contains( lang, ignoreCase = true ) || it.language.contains( getLanguageCode(lang), ignoreCase = true ) }
|
-1 -> ext.subtitles.find {
|
||||||
|
it.language.contains(
|
||||||
|
lang,
|
||||||
|
ignoreCase = true
|
||||||
|
) || it.language.contains(getLanguageCode(lang), ignoreCase = true)
|
||||||
|
}
|
||||||
|
|
||||||
else -> ext.subtitles.getOrNull(episode.selectedSubtitle!!)
|
else -> ext.subtitles.getOrNull(episode.selectedSubtitle!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1707,13 +1712,13 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||||
|
|
||||||
val useExtensionDecoder = PrefManager.getVal<Boolean>(PrefName.UseAdditionalCodec)
|
val useExtensionDecoder = PrefManager.getVal<Boolean>(PrefName.UseAdditionalCodec)
|
||||||
val decoder = if (useExtensionDecoder) {
|
val decoder = if (useExtensionDecoder) {
|
||||||
DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER
|
DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER
|
||||||
} else {
|
} else {
|
||||||
DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF
|
DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF
|
||||||
}
|
}
|
||||||
val renderersFactory = NextRenderersFactory(this)
|
val renderersFactory = NextRenderersFactory(this)
|
||||||
.setEnableDecoderFallback(true)
|
.setEnableDecoderFallback(true)
|
||||||
.setExtensionRendererMode(decoder)
|
.setExtensionRendererMode(decoder)
|
||||||
|
|
||||||
exoPlayer = ExoPlayer.Builder(this, renderersFactory)
|
exoPlayer = ExoPlayer.Builder(this, renderersFactory)
|
||||||
.setMediaSourceFactory(DefaultMediaSourceFactory(cacheFactory))
|
.setMediaSourceFactory(DefaultMediaSourceFactory(cacheFactory))
|
||||||
|
@ -1743,7 +1748,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||||
if (PrefManager.getVal<Boolean>(PrefName.TextviewSubtitles)) {
|
if (PrefManager.getVal<Boolean>(PrefName.TextviewSubtitles)) {
|
||||||
exoSubtitleView.visibility = View.GONE
|
exoSubtitleView.visibility = View.GONE
|
||||||
customSubtitleView.visibility = View.VISIBLE
|
customSubtitleView.visibility = View.VISIBLE
|
||||||
val newCues = cueGroup.cues.map { it.text.toString() ?: "" }
|
val newCues = cueGroup.cues.map { it.text.toString() }
|
||||||
|
|
||||||
if (newCues.isEmpty()) {
|
if (newCues.isEmpty()) {
|
||||||
customSubtitleView.text = ""
|
customSubtitleView.text = ""
|
||||||
|
@ -1755,20 +1760,22 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||||
|
|
||||||
val currentPosition = exoPlayer.currentPosition
|
val currentPosition = exoPlayer.currentPosition
|
||||||
|
|
||||||
if ((lastSubtitle?.length ?: 0) < 20 || (lastPosition != 0L && currentPosition - lastPosition > 1500)) {
|
if ((lastSubtitle?.length
|
||||||
|
?: 0) < 20 || (lastPosition != 0L && currentPosition - lastPosition > 1500)
|
||||||
|
) {
|
||||||
activeSubtitles.clear()
|
activeSubtitles.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (newCue in newCues) {
|
for (newCue in newCues) {
|
||||||
if (newCue !in activeSubtitles) {
|
if (newCue !in activeSubtitles) {
|
||||||
if (activeSubtitles.size >= 2) {
|
if (activeSubtitles.size >= 2) {
|
||||||
activeSubtitles.removeLast()
|
activeSubtitles.removeLast()
|
||||||
}
|
}
|
||||||
activeSubtitles.addFirst(newCue)
|
activeSubtitles.addFirst(newCue)
|
||||||
lastSubtitle = newCue
|
lastSubtitle = newCue
|
||||||
lastPosition = currentPosition
|
lastPosition = currentPosition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customSubtitleView.text = activeSubtitles.joinToString("\n")
|
customSubtitleView.text = activeSubtitles.joinToString("\n")
|
||||||
} else {
|
} else {
|
||||||
|
@ -1779,8 +1786,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
applySubtitleStyles(customSubtitleView)
|
applySubtitleStyles(customSubtitleView)
|
||||||
setupSubFormatting(playerView)
|
setupSubFormatting(playerView)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val rightNow = Calendar.getInstance()
|
val rightNow = Calendar.getInstance()
|
||||||
|
|
|
@ -2,7 +2,6 @@ package ani.dantotsu.media.anime
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
|
@ -446,7 +445,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
||||||
var subtitleToDownload: Subtitle? = null
|
var subtitleToDownload: Subtitle? = null
|
||||||
requireActivity().customAlertDialog().apply {
|
requireActivity().customAlertDialog().apply {
|
||||||
setTitle(R.string.download_subtitle)
|
setTitle(R.string.download_subtitle)
|
||||||
singleChoiceItems(subtitleNames.toTypedArray()) {which ->
|
singleChoiceItems(subtitleNames.toTypedArray()) { which ->
|
||||||
subtitleToDownload = subtitles[which]
|
subtitleToDownload = subtitles[which]
|
||||||
}
|
}
|
||||||
setPosButton(R.string.download) {
|
setPosButton(R.string.download) {
|
||||||
|
@ -483,7 +482,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val downloadAddonManager: DownloadAddonManager = Injekt.get()
|
val downloadAddonManager: DownloadAddonManager = Injekt.get()
|
||||||
if (!downloadAddonManager.isAvailable()){
|
if (!downloadAddonManager.isAvailable()) {
|
||||||
val context = currContext() ?: requireContext()
|
val context = currContext() ?: requireContext()
|
||||||
context.customAlertDialog().apply {
|
context.customAlertDialog().apply {
|
||||||
setTitle(R.string.download_addon_not_installed)
|
setTitle(R.string.download_addon_not_installed)
|
||||||
|
@ -564,17 +563,21 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
||||||
snackString(R.string.no_video_selected)
|
snackString(R.string.no_video_selected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkAudioTracks() {
|
fun checkAudioTracks() {
|
||||||
val audioTracks = extractor.audioTracks.map { it.lang }
|
val audioTracks = extractor.audioTracks.map { it.lang }
|
||||||
if (audioTracks.isNotEmpty()) {
|
if (audioTracks.isNotEmpty()) {
|
||||||
val audioNamesArray = audioTracks.toTypedArray()
|
val audioNamesArray = audioTracks.toTypedArray()
|
||||||
val checkedItems = BooleanArray(audioNamesArray.size) { false }
|
val checkedItems = BooleanArray(audioNamesArray.size) { false }
|
||||||
|
|
||||||
currContext.customAlertDialog().apply{ // ToTest
|
currContext.customAlertDialog().apply { // ToTest
|
||||||
setTitle(R.string.download_audio_tracks)
|
setTitle(R.string.download_audio_tracks)
|
||||||
multiChoiceItems(audioNamesArray, checkedItems) {
|
multiChoiceItems(audioNamesArray, checkedItems) {
|
||||||
it.forEachIndexed { index, isChecked ->
|
it.forEachIndexed { index, isChecked ->
|
||||||
val audioPair = Pair(extractor.audioTracks[index].url, extractor.audioTracks[index].lang)
|
val audioPair = Pair(
|
||||||
|
extractor.audioTracks[index].url,
|
||||||
|
extractor.audioTracks[index].lang
|
||||||
|
)
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
selectedAudioTracks.add(audioPair)
|
selectedAudioTracks.add(audioPair)
|
||||||
} else {
|
} else {
|
||||||
|
@ -606,7 +609,8 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
||||||
setTitle(R.string.download_subtitle)
|
setTitle(R.string.download_subtitle)
|
||||||
multiChoiceItems(subtitleNamesArray, checkedItems) {
|
multiChoiceItems(subtitleNamesArray, checkedItems) {
|
||||||
it.forEachIndexed { index, isChecked ->
|
it.forEachIndexed { index, isChecked ->
|
||||||
val subtitlePair = Pair(subtitles[index].file.url, subtitles[index].language)
|
val subtitlePair =
|
||||||
|
Pair(subtitles[index].file.url, subtitles[index].language)
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
selectedSubtitles.add(subtitlePair)
|
selectedSubtitles.add(subtitlePair)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -63,8 +63,12 @@ class TrackGroupDialogFragment(
|
||||||
override fun onBindViewHolder(holder: StreamViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: StreamViewHolder, position: Int) {
|
||||||
val binding = holder.binding
|
val binding = holder.binding
|
||||||
trackGroups[position].let { trackGroup ->
|
trackGroups[position].let { trackGroup ->
|
||||||
if (overrideTrackNames?.getOrNull(position - (trackGroups.size - (overrideTrackNames?.size?:0))) != null) {
|
if (overrideTrackNames?.getOrNull(
|
||||||
val pair = overrideTrackNames!![position - (trackGroups.size - overrideTrackNames!!.size)]
|
position - (trackGroups.size - (overrideTrackNames?.size ?: 0))
|
||||||
|
) != null
|
||||||
|
) {
|
||||||
|
val pair =
|
||||||
|
overrideTrackNames!![position - (trackGroups.size - overrideTrackNames!!.size)]
|
||||||
binding.subtitleTitle.text =
|
binding.subtitleTitle.text =
|
||||||
"[${pair.second}] ${pair.first}"
|
"[${pair.second}] ${pair.first}"
|
||||||
} else when (val language = trackGroup.getTrackFormat(0).language?.lowercase()) {
|
} else when (val language = trackGroup.getTrackFormat(0).language?.lowercase()) {
|
||||||
|
|
|
@ -15,7 +15,6 @@ import ani.dantotsu.databinding.ItemCommentsBinding
|
||||||
import ani.dantotsu.getAppString
|
import ani.dantotsu.getAppString
|
||||||
import ani.dantotsu.loadImage
|
import ani.dantotsu.loadImage
|
||||||
import ani.dantotsu.openImage
|
import ani.dantotsu.openImage
|
||||||
import ani.dantotsu.others.ImageViewDialog
|
|
||||||
import ani.dantotsu.profile.ProfileActivity
|
import ani.dantotsu.profile.ProfileActivity
|
||||||
import ani.dantotsu.setAnimation
|
import ani.dantotsu.setAnimation
|
||||||
import ani.dantotsu.snackString
|
import ani.dantotsu.snackString
|
||||||
|
|
|
@ -2,7 +2,6 @@ package ani.dantotsu.media.comments
|
||||||
|
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.content.Context.INPUT_METHOD_SERVICE
|
import android.content.Context.INPUT_METHOD_SERVICE
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -12,7 +11,6 @@ import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.EditText
|
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.core.animation.doOnEnd
|
import androidx.core.animation.doOnEnd
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
|
@ -33,7 +31,6 @@ import ani.dantotsu.setBaseline
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.snackString
|
import ani.dantotsu.snackString
|
||||||
import ani.dantotsu.toast
|
|
||||||
import ani.dantotsu.util.Logger
|
import ani.dantotsu.util.Logger
|
||||||
import ani.dantotsu.util.customAlertDialog
|
import ani.dantotsu.util.customAlertDialog
|
||||||
import com.xwray.groupie.GroupieAdapter
|
import com.xwray.groupie.GroupieAdapter
|
||||||
|
@ -587,19 +584,19 @@ class CommentsFragment : Fragment() {
|
||||||
private fun showCommentRulesDialog() {
|
private fun showCommentRulesDialog() {
|
||||||
activity.customAlertDialog().apply {
|
activity.customAlertDialog().apply {
|
||||||
setTitle("Commenting Rules")
|
setTitle("Commenting Rules")
|
||||||
.setMessage(
|
.setMessage(
|
||||||
"🚨 BREAK ANY RULE = YOU'RE GONE\n\n" +
|
"🚨 BREAK ANY RULE = YOU'RE GONE\n\n" +
|
||||||
"1. NO RACISM, DISCRIMINATION, OR HATE SPEECH\n" +
|
"1. NO RACISM, DISCRIMINATION, OR HATE SPEECH\n" +
|
||||||
"2. NO SPAMMING OR SELF-PROMOTION\n" +
|
"2. NO SPAMMING OR SELF-PROMOTION\n" +
|
||||||
"3. ABSOLUTELY NO NSFW CONTENT\n" +
|
"3. ABSOLUTELY NO NSFW CONTENT\n" +
|
||||||
"4. ENGLISH ONLY – NO EXCEPTIONS\n" +
|
"4. ENGLISH ONLY – NO EXCEPTIONS\n" +
|
||||||
"5. NO IMPERSONATION, HARASSMENT, OR ABUSE\n" +
|
"5. NO IMPERSONATION, HARASSMENT, OR ABUSE\n" +
|
||||||
"6. NO ILLEGAL CONTENT OR EXTREME DISRESPECT TOWARDS ANY FANDOM\n" +
|
"6. NO ILLEGAL CONTENT OR EXTREME DISRESPECT TOWARDS ANY FANDOM\n" +
|
||||||
"7. DO NOT REQUEST OR SHARE REPOSITORIES/EXTENSIONS\n" +
|
"7. DO NOT REQUEST OR SHARE REPOSITORIES/EXTENSIONS\n" +
|
||||||
"8. SPOILERS ALLOWED ONLY WITH SPOILER TAGS AND A WARNING\n" +
|
"8. SPOILERS ALLOWED ONLY WITH SPOILER TAGS AND A WARNING\n" +
|
||||||
"9. NO SEXUALIZING OR INAPPROPRIATE COMMENTS ABOUT MINOR CHARACTERS\n" +
|
"9. NO SEXUALIZING OR INAPPROPRIATE COMMENTS ABOUT MINOR CHARACTERS\n" +
|
||||||
"10. IF IT'S WRONG, DON'T POST IT!\n\n"
|
"10. IF IT'S WRONG, DON'T POST IT!\n\n"
|
||||||
)
|
)
|
||||||
setPosButton("I Understand") {
|
setPosButton("I Understand") {
|
||||||
PrefManager.setVal(PrefName.FirstComment, false)
|
PrefManager.setVal(PrefName.FirstComment, false)
|
||||||
processComment()
|
processComment()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package ani.dantotsu.media.manga
|
package ani.dantotsu.media.manga
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
|
|
@ -22,8 +22,8 @@ import ani.dantotsu.currActivity
|
||||||
import ani.dantotsu.currContext
|
import ani.dantotsu.currContext
|
||||||
import ani.dantotsu.databinding.CustomDialogLayoutBinding
|
import ani.dantotsu.databinding.CustomDialogLayoutBinding
|
||||||
import ani.dantotsu.databinding.DialogLayoutBinding
|
import ani.dantotsu.databinding.DialogLayoutBinding
|
||||||
import ani.dantotsu.databinding.ItemMediaSourceBinding
|
|
||||||
import ani.dantotsu.databinding.ItemChipBinding
|
import ani.dantotsu.databinding.ItemChipBinding
|
||||||
|
import ani.dantotsu.databinding.ItemMediaSourceBinding
|
||||||
import ani.dantotsu.isOnline
|
import ani.dantotsu.isOnline
|
||||||
import ani.dantotsu.loadImage
|
import ani.dantotsu.loadImage
|
||||||
import ani.dantotsu.media.Media
|
import ani.dantotsu.media.Media
|
||||||
|
@ -75,7 +75,8 @@ class MangaReadAdapter(
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
val bind = ItemMediaSourceBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
val bind =
|
||||||
|
ItemMediaSourceBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
return ViewHolder(bind)
|
return ViewHolder(bind)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,11 +100,11 @@ class MangaReadAdapter(
|
||||||
}
|
}
|
||||||
val offline = !isOnline(binding.root.context) || PrefManager.getVal(PrefName.OfflineMode)
|
val offline = !isOnline(binding.root.context) || PrefManager.getVal(PrefName.OfflineMode)
|
||||||
//for removing saved progress
|
//for removing saved progress
|
||||||
binding.sourceTitle.setOnLongClickListener{
|
binding.sourceTitle.setOnLongClickListener {
|
||||||
fragment.requireContext().customAlertDialog().apply {
|
fragment.requireContext().customAlertDialog().apply {
|
||||||
setTitle(" Delete Progress for all chapters of ${media.nameRomaji}")
|
setTitle(" Delete Progress for all chapters of ${media.nameRomaji}")
|
||||||
setMessage("This will delete all the locally stored progress for chapters")
|
setMessage("This will delete all the locally stored progress for chapters")
|
||||||
setPosButton(R.string.ok){
|
setPosButton(R.string.ok) {
|
||||||
clearCustomValsForMedia("${media.id}", "_Chapter")
|
clearCustomValsForMedia("${media.id}", "_Chapter")
|
||||||
clearCustomValsForMedia("${media.id}", "_Vol")
|
clearCustomValsForMedia("${media.id}", "_Vol")
|
||||||
snackString("Deleted the progress of Chapters for ${media.nameRomaji}")
|
snackString("Deleted the progress of Chapters for ${media.nameRomaji}")
|
||||||
|
@ -286,7 +287,7 @@ class MangaReadAdapter(
|
||||||
fragment.requireContext().customAlertDialog().apply {
|
fragment.requireContext().customAlertDialog().apply {
|
||||||
setTitle(" Delete Progress for all chapters of ${media.nameRomaji}")
|
setTitle(" Delete Progress for all chapters of ${media.nameRomaji}")
|
||||||
setMessage("This will delete all the locally stored progress for chapters")
|
setMessage("This will delete all the locally stored progress for chapters")
|
||||||
setPosButton(R.string.ok){
|
setPosButton(R.string.ok) {
|
||||||
// Usage
|
// Usage
|
||||||
clearCustomValsForMedia("${media.id}", "_Chapter")
|
clearCustomValsForMedia("${media.id}", "_Chapter")
|
||||||
clearCustomValsForMedia("${media.id}", "_Vol")
|
clearCustomValsForMedia("${media.id}", "_Vol")
|
||||||
|
@ -297,7 +298,7 @@ class MangaReadAdapter(
|
||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resetProgressDef.text = getString(currContext()!!,R.string.clear_stored_chapter)
|
resetProgressDef.text = getString(currContext()!!, R.string.clear_stored_chapter)
|
||||||
|
|
||||||
// Scanlator
|
// Scanlator
|
||||||
mangaScanlatorContainer.isVisible = options.count() > 1
|
mangaScanlatorContainer.isVisible = options.count() > 1
|
||||||
|
@ -331,12 +332,17 @@ class MangaReadAdapter(
|
||||||
val checkBox = CheckBox(currContext()).apply {
|
val checkBox = CheckBox(currContext()).apply {
|
||||||
text = option
|
text = option
|
||||||
setOnCheckedChangeListener { _, _ ->
|
setOnCheckedChangeListener { _, _ ->
|
||||||
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
|
tickAllButton.setImageResource(
|
||||||
|
getToggleImageResource(
|
||||||
|
checkboxContainer
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (media.selected!!.scanlators != null) {
|
if (media.selected!!.scanlators != null) {
|
||||||
checkBox.isChecked = media.selected!!.scanlators?.contains(option) != true
|
checkBox.isChecked =
|
||||||
|
media.selected!!.scanlators?.contains(option) != true
|
||||||
scanlatorSelectionListener?.onScanlatorsSelected()
|
scanlatorSelectionListener?.onScanlatorsSelected()
|
||||||
} else {
|
} else {
|
||||||
checkBox.isChecked = true
|
checkBox.isChecked = true
|
||||||
|
@ -488,10 +494,12 @@ class MangaReadAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val formattedChapters = filteredChapters.map {
|
val formattedChapters = filteredChapters.map {
|
||||||
MediaNameAdapter.findChapterNumber(it.value.number)?.toInt()?.toString() to it.key
|
MediaNameAdapter.findChapterNumber(it.value.number)?.toInt()
|
||||||
|
?.toString() to it.key
|
||||||
}
|
}
|
||||||
if (formattedChapters.any { it.first == continueNumber }) {
|
if (formattedChapters.any { it.first == continueNumber }) {
|
||||||
var continueEp = media.manga.chapters!![formattedChapters.first { it.first == continueNumber }.second]
|
var continueEp =
|
||||||
|
media.manga.chapters!![formattedChapters.first { it.first == continueNumber }.second]
|
||||||
binding.sourceContinue.visibility = View.VISIBLE
|
binding.sourceContinue.visibility = View.VISIBLE
|
||||||
handleProgress(
|
handleProgress(
|
||||||
binding.itemMediaProgressCont,
|
binding.itemMediaProgressCont,
|
||||||
|
@ -501,9 +509,11 @@ class MangaReadAdapter(
|
||||||
continueEp!!.number
|
continueEp!!.number
|
||||||
)
|
)
|
||||||
if ((binding.itemMediaProgress.layoutParams as LinearLayout.LayoutParams).weight > 0.8f) {
|
if ((binding.itemMediaProgress.layoutParams as LinearLayout.LayoutParams).weight > 0.8f) {
|
||||||
val numberPlusOne = formattedChapters.indexOfFirst { it.first?.toIntOrNull() == continueNumber.toInt() + 1 }
|
val numberPlusOne =
|
||||||
|
formattedChapters.indexOfFirst { it.first?.toIntOrNull() == continueNumber.toInt() + 1 }
|
||||||
if (numberPlusOne != -1) {
|
if (numberPlusOne != -1) {
|
||||||
continueEp = media.manga.chapters!![formattedChapters[numberPlusOne].second]
|
continueEp =
|
||||||
|
media.manga.chapters!![formattedChapters[numberPlusOne].second]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.itemMediaImage.loadImage(media.banner ?: media.cover)
|
binding.itemMediaImage.loadImage(media.banner ?: media.cover)
|
||||||
|
@ -530,7 +540,8 @@ class MangaReadAdapter(
|
||||||
binding.sourceProgressBar.visibility = View.GONE
|
binding.sourceProgressBar.visibility = View.GONE
|
||||||
|
|
||||||
val sourceFound = filteredChapters.isNotEmpty()
|
val sourceFound = filteredChapters.isNotEmpty()
|
||||||
val isDownloadedSource = mangaReadSources[media.selected!!.sourceIndex] is OfflineMangaParser
|
val isDownloadedSource =
|
||||||
|
mangaReadSources[media.selected!!.sourceIndex] is OfflineMangaParser
|
||||||
|
|
||||||
if (isDownloadedSource) {
|
if (isDownloadedSource) {
|
||||||
binding.sourceNotFound.text = if (sourceFound) {
|
binding.sourceNotFound.text = if (sourceFound) {
|
||||||
|
@ -539,7 +550,8 @@ class MangaReadAdapter(
|
||||||
currActivity()!!.getString(R.string.download_not_found)
|
currActivity()!!.getString(R.string.download_not_found)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
binding.sourceNotFound.text = currActivity()!!.getString(R.string.source_not_found)
|
binding.sourceNotFound.text =
|
||||||
|
currActivity()!!.getString(R.string.source_not_found)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.sourceNotFound.isGone = sourceFound
|
binding.sourceNotFound.isGone = sourceFound
|
||||||
|
|
|
@ -261,13 +261,14 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
||||||
val chapters = loadedChapters[media.selected!!.sourceIndex]
|
val chapters = loadedChapters[media.selected!!.sourceIndex]
|
||||||
if (chapters != null) {
|
if (chapters != null) {
|
||||||
headerAdapter.options = getScanlators(chapters)
|
headerAdapter.options = getScanlators(chapters)
|
||||||
val filteredChapters = if (model.mangaReadSources?.get(media.selected!!.sourceIndex) is OfflineMangaParser) {
|
val filteredChapters =
|
||||||
chapters
|
if (model.mangaReadSources?.get(media.selected!!.sourceIndex) is OfflineMangaParser) {
|
||||||
} else {
|
chapters
|
||||||
chapters.filterNot { (_, chapter) ->
|
} else {
|
||||||
chapter.scanlator in headerAdapter.hiddenScanlators
|
chapters.filterNot { (_, chapter) ->
|
||||||
|
chapter.scanlator in headerAdapter.hiddenScanlators
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
media.manga?.chapters = filteredChapters.toMutableMap()
|
media.manga?.chapters = filteredChapters.toMutableMap()
|
||||||
|
|
||||||
|
@ -397,17 +398,18 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
||||||
selectedSetting = allSettings[which]
|
selectedSetting = allSettings[which]
|
||||||
itemSelected = true
|
itemSelected = true
|
||||||
|
|
||||||
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
val fragment =
|
||||||
changeUIVisibility(true)
|
MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||||
loadChapters(media.selected!!.sourceIndex, true)
|
changeUIVisibility(true)
|
||||||
}
|
loadChapters(media.selected!!.sourceIndex, true)
|
||||||
|
}
|
||||||
parentFragmentManager.beginTransaction()
|
parentFragmentManager.beginTransaction()
|
||||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||||
.addToBackStack(null)
|
.addToBackStack(null)
|
||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
onDismiss{
|
onDismiss {
|
||||||
if (!itemSelected) {
|
if (!itemSelected) {
|
||||||
changeUIVisibility(true)
|
changeUIVisibility(true)
|
||||||
}
|
}
|
||||||
|
@ -590,7 +592,9 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
||||||
|
|
||||||
// Find latest chapter for subscription
|
// Find latest chapter for subscription
|
||||||
selected.latest =
|
selected.latest =
|
||||||
media.manga?.chapters?.values?.maxOfOrNull { MediaNameAdapter.findChapterNumber(it.number) ?: 0f } ?: 0f
|
media.manga?.chapters?.values?.maxOfOrNull {
|
||||||
|
MediaNameAdapter.findChapterNumber(it.number) ?: 0f
|
||||||
|
} ?: 0f
|
||||||
selected.latest =
|
selected.latest =
|
||||||
media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest
|
media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,8 @@ class ChapterLoaderDialog : BottomSheetDialogFragment() {
|
||||||
_binding = BottomSheetSelectorBinding.inflate(inflater, container, false)
|
_binding = BottomSheetSelectorBinding.inflate(inflater, container, false)
|
||||||
val window = dialog?.window
|
val window = dialog?.window
|
||||||
window?.statusBarColor = Color.TRANSPARENT
|
window?.statusBarColor = Color.TRANSPARENT
|
||||||
window?.navigationBarColor = requireContext().getThemeColor(com.google.android.material.R.attr.colorSurface)
|
window?.navigationBarColor =
|
||||||
|
requireContext().getThemeColor(com.google.android.material.R.attr.colorSurface)
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package ani.dantotsu.media.manga.mangareader
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
@ -58,8 +57,6 @@ import ani.dantotsu.media.Media
|
||||||
import ani.dantotsu.media.MediaDetailsViewModel
|
import ani.dantotsu.media.MediaDetailsViewModel
|
||||||
import ani.dantotsu.media.MediaNameAdapter
|
import ani.dantotsu.media.MediaNameAdapter
|
||||||
import ani.dantotsu.media.MediaSingleton
|
import ani.dantotsu.media.MediaSingleton
|
||||||
import ani.dantotsu.media.anime.ExoplayerView
|
|
||||||
import ani.dantotsu.media.anime.ExoplayerView.Companion
|
|
||||||
import ani.dantotsu.media.manga.MangaCache
|
import ani.dantotsu.media.manga.MangaCache
|
||||||
import ani.dantotsu.media.manga.MangaChapter
|
import ani.dantotsu.media.manga.MangaChapter
|
||||||
import ani.dantotsu.others.ImageViewDialog
|
import ani.dantotsu.others.ImageViewDialog
|
||||||
|
@ -196,8 +193,9 @@ class MangaReaderActivity : AppCompatActivity() {
|
||||||
finish()
|
finish()
|
||||||
return@addCallback
|
return@addCallback
|
||||||
}
|
}
|
||||||
val chapter = (MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!.number)
|
val chapter =
|
||||||
?.minus(1L) ?: 0).toString()
|
(MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!.number)
|
||||||
|
?.minus(1L) ?: 0).toString()
|
||||||
if (chapter == "0.0" && PrefManager.getVal(PrefName.ChapterZeroReader)
|
if (chapter == "0.0" && PrefManager.getVal(PrefName.ChapterZeroReader)
|
||||||
// Not asking individually or incognito
|
// Not asking individually or incognito
|
||||||
&& !showProgressDialog && !PrefManager.getVal<Boolean>(PrefName.Incognito)
|
&& !showProgressDialog && !PrefManager.getVal<Boolean>(PrefName.Incognito)
|
||||||
|
|
|
@ -55,6 +55,7 @@ class Swipy @JvmOverloads constructor(
|
||||||
else
|
else
|
||||||
VerticalPosition.Top
|
VerticalPosition.Top
|
||||||
}
|
}
|
||||||
|
|
||||||
!it.canScrollVertically(1) -> VerticalPosition.Bottom
|
!it.canScrollVertically(1) -> VerticalPosition.Bottom
|
||||||
!it.canScrollVertically(-1) -> VerticalPosition.Top
|
!it.canScrollVertically(-1) -> VerticalPosition.Top
|
||||||
else -> VerticalPosition.None
|
else -> VerticalPosition.None
|
||||||
|
@ -67,6 +68,7 @@ class Swipy @JvmOverloads constructor(
|
||||||
else
|
else
|
||||||
HorizontalPosition.Left
|
HorizontalPosition.Left
|
||||||
}
|
}
|
||||||
|
|
||||||
!it.canScrollHorizontally(1) -> HorizontalPosition.Right
|
!it.canScrollHorizontally(1) -> HorizontalPosition.Right
|
||||||
!it.canScrollHorizontally(-1) -> HorizontalPosition.Left
|
!it.canScrollHorizontally(-1) -> HorizontalPosition.Left
|
||||||
else -> HorizontalPosition.None
|
else -> HorizontalPosition.None
|
||||||
|
@ -97,12 +99,14 @@ class Swipy @JvmOverloads constructor(
|
||||||
initialDown = if (vertical) ev.getY(0) else ev.getX(0)
|
initialDown = if (vertical) ev.getY(0) else ev.getX(0)
|
||||||
isBeingDragged = false
|
isBeingDragged = false
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionEvent.ACTION_MOVE -> {
|
MotionEvent.ACTION_MOVE -> {
|
||||||
val pointerIndex = ev.findPointerIndex(activePointerId)
|
val pointerIndex = ev.findPointerIndex(activePointerId)
|
||||||
if (pointerIndex >= 0) {
|
if (pointerIndex >= 0) {
|
||||||
startDragging(if (vertical) ev.getY(pointerIndex) else ev.getX(pointerIndex))
|
startDragging(if (vertical) ev.getY(pointerIndex) else ev.getX(pointerIndex))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionEvent.ACTION_POINTER_UP -> onSecondaryPointerUp(ev)
|
MotionEvent.ACTION_POINTER_UP -> onSecondaryPointerUp(ev)
|
||||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||||
isBeingDragged = false
|
isBeingDragged = false
|
||||||
|
@ -122,6 +126,7 @@ class Swipy @JvmOverloads constructor(
|
||||||
activePointerId = ev.getPointerId(0)
|
activePointerId = ev.getPointerId(0)
|
||||||
isBeingDragged = false
|
isBeingDragged = false
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionEvent.ACTION_MOVE -> {
|
MotionEvent.ACTION_MOVE -> {
|
||||||
pointerIndex = ev.findPointerIndex(activePointerId)
|
pointerIndex = ev.findPointerIndex(activePointerId)
|
||||||
if (pointerIndex >= 0) {
|
if (pointerIndex >= 0) {
|
||||||
|
@ -130,28 +135,36 @@ class Swipy @JvmOverloads constructor(
|
||||||
if (isBeingDragged) handleDrag(pos)
|
if (isBeingDragged) handleDrag(pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionEvent.ACTION_POINTER_DOWN -> {
|
MotionEvent.ACTION_POINTER_DOWN -> {
|
||||||
pointerIndex = ev.actionIndex
|
pointerIndex = ev.actionIndex
|
||||||
if (pointerIndex >= 0) activePointerId = ev.getPointerId(pointerIndex)
|
if (pointerIndex >= 0) activePointerId = ev.getPointerId(pointerIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionEvent.ACTION_POINTER_UP -> onSecondaryPointerUp(ev)
|
MotionEvent.ACTION_POINTER_UP -> onSecondaryPointerUp(ev)
|
||||||
MotionEvent.ACTION_UP -> {
|
MotionEvent.ACTION_UP -> {
|
||||||
resetSwipes()
|
resetSwipes()
|
||||||
pointerIndex = ev.findPointerIndex(activePointerId)
|
pointerIndex = ev.findPointerIndex(activePointerId)
|
||||||
if (pointerIndex >= 0) finishSpinner(if (vertical) ev.getY(pointerIndex) else ev.getX(pointerIndex))
|
if (pointerIndex >= 0) finishSpinner(
|
||||||
|
if (vertical) ev.getY(pointerIndex) else ev.getX(
|
||||||
|
pointerIndex
|
||||||
|
)
|
||||||
|
)
|
||||||
activePointerId = INVALID_POINTER
|
activePointerId = INVALID_POINTER
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionEvent.ACTION_CANCEL -> return false
|
MotionEvent.ACTION_CANCEL -> return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startDragging(pos: Float) {
|
private fun startDragging(pos: Float) {
|
||||||
val posDiff = if ((vertical && verticalPos == VerticalPosition.Top) || (!vertical && horizontalPos == HorizontalPosition.Left))
|
val posDiff =
|
||||||
pos - initialDown
|
if ((vertical && verticalPos == VerticalPosition.Top) || (!vertical && horizontalPos == HorizontalPosition.Left))
|
||||||
else
|
pos - initialDown
|
||||||
initialDown - pos
|
else
|
||||||
|
initialDown - pos
|
||||||
if (posDiff > touchSlop && !isBeingDragged) {
|
if (posDiff > touchSlop && !isBeingDragged) {
|
||||||
initialMotion = initialDown + touchSlop
|
initialMotion = initialDown + touchSlop
|
||||||
isBeingDragged = true
|
isBeingDragged = true
|
||||||
|
|
|
@ -14,8 +14,6 @@ import ani.dantotsu.setAnimation
|
||||||
import ani.dantotsu.snackString
|
import ani.dantotsu.snackString
|
||||||
import ani.dantotsu.util.Logger
|
import ani.dantotsu.util.Logger
|
||||||
import ani.dantotsu.util.customAlertDialog
|
import ani.dantotsu.util.customAlertDialog
|
||||||
import com.bumptech.glide.Glide
|
|
||||||
import com.bumptech.glide.load.model.GlideUrl
|
|
||||||
|
|
||||||
class NovelResponseAdapter(
|
class NovelResponseAdapter(
|
||||||
val fragment: NovelReadFragment,
|
val fragment: NovelReadFragment,
|
||||||
|
@ -41,7 +39,8 @@ class NovelResponseAdapter(
|
||||||
setAnimation(fragment.requireContext(), holder.binding.root)
|
setAnimation(fragment.requireContext(), holder.binding.root)
|
||||||
binding.itemMediaImage.loadImage(novel.coverUrl, 400, 0)
|
binding.itemMediaImage.loadImage(novel.coverUrl, 400, 0)
|
||||||
|
|
||||||
val color =fragment.requireContext().getThemeColor(com.google.android.material.R.attr.colorOnBackground)
|
val color = fragment.requireContext()
|
||||||
|
.getThemeColor(com.google.android.material.R.attr.colorOnBackground)
|
||||||
binding.itemEpisodeTitle.text = novel.name
|
binding.itemEpisodeTitle.text = novel.name
|
||||||
binding.itemEpisodeFiller.text =
|
binding.itemEpisodeFiller.text =
|
||||||
if (downloadedCheckCallback.downloadedCheck(novel)) {
|
if (downloadedCheckCallback.downloadedCheck(novel)) {
|
||||||
|
|
|
@ -50,10 +50,10 @@ class ListViewModel : ViewModel() {
|
||||||
search,
|
search,
|
||||||
ignoreCase = true
|
ignoreCase = true
|
||||||
) == true || media.synonyms.any { it.contains(search, ignoreCase = true) } ||
|
) == true || media.synonyms.any { it.contains(search, ignoreCase = true) } ||
|
||||||
media.nameRomaji.contains(
|
media.nameRomaji.contains(
|
||||||
search,
|
search,
|
||||||
ignoreCase = true
|
ignoreCase = true
|
||||||
)
|
)
|
||||||
} as ArrayList<Media>
|
} as ArrayList<Media>
|
||||||
}.toMutableMap()
|
}.toMutableMap()
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import ani.dantotsu.currContext
|
||||||
import ani.dantotsu.media.Media
|
import ani.dantotsu.media.Media
|
||||||
import ani.dantotsu.media.MediaNameAdapter
|
import ani.dantotsu.media.MediaNameAdapter
|
||||||
import ani.dantotsu.media.Selected
|
import ani.dantotsu.media.Selected
|
||||||
import ani.dantotsu.media.emptyMedia
|
|
||||||
import ani.dantotsu.parsers.AnimeParser
|
import ani.dantotsu.parsers.AnimeParser
|
||||||
import ani.dantotsu.parsers.AnimeSources
|
import ani.dantotsu.parsers.AnimeSources
|
||||||
import ani.dantotsu.parsers.BaseParser
|
import ani.dantotsu.parsers.BaseParser
|
||||||
|
@ -63,11 +62,11 @@ class SubscriptionHelper {
|
||||||
val show = parser.loadSavedShowResponse(subscribeMedia.id)
|
val show = parser.loadSavedShowResponse(subscribeMedia.id)
|
||||||
?: forceLoadShowResponse(subscribeMedia, selected, parser)
|
?: forceLoadShowResponse(subscribeMedia, selected, parser)
|
||||||
?: throw Exception(
|
?: throw Exception(
|
||||||
currContext()?.getString(
|
currContext()?.getString(
|
||||||
R.string.failed_to_load_data,
|
R.string.failed_to_load_data,
|
||||||
subscribeMedia.id
|
subscribeMedia.id
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
show.sAnime?.let {
|
show.sAnime?.let {
|
||||||
parser.getLatestEpisode(
|
parser.getLatestEpisode(
|
||||||
show.link, show.extra,
|
show.link, show.extra,
|
||||||
|
@ -103,11 +102,11 @@ class SubscriptionHelper {
|
||||||
val show = parser.loadSavedShowResponse(subscribeMedia.id)
|
val show = parser.loadSavedShowResponse(subscribeMedia.id)
|
||||||
?: forceLoadShowResponse(subscribeMedia, selected, parser)
|
?: forceLoadShowResponse(subscribeMedia, selected, parser)
|
||||||
?: throw Exception(
|
?: throw Exception(
|
||||||
currContext()?.getString(
|
currContext()?.getString(
|
||||||
R.string.failed_to_load_data,
|
R.string.failed_to_load_data,
|
||||||
subscribeMedia.id
|
subscribeMedia.id
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
show.sManga?.let {
|
show.sManga?.let {
|
||||||
parser.getLatestChapter(
|
parser.getLatestChapter(
|
||||||
show.link, show.extra,
|
show.link, show.extra,
|
||||||
|
@ -123,7 +122,11 @@ class SubscriptionHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun forceLoadShowResponse(subscribeMedia: SubscribeMedia, selected: Selected, parser: BaseParser): ShowResponse? {
|
private suspend fun forceLoadShowResponse(
|
||||||
|
subscribeMedia: SubscribeMedia,
|
||||||
|
selected: Selected,
|
||||||
|
parser: BaseParser
|
||||||
|
): ShowResponse? {
|
||||||
val tempMedia = Media(
|
val tempMedia = Media(
|
||||||
id = subscribeMedia.id,
|
id = subscribeMedia.id,
|
||||||
name = null,
|
name = null,
|
||||||
|
|
|
@ -127,8 +127,10 @@ class SubscriptionNotificationTask : Task {
|
||||||
banner = media.banner
|
banner = media.banner
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
PrefManager.setVal(PrefName.UnreadCommentNotifications,
|
PrefManager.setVal(
|
||||||
PrefManager.getVal<Int>(PrefName.UnreadCommentNotifications) + 1)
|
PrefName.UnreadCommentNotifications,
|
||||||
|
PrefManager.getVal<Int>(PrefName.UnreadCommentNotifications) + 1
|
||||||
|
)
|
||||||
val notification = createNotification(
|
val notification = createNotification(
|
||||||
context.applicationContext,
|
context.applicationContext,
|
||||||
media,
|
media,
|
||||||
|
@ -240,7 +242,7 @@ class SubscriptionNotificationTask : Task {
|
||||||
if (newStore.size >= 100) {
|
if (newStore.size >= 100) {
|
||||||
newStore.remove(newStore.minByOrNull { it.time })
|
newStore.remove(newStore.minByOrNull { it.time })
|
||||||
}
|
}
|
||||||
if (newStore.any { it.title == notification.title && it.content == notification.content}) {
|
if (newStore.any { it.title == notification.title && it.content == notification.content }) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
|
@ -37,7 +36,7 @@ class OfflineFragment : Fragment() {
|
||||||
PrefManager.setVal(PrefName.OfflineMode, false)
|
PrefManager.setVal(PrefName.OfflineMode, false)
|
||||||
startMainActivity(requireActivity())
|
startMainActivity(requireActivity())
|
||||||
} else {
|
} else {
|
||||||
if (isOnline(requireContext()) ) {
|
if (isOnline(requireContext())) {
|
||||||
startMainActivity(requireActivity())
|
startMainActivity(requireActivity())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import kotlinx.serialization.json.JsonArray
|
||||||
import kotlinx.serialization.json.decodeFromJsonElement
|
import kotlinx.serialization.json.decodeFromJsonElement
|
||||||
|
|
||||||
object Anify {
|
object Anify {
|
||||||
suspend fun fetchAndParseMetadata(id :Int): Map<String, Episode> {
|
suspend fun fetchAndParseMetadata(id: Int): Map<String, Episode> {
|
||||||
val response = client.get("https://anify.eltik.cc/content-metadata/$id")
|
val response = client.get("https://anify.eltik.cc/content-metadata/$id")
|
||||||
.parsed<JsonArray>().map {
|
.parsed<JsonArray>().map {
|
||||||
Mapper.json.decodeFromJsonElement<AnifyElement>(it)
|
Mapper.json.decodeFromJsonElement<AnifyElement>(it)
|
||||||
|
@ -24,15 +24,16 @@ object Anify {
|
||||||
)
|
)
|
||||||
} ?: emptyMap()
|
} ?: emptyMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class AnifyElement (
|
data class AnifyElement(
|
||||||
@SerialName("providerId")
|
@SerialName("providerId")
|
||||||
val providerID: String? = null,
|
val providerID: String? = null,
|
||||||
val data: List<Datum>? = null
|
val data: List<Datum>? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Datum (
|
data class Datum(
|
||||||
val id: String? = null,
|
val id: String? = null,
|
||||||
val description: String? = null,
|
val description: String? = null,
|
||||||
val hasDub: Boolean? = null,
|
val hasDub: Boolean? = null,
|
||||||
|
|
|
@ -13,132 +13,132 @@ import android.util.AttributeSet
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
|
||||||
class Xubtitle
|
class Xubtitle
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
constructor(
|
constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
attrs: AttributeSet? = null,
|
attrs: AttributeSet? = null,
|
||||||
defStyleAttr: Int = 0,
|
defStyleAttr: Int = 0,
|
||||||
) : AppCompatTextView(context, attrs, defStyleAttr) {
|
) : AppCompatTextView(context, attrs, defStyleAttr) {
|
||||||
private var outlineThickness: Float = 0f
|
private var outlineThickness: Float = 0f
|
||||||
private var effectColor: Int = currentTextColor
|
private var effectColor: Int = currentTextColor
|
||||||
private var currentEffect: Effect = Effect.NONE
|
private var currentEffect: Effect = Effect.NONE
|
||||||
|
|
||||||
private val shadowPaint = Paint().apply { isAntiAlias = true }
|
private val shadowPaint = Paint().apply { isAntiAlias = true }
|
||||||
private val outlinePaint = Paint().apply { isAntiAlias = true }
|
private val outlinePaint = Paint().apply { isAntiAlias = true }
|
||||||
private var shineShader: Shader? = null
|
private var shineShader: Shader? = null
|
||||||
|
|
||||||
enum class Effect {
|
enum class Effect {
|
||||||
NONE,
|
NONE,
|
||||||
OUTLINE,
|
OUTLINE,
|
||||||
SHINE,
|
SHINE,
|
||||||
DROP_SHADOW,
|
DROP_SHADOW,
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
override fun onDraw(canvas: Canvas) {
|
||||||
val text = text.toString()
|
val text = text.toString()
|
||||||
val textPaint =
|
val textPaint =
|
||||||
TextPaint(paint).apply {
|
TextPaint(paint).apply {
|
||||||
color = currentTextColor
|
color = currentTextColor
|
||||||
}
|
}
|
||||||
val staticLayout =
|
val staticLayout =
|
||||||
StaticLayout.Builder
|
StaticLayout.Builder
|
||||||
.obtain(text, 0, text.length, textPaint, width)
|
.obtain(text, 0, text.length, textPaint, width)
|
||||||
.setAlignment(Layout.Alignment.ALIGN_CENTER)
|
.setAlignment(Layout.Alignment.ALIGN_CENTER)
|
||||||
.setLineSpacing(0f, 1f)
|
.setLineSpacing(0f, 1f)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
when (currentEffect) {
|
when (currentEffect) {
|
||||||
Effect.OUTLINE -> {
|
Effect.OUTLINE -> {
|
||||||
textPaint.style = Paint.Style.STROKE
|
textPaint.style = Paint.Style.STROKE
|
||||||
textPaint.strokeWidth = outlineThickness
|
textPaint.strokeWidth = outlineThickness
|
||||||
textPaint.color = effectColor
|
textPaint.color = effectColor
|
||||||
|
|
||||||
staticLayout.draw(canvas)
|
staticLayout.draw(canvas)
|
||||||
|
|
||||||
textPaint.style = Paint.Style.FILL
|
textPaint.style = Paint.Style.FILL
|
||||||
textPaint.color = currentTextColor
|
textPaint.color = currentTextColor
|
||||||
staticLayout.draw(canvas)
|
staticLayout.draw(canvas)
|
||||||
}
|
}
|
||||||
|
|
||||||
Effect.DROP_SHADOW -> {
|
Effect.DROP_SHADOW -> {
|
||||||
setLayerType(LAYER_TYPE_SOFTWARE, null)
|
setLayerType(LAYER_TYPE_SOFTWARE, null)
|
||||||
textPaint.setShadowLayer(outlineThickness, 4f, 4f, effectColor)
|
textPaint.setShadowLayer(outlineThickness, 4f, 4f, effectColor)
|
||||||
|
|
||||||
staticLayout.draw(canvas)
|
staticLayout.draw(canvas)
|
||||||
|
|
||||||
textPaint.clearShadowLayer()
|
textPaint.clearShadowLayer()
|
||||||
}
|
}
|
||||||
|
|
||||||
Effect.SHINE -> {
|
Effect.SHINE -> {
|
||||||
val shadowShader =
|
val shadowShader =
|
||||||
LinearGradient(
|
LinearGradient(
|
||||||
0f,
|
0f,
|
||||||
0f,
|
0f,
|
||||||
width.toFloat(),
|
width.toFloat(),
|
||||||
height.toFloat(),
|
height.toFloat(),
|
||||||
intArrayOf(Color.WHITE, effectColor, Color.BLACK),
|
intArrayOf(Color.WHITE, effectColor, Color.BLACK),
|
||||||
null,
|
null,
|
||||||
Shader.TileMode.CLAMP,
|
Shader.TileMode.CLAMP,
|
||||||
)
|
|
||||||
|
|
||||||
val shadowPaint =
|
|
||||||
Paint().apply {
|
|
||||||
isAntiAlias = true
|
|
||||||
style = Paint.Style.FILL
|
|
||||||
textSize = textPaint.textSize
|
|
||||||
typeface = textPaint.typeface
|
|
||||||
shader = shadowShader
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.drawText(
|
|
||||||
text,
|
|
||||||
x + 4f, // Shadow offset
|
|
||||||
y + 4f,
|
|
||||||
shadowPaint,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val shader =
|
val shadowPaint =
|
||||||
LinearGradient(
|
Paint().apply {
|
||||||
0f,
|
isAntiAlias = true
|
||||||
0f,
|
style = Paint.Style.FILL
|
||||||
width.toFloat(),
|
textSize = textPaint.textSize
|
||||||
height.toFloat(),
|
typeface = textPaint.typeface
|
||||||
intArrayOf(effectColor, Color.WHITE, Color.WHITE),
|
shader = shadowShader
|
||||||
null,
|
}
|
||||||
Shader.TileMode.CLAMP,
|
|
||||||
)
|
|
||||||
textPaint.shader = shader
|
|
||||||
staticLayout.draw(canvas)
|
|
||||||
textPaint.shader = null
|
|
||||||
}
|
|
||||||
|
|
||||||
Effect.NONE -> {
|
canvas.drawText(
|
||||||
staticLayout.draw(canvas)
|
text,
|
||||||
}
|
x + 4f, // Shadow offset
|
||||||
|
y + 4f,
|
||||||
|
shadowPaint,
|
||||||
|
)
|
||||||
|
|
||||||
|
val shader =
|
||||||
|
LinearGradient(
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
width.toFloat(),
|
||||||
|
height.toFloat(),
|
||||||
|
intArrayOf(effectColor, Color.WHITE, Color.WHITE),
|
||||||
|
null,
|
||||||
|
Shader.TileMode.CLAMP,
|
||||||
|
)
|
||||||
|
textPaint.shader = shader
|
||||||
|
staticLayout.draw(canvas)
|
||||||
|
textPaint.shader = null
|
||||||
|
}
|
||||||
|
|
||||||
|
Effect.NONE -> {
|
||||||
|
staticLayout.draw(canvas)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applyOutline(
|
|
||||||
color: Int,
|
|
||||||
outlineThickness: Float,
|
|
||||||
) {
|
|
||||||
this.effectColor = color
|
|
||||||
this.outlineThickness = outlineThickness
|
|
||||||
currentEffect = Effect.OUTLINE
|
|
||||||
}
|
|
||||||
|
|
||||||
// Too hard for me to figure it out
|
|
||||||
fun applyShineEffect(color: Int) {
|
|
||||||
this.effectColor = color
|
|
||||||
currentEffect = Effect.SHINE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun applyDropShadow(
|
|
||||||
color: Int,
|
|
||||||
outlineThickness: Float,
|
|
||||||
) {
|
|
||||||
this.effectColor = color
|
|
||||||
this.outlineThickness = outlineThickness
|
|
||||||
currentEffect = Effect.DROP_SHADOW
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun applyOutline(
|
||||||
|
color: Int,
|
||||||
|
outlineThickness: Float,
|
||||||
|
) {
|
||||||
|
this.effectColor = color
|
||||||
|
this.outlineThickness = outlineThickness
|
||||||
|
currentEffect = Effect.OUTLINE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Too hard for me to figure it out
|
||||||
|
fun applyShineEffect(color: Int) {
|
||||||
|
this.effectColor = color
|
||||||
|
currentEffect = Effect.SHINE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun applyDropShadow(
|
||||||
|
color: Int,
|
||||||
|
outlineThickness: Float,
|
||||||
|
) {
|
||||||
|
this.effectColor = color
|
||||||
|
this.outlineThickness = outlineThickness
|
||||||
|
currentEffect = Effect.DROP_SHADOW
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package ani.dantotsu.parsers
|
package ani.dantotsu.parsers
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
|
@ -6,7 +5,6 @@ import ani.dantotsu.FileUrl
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.currContext
|
import ani.dantotsu.currContext
|
||||||
import ani.dantotsu.media.Media
|
import ani.dantotsu.media.Media
|
||||||
import ani.dantotsu.okHttpClient
|
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.util.Logger
|
import ani.dantotsu.util.Logger
|
||||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||||
|
|
|
@ -168,7 +168,7 @@ class ExtensionTestItem(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val serverResultStart = System.currentTimeMillis()
|
val serverResultStart = System.currentTimeMillis()
|
||||||
val serverResult = extension.loadImages("", chapterResult.first().sChapter)
|
val serverResult = extension.loadImages("", chapterResult.first().sChapter)
|
||||||
serverResultData.time = (System.currentTimeMillis() - serverResultStart).toInt()
|
serverResultData.time = (System.currentTimeMillis() - serverResultStart).toInt()
|
||||||
serverResultData.size = serverResult.size
|
serverResultData.size = serverResult.size
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
|
@ -266,8 +266,10 @@ class ExtensionTestItem(
|
||||||
)
|
)
|
||||||
binding.searchResultText.isVisible = true
|
binding.searchResultText.isVisible = true
|
||||||
if (searchResultData.size == 0) {
|
if (searchResultData.size == 0) {
|
||||||
val text = context.getString(R.string.title_search_test,
|
val text = context.getString(
|
||||||
context.getString(R.string.no_results_found))
|
R.string.title_search_test,
|
||||||
|
context.getString(R.string.no_results_found)
|
||||||
|
)
|
||||||
binding.searchResultText.text = text
|
binding.searchResultText.text = text
|
||||||
binding.searchResultText.setCompoundDrawablesWithIntrinsicBounds(
|
binding.searchResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
R.drawable.ic_circle_cancel, 0, 0, 0
|
R.drawable.ic_circle_cancel, 0, 0, 0
|
||||||
|
@ -277,8 +279,10 @@ class ExtensionTestItem(
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val text = context.getString(R.string.title_search_test,
|
val text = context.getString(
|
||||||
context.getString(R.string.results_found, searchResultData.size.toString()))
|
R.string.title_search_test,
|
||||||
|
context.getString(R.string.results_found, searchResultData.size.toString())
|
||||||
|
)
|
||||||
binding.searchResultText.text = text + "\n${searchResultData.time}ms"
|
binding.searchResultText.text = text + "\n${searchResultData.time}ms"
|
||||||
binding.searchResultText.setCompoundDrawablesWithIntrinsicBounds(
|
binding.searchResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
R.drawable.ic_circle_check, 0, 0, 0
|
R.drawable.ic_circle_check, 0, 0, 0
|
||||||
|
@ -297,13 +301,21 @@ class ExtensionTestItem(
|
||||||
)
|
)
|
||||||
binding.episodeResultText.isVisible = true
|
binding.episodeResultText.isVisible = true
|
||||||
if (episodeResultData.size == 0) {
|
if (episodeResultData.size == 0) {
|
||||||
val text = when(extensionType) {
|
val text = when (extensionType) {
|
||||||
"anime" -> context.getString(R.string.episode_search_test,
|
"anime" -> context.getString(
|
||||||
context.getString(R.string.no_results_found))
|
R.string.episode_search_test,
|
||||||
"manga" -> context.getString(R.string.chapter_search_test,
|
context.getString(R.string.no_results_found)
|
||||||
context.getString(R.string.no_results_found))
|
)
|
||||||
else -> context.getString(R.string.book_search_test,
|
|
||||||
context.getString(R.string.no_results_found))
|
"manga" -> context.getString(
|
||||||
|
R.string.chapter_search_test,
|
||||||
|
context.getString(R.string.no_results_found)
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> context.getString(
|
||||||
|
R.string.book_search_test,
|
||||||
|
context.getString(R.string.no_results_found)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
binding.episodeResultText.text = text
|
binding.episodeResultText.text = text
|
||||||
binding.episodeResultText.setCompoundDrawablesWithIntrinsicBounds(
|
binding.episodeResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
@ -314,13 +326,21 @@ class ExtensionTestItem(
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val text = when(extensionType) {
|
val text = when (extensionType) {
|
||||||
"anime" -> context.getString(R.string.episode_search_test,
|
"anime" -> context.getString(
|
||||||
context.getString(R.string.results_found, episodeResultData.size.toString()))
|
R.string.episode_search_test,
|
||||||
"manga" -> context.getString(R.string.chapter_search_test,
|
context.getString(R.string.results_found, episodeResultData.size.toString())
|
||||||
context.getString(R.string.results_found, episodeResultData.size.toString()))
|
)
|
||||||
else -> context.getString(R.string.book_search_test,
|
|
||||||
context.getString(R.string.results_found, episodeResultData.size.toString()))
|
"manga" -> context.getString(
|
||||||
|
R.string.chapter_search_test,
|
||||||
|
context.getString(R.string.results_found, episodeResultData.size.toString())
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> context.getString(
|
||||||
|
R.string.book_search_test,
|
||||||
|
context.getString(R.string.results_found, episodeResultData.size.toString())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
binding.episodeResultText.text = text + "\n${episodeResultData.time}ms"
|
binding.episodeResultText.text = text + "\n${episodeResultData.time}ms"
|
||||||
binding.episodeResultText.setCompoundDrawablesWithIntrinsicBounds(
|
binding.episodeResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
@ -348,13 +368,21 @@ class ExtensionTestItem(
|
||||||
)
|
)
|
||||||
binding.serverResultText.isVisible = true
|
binding.serverResultText.isVisible = true
|
||||||
if (serverResultData.size == 0) {
|
if (serverResultData.size == 0) {
|
||||||
val text = when(extensionType) {
|
val text = when (extensionType) {
|
||||||
"anime" -> context.getString(R.string.video_search_test,
|
"anime" -> context.getString(
|
||||||
context.getString(R.string.no_results_found))
|
R.string.video_search_test,
|
||||||
"manga" -> context.getString(R.string.image_search_test,
|
context.getString(R.string.no_results_found)
|
||||||
context.getString(R.string.no_results_found))
|
)
|
||||||
else -> context.getString(R.string.book_search_test,
|
|
||||||
context.getString(R.string.no_results_found))
|
"manga" -> context.getString(
|
||||||
|
R.string.image_search_test,
|
||||||
|
context.getString(R.string.no_results_found)
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> context.getString(
|
||||||
|
R.string.book_search_test,
|
||||||
|
context.getString(R.string.no_results_found)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
binding.serverResultText.text = text + "\n${serverResultData.time}ms"
|
binding.serverResultText.text = text + "\n${serverResultData.time}ms"
|
||||||
binding.serverResultText.setCompoundDrawablesWithIntrinsicBounds(
|
binding.serverResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
@ -365,13 +393,21 @@ class ExtensionTestItem(
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val text = when(extensionType) {
|
val text = when (extensionType) {
|
||||||
"anime" -> context.getString(R.string.video_search_test,
|
"anime" -> context.getString(
|
||||||
context.getString(R.string.results_found, serverResultData.size.toString()))
|
R.string.video_search_test,
|
||||||
"manga" -> context.getString(R.string.image_search_test,
|
context.getString(R.string.results_found, serverResultData.size.toString())
|
||||||
context.getString(R.string.results_found, serverResultData.size.toString()))
|
)
|
||||||
else -> context.getString(R.string.book_search_test,
|
|
||||||
context.getString(R.string.results_found, serverResultData.size.toString()))
|
"manga" -> context.getString(
|
||||||
|
R.string.image_search_test,
|
||||||
|
context.getString(R.string.results_found, serverResultData.size.toString())
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> context.getString(
|
||||||
|
R.string.book_search_test,
|
||||||
|
context.getString(R.string.results_found, serverResultData.size.toString())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
binding.serverResultText.text = text
|
binding.serverResultText.text = text
|
||||||
binding.serverResultText.setCompoundDrawablesWithIntrinsicBounds(
|
binding.serverResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
|
|
@ -110,7 +110,7 @@ class ExtensionTestSettingsBottomDialog : BottomSheetDialogFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupAdapter() {
|
private fun setupAdapter() {
|
||||||
val namesAndUrls: Map<String,Drawable?> = when (extensionType) {
|
val namesAndUrls: Map<String, Drawable?> = when (extensionType) {
|
||||||
"anime" -> animeExtension.installedExtensionsFlow.value.associate { it.name to it.icon }
|
"anime" -> animeExtension.installedExtensionsFlow.value.associate { it.name to it.icon }
|
||||||
"manga" -> mangaExtensions.installedExtensionsFlow.value.associate { it.name to it.icon }
|
"manga" -> mangaExtensions.installedExtensionsFlow.value.associate { it.name to it.icon }
|
||||||
"novel" -> novelExtensions.installedExtensionsFlow.value.associate { it.name to it.icon }
|
"novel" -> novelExtensions.installedExtensionsFlow.value.associate { it.name to it.icon }
|
||||||
|
|
|
@ -33,7 +33,7 @@ class OfflineMangaParser : MangaParser() {
|
||||||
directory.listFiles().forEach {
|
directory.listFiles().forEach {
|
||||||
val scanlator = downloadManager.mangaDownloadedTypes.find { items ->
|
val scanlator = downloadManager.mangaDownloadedTypes.find { items ->
|
||||||
items.titleName == mangaLink &&
|
items.titleName == mangaLink &&
|
||||||
items.chapterName == it.name
|
items.chapterName == it.name
|
||||||
}?.scanlator ?: "Unknown"
|
}?.scanlator ?: "Unknown"
|
||||||
if (it.isDirectory) {
|
if (it.isDirectory) {
|
||||||
val chapter = MangaChapter(
|
val chapter = MangaChapter(
|
||||||
|
|
|
@ -73,6 +73,7 @@ class ParserTestActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"manga" -> {
|
"manga" -> {
|
||||||
ExtensionTestSettingsBottomDialog.extensionsToTest.forEach { name ->
|
ExtensionTestSettingsBottomDialog.extensionsToTest.forEach { name ->
|
||||||
val extension =
|
val extension =
|
||||||
|
@ -89,6 +90,7 @@ class ParserTestActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"novel" -> {
|
"novel" -> {
|
||||||
ExtensionTestSettingsBottomDialog.extensionsToTest.forEach { name ->
|
ExtensionTestSettingsBottomDialog.extensionsToTest.forEach { name ->
|
||||||
val extension =
|
val extension =
|
||||||
|
|
|
@ -120,8 +120,10 @@ class NovelExtensionManager(private val context: Context) {
|
||||||
* @param extension The anime extension to be installed.
|
* @param extension The anime extension to be installed.
|
||||||
*/
|
*/
|
||||||
fun installExtension(extension: NovelExtension.Available): Observable<InstallStep> {
|
fun installExtension(extension: NovelExtension.Available): Observable<InstallStep> {
|
||||||
return installer.downloadAndInstall(api.getNovelApkUrl(extension), extension.pkgName,
|
return installer.downloadAndInstall(
|
||||||
extension.name, MediaType.NOVEL)
|
api.getNovelApkUrl(extension), extension.pkgName,
|
||||||
|
extension.name, MediaType.NOVEL
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -53,7 +53,8 @@ class ChartBuilder {
|
||||||
scrollPos: Float? = null,
|
scrollPos: Float? = null,
|
||||||
normalize: Boolean = false
|
normalize: Boolean = false
|
||||||
): AAOptions {
|
): AAOptions {
|
||||||
val primaryColor = context.getThemeColor(com.google.android.material.R.attr.colorPrimary)
|
val primaryColor =
|
||||||
|
context.getThemeColor(com.google.android.material.R.attr.colorPrimary)
|
||||||
var chartType = passedChartType
|
var chartType = passedChartType
|
||||||
var aaChartType = passedAaChartType
|
var aaChartType = passedAaChartType
|
||||||
var categories = passedCategories
|
var categories = passedCategories
|
||||||
|
@ -303,7 +304,8 @@ class ChartBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setColors(aaOptions: AAOptions, context: Context) {
|
private fun setColors(aaOptions: AAOptions, context: Context) {
|
||||||
val backgroundColor = context.getThemeColor(com.google.android.material.R.attr.colorSurfaceVariant)
|
val backgroundColor =
|
||||||
|
context.getThemeColor(com.google.android.material.R.attr.colorSurfaceVariant)
|
||||||
val backgroundStyle = AAStyle().color(
|
val backgroundStyle = AAStyle().color(
|
||||||
AAColor.rgbaColor(
|
AAColor.rgbaColor(
|
||||||
Color.red(backgroundColor),
|
Color.red(backgroundColor),
|
||||||
|
@ -312,7 +314,8 @@ class ChartBuilder {
|
||||||
1f
|
1f
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val colorOnBackground = context.getThemeColor(com.google.android.material.R.attr.colorOnSurface)
|
val colorOnBackground =
|
||||||
|
context.getThemeColor(com.google.android.material.R.attr.colorOnSurface)
|
||||||
val onBackgroundStyle = AAStyle().color(
|
val onBackgroundStyle = AAStyle().color(
|
||||||
AAColor.rgbaColor(
|
AAColor.rgbaColor(
|
||||||
Color.red(colorOnBackground),
|
Color.red(colorOnBackground),
|
||||||
|
|
|
@ -36,10 +36,10 @@ class FollowerItem(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLayout(): Int {
|
override fun getLayout(): Int {
|
||||||
return if(grid) R.layout.item_follower_grid else R.layout.item_follower
|
return if (grid) R.layout.item_follower_grid else R.layout.item_follower
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initializeViewBinding(view: View): ViewBinding {
|
override fun initializeViewBinding(view: View): ViewBinding {
|
||||||
return if(grid) ItemFollowerGridBinding.bind(view) else ItemFollowerBinding.bind(view)
|
return if (grid) ItemFollowerGridBinding.bind(view) else ItemFollowerBinding.bind(view)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -156,17 +156,28 @@ class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListene
|
||||||
openLinkInBrowser(getString(R.string.anilist_link, user.name))
|
openLinkInBrowser(getString(R.string.anilist_link, user.name))
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_share_profile -> {
|
R.id.action_share_profile -> {
|
||||||
val shareIntent = Intent(Intent.ACTION_SEND)
|
val shareIntent = Intent(Intent.ACTION_SEND)
|
||||||
shareIntent.type = "text/plain"
|
shareIntent.type = "text/plain"
|
||||||
shareIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.anilist_link, user.name))
|
shareIntent.putExtra(
|
||||||
startActivity(Intent.createChooser(shareIntent, "Share Profile"))
|
Intent.EXTRA_TEXT,
|
||||||
|
getString(R.string.anilist_link, user.name)
|
||||||
|
)
|
||||||
|
startActivity(
|
||||||
|
Intent.createChooser(
|
||||||
|
shareIntent,
|
||||||
|
"Share Profile"
|
||||||
|
)
|
||||||
|
)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_copy_user_id -> {
|
R.id.action_copy_user_id -> {
|
||||||
copyToClipboard(user.id.toString(), true)
|
copyToClipboard(user.id.toString(), true)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,11 @@ class UsersAdapter(private val user: MutableList<User>, private val grid: Boolea
|
||||||
parent,
|
parent,
|
||||||
false
|
false
|
||||||
) else
|
) else
|
||||||
ItemFollowerBinding.inflate(
|
ItemFollowerBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
parent,
|
parent,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ import ani.dantotsu.profile.User
|
||||||
import ani.dantotsu.profile.UsersDialogFragment
|
import ani.dantotsu.profile.UsersDialogFragment
|
||||||
import ani.dantotsu.setAnimation
|
import ani.dantotsu.setAnimation
|
||||||
import ani.dantotsu.snackString
|
import ani.dantotsu.snackString
|
||||||
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
|
|
||||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||||
|
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
|
||||||
import com.xwray.groupie.GroupieAdapter
|
import com.xwray.groupie.GroupieAdapter
|
||||||
import com.xwray.groupie.viewbinding.BindableItem
|
import com.xwray.groupie.viewbinding.BindableItem
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
@ -52,14 +52,19 @@ class ActivityItem(
|
||||||
}
|
}
|
||||||
binding.activityRepliesContainer.setOnClickListener {
|
binding.activityRepliesContainer.setOnClickListener {
|
||||||
RepliesBottomDialog.newInstance(activity.id)
|
RepliesBottomDialog.newInstance(activity.id)
|
||||||
.show((context as FragmentActivity).supportFragmentManager, "replies")
|
.show((context as FragmentActivity).supportFragmentManager, "replies")
|
||||||
}
|
}
|
||||||
binding.replyCount.text = activity.replyCount.toString()
|
binding.replyCount.text = activity.replyCount.toString()
|
||||||
binding.activityReplies.setColorFilter(ContextCompat.getColor(binding.root.context, R.color.bg_opp))
|
binding.activityReplies.setColorFilter(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
binding.root.context,
|
||||||
|
R.color.bg_opp
|
||||||
|
)
|
||||||
|
)
|
||||||
binding.activityLikeContainer.setOnLongClickListener {
|
binding.activityLikeContainer.setOnLongClickListener {
|
||||||
UsersDialogFragment().apply {
|
UsersDialogFragment().apply {
|
||||||
userList(userList)
|
userList(userList)
|
||||||
show((context as FragmentActivity).supportFragmentManager, "dialog")
|
show((context as FragmentActivity).supportFragmentManager, "dialog")
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -84,7 +89,8 @@ class ActivityItem(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.activityDelete.isVisible = activity.userId == Anilist.userid || activity.messenger?.id == Anilist.userid
|
binding.activityDelete.isVisible =
|
||||||
|
activity.userId == Anilist.userid || activity.messenger?.id == Anilist.userid
|
||||||
binding.activityDelete.setOnClickListener {
|
binding.activityDelete.setOnClickListener {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val res = Anilist.mutation.deleteActivity(activity.id)
|
val res = Anilist.mutation.deleteActivity(activity.id)
|
||||||
|
@ -161,7 +167,8 @@ class ActivityItem(
|
||||||
"MessageActivity" -> {
|
"MessageActivity" -> {
|
||||||
binding.activityBannerContainer.visibility = View.GONE
|
binding.activityBannerContainer.visibility = View.GONE
|
||||||
binding.activityContent.visibility = View.VISIBLE
|
binding.activityContent.visibility = View.VISIBLE
|
||||||
binding.activityPrivate.visibility = if (activity.isPrivate == true) View.VISIBLE else View.GONE
|
binding.activityPrivate.visibility =
|
||||||
|
if (activity.isPrivate == true) View.VISIBLE else View.GONE
|
||||||
if (!(context as android.app.Activity).isDestroyed) {
|
if (!(context as android.app.Activity).isDestroyed) {
|
||||||
val markwon = buildMarkwon(context, false)
|
val markwon = buildMarkwon(context, false)
|
||||||
markwon.setMarkdown(
|
markwon.setMarkdown(
|
||||||
|
|
|
@ -14,8 +14,8 @@ import ani.dantotsu.loadImage
|
||||||
import ani.dantotsu.profile.User
|
import ani.dantotsu.profile.User
|
||||||
import ani.dantotsu.profile.UsersDialogFragment
|
import ani.dantotsu.profile.UsersDialogFragment
|
||||||
import ani.dantotsu.snackString
|
import ani.dantotsu.snackString
|
||||||
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
|
|
||||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||||
|
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
|
||||||
import com.xwray.groupie.GroupieAdapter
|
import com.xwray.groupie.GroupieAdapter
|
||||||
import com.xwray.groupie.viewbinding.BindableItem
|
import com.xwray.groupie.viewbinding.BindableItem
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
@ -26,7 +26,7 @@ import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class ActivityReplyItem(
|
class ActivityReplyItem(
|
||||||
private val reply: ActivityReply,
|
private val reply: ActivityReply,
|
||||||
private val parentId : Int,
|
private val parentId: Int,
|
||||||
private val fragActivity: FragmentActivity,
|
private val fragActivity: FragmentActivity,
|
||||||
private val parentAdapter: GroupieAdapter,
|
private val parentAdapter: GroupieAdapter,
|
||||||
private val clickCallback: (Int, type: String) -> Unit,
|
private val clickCallback: (Int, type: String) -> Unit,
|
||||||
|
|
|
@ -1,26 +1,21 @@
|
||||||
package ani.dantotsu.profile.activity
|
package ani.dantotsu.profile.activity
|
||||||
|
|
||||||
import android.content.res.Configuration
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.core.view.updateMargins
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.databinding.ActivityFeedBinding
|
|
||||||
import ani.dantotsu.databinding.ActivityNotificationBinding
|
import ani.dantotsu.databinding.ActivityNotificationBinding
|
||||||
import ani.dantotsu.initActivity
|
import ani.dantotsu.initActivity
|
||||||
import ani.dantotsu.navBarHeight
|
import ani.dantotsu.navBarHeight
|
||||||
|
import ani.dantotsu.profile.activity.ActivityFragment.Companion.ActivityType
|
||||||
import ani.dantotsu.statusBarHeight
|
import ani.dantotsu.statusBarHeight
|
||||||
import ani.dantotsu.themes.ThemeManager
|
import ani.dantotsu.themes.ThemeManager
|
||||||
import ani.dantotsu.profile.activity.ActivityFragment.Companion.ActivityType
|
|
||||||
import ani.dantotsu.profile.notification.NotificationActivity
|
|
||||||
import nl.joery.animatedbottombar.AnimatedBottomBar
|
import nl.joery.animatedbottombar.AnimatedBottomBar
|
||||||
|
|
||||||
class FeedActivity : AppCompatActivity() {
|
class FeedActivity : AppCompatActivity() {
|
||||||
|
@ -50,9 +45,12 @@ class FeedActivity : AppCompatActivity() {
|
||||||
|
|
||||||
binding.notificationBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
|
binding.notificationBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
|
||||||
val getOne = intent.getIntExtra("activityId", -1)
|
val getOne = intent.getIntExtra("activityId", -1)
|
||||||
if (getOne != -1) { navBar.visibility = View.GONE }
|
if (getOne != -1) {
|
||||||
|
navBar.visibility = View.GONE
|
||||||
|
}
|
||||||
binding.notificationViewPager.isUserInputEnabled = false
|
binding.notificationViewPager.isUserInputEnabled = false
|
||||||
binding.notificationViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle, getOne)
|
binding.notificationViewPager.adapter =
|
||||||
|
ViewPagerAdapter(supportFragmentManager, lifecycle, getOne)
|
||||||
binding.notificationViewPager.setOffscreenPageLimit(4)
|
binding.notificationViewPager.setOffscreenPageLimit(4)
|
||||||
binding.notificationViewPager.setCurrentItem(selected, false)
|
binding.notificationViewPager.setCurrentItem(selected, false)
|
||||||
navBar.selectTabAt(selected)
|
navBar.selectTabAt(selected)
|
||||||
|
@ -83,7 +81,11 @@ class FeedActivity : AppCompatActivity() {
|
||||||
|
|
||||||
override fun createFragment(position: Int): Fragment {
|
override fun createFragment(position: Int): Fragment {
|
||||||
return when (position) {
|
return when (position) {
|
||||||
0 -> ActivityFragment.newInstance(if (activityId != -1) ActivityType.ONE else ActivityType.USER, activityId = activityId)
|
0 -> ActivityFragment.newInstance(
|
||||||
|
if (activityId != -1) ActivityType.ONE else ActivityType.USER,
|
||||||
|
activityId = activityId
|
||||||
|
)
|
||||||
|
|
||||||
else -> ActivityFragment.newInstance(ActivityType.GLOBAL)
|
else -> ActivityFragment.newInstance(ActivityType.GLOBAL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,17 +9,20 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
|
||||||
import ani.dantotsu.databinding.ActivityNotificationBinding
|
import ani.dantotsu.databinding.ActivityNotificationBinding
|
||||||
import ani.dantotsu.initActivity
|
import ani.dantotsu.initActivity
|
||||||
import ani.dantotsu.navBarHeight
|
import ani.dantotsu.navBarHeight
|
||||||
|
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.COMMENT
|
||||||
|
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.MEDIA
|
||||||
|
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.ONE
|
||||||
|
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.SUBSCRIPTION
|
||||||
|
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.USER
|
||||||
|
import ani.dantotsu.profile.notification.NotificationFragment.Companion.newInstance
|
||||||
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.statusBarHeight
|
import ani.dantotsu.statusBarHeight
|
||||||
import ani.dantotsu.themes.ThemeManager
|
import ani.dantotsu.themes.ThemeManager
|
||||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.*
|
|
||||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.newInstance
|
|
||||||
import nl.joery.animatedbottombar.AnimatedBottomBar
|
import nl.joery.animatedbottombar.AnimatedBottomBar
|
||||||
|
|
||||||
class NotificationActivity : AppCompatActivity() {
|
class NotificationActivity : AppCompatActivity() {
|
||||||
|
@ -58,7 +61,8 @@ class NotificationActivity : AppCompatActivity() {
|
||||||
val getOne = intent.getIntExtra("activityId", -1)
|
val getOne = intent.getIntExtra("activityId", -1)
|
||||||
if (getOne != -1) navBar.isVisible = false
|
if (getOne != -1) navBar.isVisible = false
|
||||||
binding.notificationViewPager.isUserInputEnabled = false
|
binding.notificationViewPager.isUserInputEnabled = false
|
||||||
binding.notificationViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle, getOne, CommentsEnabled)
|
binding.notificationViewPager.adapter =
|
||||||
|
ViewPagerAdapter(supportFragmentManager, lifecycle, getOne, CommentsEnabled)
|
||||||
binding.notificationViewPager.setCurrentItem(selected, false)
|
binding.notificationViewPager.setCurrentItem(selected, false)
|
||||||
navBar.selectTabAt(selected)
|
navBar.selectTabAt(selected)
|
||||||
navBar.setOnTabSelectListener(object : AnimatedBottomBar.OnTabSelectListener {
|
navBar.setOnTabSelectListener(object : AnimatedBottomBar.OnTabSelectListener {
|
||||||
|
|
|
@ -60,7 +60,8 @@ class NotificationItem(
|
||||||
PrefName.SubscriptionNotificationStore,
|
PrefName.SubscriptionNotificationStore,
|
||||||
null
|
null
|
||||||
) ?: listOf()
|
) ?: listOf()
|
||||||
val newList = list.filter { (it.time / 1000L).toInt() != notification.createdAt}
|
val newList =
|
||||||
|
list.filter { (it.time / 1000L).toInt() != notification.createdAt }
|
||||||
PrefManager.setVal(PrefName.SubscriptionNotificationStore, newList)
|
PrefManager.setVal(PrefName.SubscriptionNotificationStore, newList)
|
||||||
parentAdapter.remove(this@NotificationItem)
|
parentAdapter.remove(this@NotificationItem)
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ class RepoItem(
|
||||||
val url: String,
|
val url: String,
|
||||||
private val mediaType: MediaType,
|
private val mediaType: MediaType,
|
||||||
val onRemove: (String, MediaType) -> Unit
|
val onRemove: (String, MediaType) -> Unit
|
||||||
) :BindableItem<ItemRepoBinding>() {
|
) : BindableItem<ItemRepoBinding>() {
|
||||||
override fun getLayout() = R.layout.item_repo
|
override fun getLayout() = R.layout.item_repo
|
||||||
|
|
||||||
override fun bind(viewBinding: ItemRepoBinding, position: Int) {
|
override fun bind(viewBinding: ItemRepoBinding, position: Int) {
|
||||||
|
@ -88,7 +88,7 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
|
||||||
)
|
)
|
||||||
adapter.addAll(repositories.map { RepoItem(it, mediaType, ::onRepositoryRemoved) })
|
adapter.addAll(repositories.map { RepoItem(it, mediaType, ::onRepositoryRemoved) })
|
||||||
|
|
||||||
binding.repositoryInput.hint = when(mediaType) {
|
binding.repositoryInput.hint = when (mediaType) {
|
||||||
MediaType.ANIME -> getString(R.string.anime_add_repository)
|
MediaType.ANIME -> getString(R.string.anime_add_repository)
|
||||||
MediaType.MANGA -> getString(R.string.manga_add_repository)
|
MediaType.MANGA -> getString(R.string.manga_add_repository)
|
||||||
MediaType.NOVEL -> getString(R.string.novel_add_repository)
|
MediaType.NOVEL -> getString(R.string.novel_add_repository)
|
||||||
|
@ -110,7 +110,8 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
|
||||||
|
|
||||||
binding.repositoryInput.setOnEditorActionListener { textView, action, keyEvent ->
|
binding.repositoryInput.setOnEditorActionListener { textView, action, keyEvent ->
|
||||||
if (action == EditorInfo.IME_ACTION_DONE ||
|
if (action == EditorInfo.IME_ACTION_DONE ||
|
||||||
(keyEvent?.action == KeyEvent.ACTION_UP && keyEvent.keyCode == KeyEvent.KEYCODE_ENTER)) {
|
(keyEvent?.action == KeyEvent.ACTION_UP && keyEvent.keyCode == KeyEvent.KEYCODE_ENTER)
|
||||||
|
) {
|
||||||
val url = textView.text.toString()
|
val url = textView.text.toString()
|
||||||
if (url.isNotBlank()) {
|
if (url.isNotBlank()) {
|
||||||
val error = isValidUrl(url)
|
val error = isValidUrl(url)
|
||||||
|
@ -215,6 +216,7 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
|
||||||
Injekt.get<AnimeExtensionManager>().findAvailableExtensions()
|
Injekt.get<AnimeExtensionManager>().findAvailableExtensions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaType.MANGA -> {
|
MediaType.MANGA -> {
|
||||||
val manga =
|
val manga =
|
||||||
PrefManager.getVal<Set<String>>(PrefName.MangaExtensionRepos)
|
PrefManager.getVal<Set<String>>(PrefName.MangaExtensionRepos)
|
||||||
|
@ -224,6 +226,7 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
|
||||||
Injekt.get<MangaExtensionManager>().findAvailableExtensions()
|
Injekt.get<MangaExtensionManager>().findAvailableExtensions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaType.NOVEL -> {
|
MediaType.NOVEL -> {
|
||||||
val novel =
|
val novel =
|
||||||
PrefManager.getVal<Set<String>>(PrefName.NovelExtensionRepos)
|
PrefManager.getVal<Set<String>>(PrefName.NovelExtensionRepos)
|
||||||
|
@ -247,6 +250,7 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
|
||||||
Injekt.get<AnimeExtensionManager>().findAvailableExtensions()
|
Injekt.get<AnimeExtensionManager>().findAvailableExtensions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaType.MANGA -> {
|
MediaType.MANGA -> {
|
||||||
val manga =
|
val manga =
|
||||||
PrefManager.getVal<Set<String>>(PrefName.MangaExtensionRepos)
|
PrefManager.getVal<Set<String>>(PrefName.MangaExtensionRepos)
|
||||||
|
@ -256,6 +260,7 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
|
||||||
Injekt.get<MangaExtensionManager>().findAvailableExtensions()
|
Injekt.get<MangaExtensionManager>().findAvailableExtensions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaType.NOVEL -> {
|
MediaType.NOVEL -> {
|
||||||
val novel =
|
val novel =
|
||||||
PrefManager.getVal<Set<String>>(PrefName.NovelExtensionRepos)
|
PrefManager.getVal<Set<String>>(PrefName.NovelExtensionRepos)
|
||||||
|
|
|
@ -56,7 +56,8 @@ class AnilistSettingsActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentTitleLang = Anilist.titleLanguage
|
val currentTitleLang = Anilist.titleLanguage
|
||||||
val titleFormat = UserTitleLanguage.entries.firstOrNull { it.name == currentTitleLang } ?: UserTitleLanguage.ENGLISH
|
val titleFormat = UserTitleLanguage.entries.firstOrNull { it.name == currentTitleLang }
|
||||||
|
?: UserTitleLanguage.ENGLISH
|
||||||
|
|
||||||
settingsAnilistTitleLanguage.setText(titleLang[titleFormat.ordinal])
|
settingsAnilistTitleLanguage.setText(titleLang[titleFormat.ordinal])
|
||||||
settingsAnilistTitleLanguage.setAdapter(
|
settingsAnilistTitleLanguage.setAdapter(
|
||||||
|
@ -78,7 +79,9 @@ class AnilistSettingsActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentStaffNameLang = Anilist.staffNameLanguage
|
val currentStaffNameLang = Anilist.staffNameLanguage
|
||||||
val staffNameFormat = UserStaffNameLanguage.entries.firstOrNull { it.name == currentStaffNameLang } ?: UserStaffNameLanguage.ROMAJI_WESTERN
|
val staffNameFormat =
|
||||||
|
UserStaffNameLanguage.entries.firstOrNull { it.name == currentStaffNameLang }
|
||||||
|
?: UserStaffNameLanguage.ROMAJI_WESTERN
|
||||||
|
|
||||||
settingsAnilistStaffLanguage.setText(staffNameLang[staffNameFormat.ordinal])
|
settingsAnilistStaffLanguage.setText(staffNameLang[staffNameFormat.ordinal])
|
||||||
settingsAnilistStaffLanguage.setAdapter(
|
settingsAnilistStaffLanguage.setAdapter(
|
||||||
|
@ -99,8 +102,9 @@ class AnilistSettingsActivity : AppCompatActivity() {
|
||||||
settingsAnilistStaffLanguage.clearFocus()
|
settingsAnilistStaffLanguage.clearFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentMergeTimeDisplay = activityMergeTimeMap.entries.firstOrNull { it.value == Anilist.activityMergeTime }?.key
|
val currentMergeTimeDisplay =
|
||||||
?: "${Anilist.activityMergeTime} mins"
|
activityMergeTimeMap.entries.firstOrNull { it.value == Anilist.activityMergeTime }?.key
|
||||||
|
?: "${Anilist.activityMergeTime} mins"
|
||||||
settingsAnilistActivityMergeTime.setText(currentMergeTimeDisplay)
|
settingsAnilistActivityMergeTime.setText(currentMergeTimeDisplay)
|
||||||
settingsAnilistActivityMergeTime.setAdapter(
|
settingsAnilistActivityMergeTime.setAdapter(
|
||||||
ArrayAdapter(context, R.layout.item_dropdown, activityMergeTimeMap.keys.toList())
|
ArrayAdapter(context, R.layout.item_dropdown, activityMergeTimeMap.keys.toList())
|
||||||
|
@ -117,7 +121,8 @@ class AnilistSettingsActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentScoreFormat = Anilist.scoreFormat
|
val currentScoreFormat = Anilist.scoreFormat
|
||||||
val scoreFormat = ScoreFormat.entries.firstOrNull{ it.name == currentScoreFormat } ?: ScoreFormat.POINT_100
|
val scoreFormat = ScoreFormat.entries.firstOrNull { it.name == currentScoreFormat }
|
||||||
|
?: ScoreFormat.POINT_100
|
||||||
settingsAnilistScoreFormat.setText(scoreFormats[scoreFormat.ordinal])
|
settingsAnilistScoreFormat.setText(scoreFormats[scoreFormat.ordinal])
|
||||||
settingsAnilistScoreFormat.setAdapter(
|
settingsAnilistScoreFormat.setAdapter(
|
||||||
ArrayAdapter(context, R.layout.item_dropdown, scoreFormats)
|
ArrayAdapter(context, R.layout.item_dropdown, scoreFormats)
|
||||||
|
@ -139,7 +144,8 @@ class AnilistSettingsActivity : AppCompatActivity() {
|
||||||
settingsAnilistScoreFormat.clearFocus()
|
settingsAnilistScoreFormat.clearFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentRowOrder = rowOrderMap.entries.firstOrNull { it.value == Anilist.rowOrder }?.key ?: "Score"
|
val currentRowOrder =
|
||||||
|
rowOrderMap.entries.firstOrNull { it.value == Anilist.rowOrder }?.key ?: "Score"
|
||||||
settingsAnilistRowOrder.setText(currentRowOrder)
|
settingsAnilistRowOrder.setText(currentRowOrder)
|
||||||
settingsAnilistRowOrder.setAdapter(
|
settingsAnilistRowOrder.setAdapter(
|
||||||
ArrayAdapter(context, R.layout.item_dropdown, rowOrderMap.keys.toList())
|
ArrayAdapter(context, R.layout.item_dropdown, rowOrderMap.keys.toList())
|
||||||
|
@ -155,7 +161,8 @@ class AnilistSettingsActivity : AppCompatActivity() {
|
||||||
settingsAnilistRowOrder.clearFocus()
|
settingsAnilistRowOrder.clearFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
val containers = listOf(binding.animeCustomListsContainer, binding.mangaCustomListsContainer)
|
val containers =
|
||||||
|
listOf(binding.animeCustomListsContainer, binding.mangaCustomListsContainer)
|
||||||
val customLists = listOf(Anilist.animeCustomLists, Anilist.mangaCustomLists)
|
val customLists = listOf(Anilist.animeCustomLists, Anilist.mangaCustomLists)
|
||||||
val buttons = listOf(binding.addAnimeListButton, binding.addMangaListButton)
|
val buttons = listOf(binding.addAnimeListButton, binding.addMangaListButton)
|
||||||
|
|
||||||
|
@ -175,7 +182,8 @@ class AnilistSettingsActivity : AppCompatActivity() {
|
||||||
saveCustomLists()
|
saveCustomLists()
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentTimezone = Anilist.timezone?.let { Anilist.getDisplayTimezone(it, context) } ?: context.getString(R.string.selected_no_time_zone)
|
val currentTimezone = Anilist.timezone?.let { Anilist.getDisplayTimezone(it, context) }
|
||||||
|
?: context.getString(R.string.selected_no_time_zone)
|
||||||
settingsAnilistTimezone.setText(currentTimezone)
|
settingsAnilistTimezone.setText(currentTimezone)
|
||||||
settingsAnilistTimezone.setAdapter(
|
settingsAnilistTimezone.setAdapter(
|
||||||
ArrayAdapter(context, R.layout.item_dropdown, Anilist.timeZone)
|
ArrayAdapter(context, R.layout.item_dropdown, Anilist.timeZone)
|
||||||
|
|
|
@ -169,8 +169,12 @@ class ExtensionsActivity : AppCompatActivity() {
|
||||||
customAlertDialog().apply {
|
customAlertDialog().apply {
|
||||||
setTitle("Language")
|
setTitle("Language")
|
||||||
singleChoiceItems(languageOptions, index) { selected ->
|
singleChoiceItems(languageOptions, index) { selected ->
|
||||||
PrefManager.setVal(PrefName.LangSort, LanguageMapper.Companion.Language.entries[selected].code)
|
PrefManager.setVal(
|
||||||
val currentFragment = supportFragmentManager.findFragmentByTag("f${viewPager.currentItem}")
|
PrefName.LangSort,
|
||||||
|
LanguageMapper.Companion.Language.entries[selected].code
|
||||||
|
)
|
||||||
|
val currentFragment =
|
||||||
|
supportFragmentManager.findFragmentByTag("f${viewPager.currentItem}")
|
||||||
if (currentFragment is SearchQueryHandler) {
|
if (currentFragment is SearchQueryHandler) {
|
||||||
currentFragment.notifyDataChanged()
|
currentFragment.notifyDataChanged()
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
if (allSettings.isNotEmpty()) {
|
if (allSettings.isNotEmpty()) {
|
||||||
var selectedSetting = allSettings[0]
|
var selectedSetting = allSettings[0]
|
||||||
if (allSettings.size > 1) {
|
if (allSettings.size > 1) {
|
||||||
val names = allSettings.map { LanguageMapper.getLanguageName(it.lang) }
|
val names = allSettings.map { getLanguageName(it.lang) }
|
||||||
.toTypedArray()
|
.toTypedArray()
|
||||||
var selectedIndex = 0
|
var selectedIndex = 0
|
||||||
requireContext().customAlertDialog().apply {
|
requireContext().customAlertDialog().apply {
|
||||||
|
|
|
@ -290,7 +290,8 @@ class PlayerSettingsActivity :
|
||||||
PrefManager.setVal(PrefName.UseInternalCast, isChecked)
|
PrefManager.setVal(PrefName.UseInternalCast, isChecked)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.playerSettingsAdditionalCodec.isChecked = PrefManager.getVal(PrefName.UseAdditionalCodec)
|
binding.playerSettingsAdditionalCodec.isChecked =
|
||||||
|
PrefManager.getVal(PrefName.UseAdditionalCodec)
|
||||||
binding.playerSettingsAdditionalCodec.setOnCheckedChangeListener { _, isChecked ->
|
binding.playerSettingsAdditionalCodec.setOnCheckedChangeListener { _, isChecked ->
|
||||||
PrefManager.setVal(PrefName.UseAdditionalCodec, isChecked)
|
PrefManager.setVal(PrefName.UseAdditionalCodec, isChecked)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import ani.dantotsu.BottomSheetDialogFragment
|
import ani.dantotsu.BottomSheetDialogFragment
|
||||||
import ani.dantotsu.databinding.BottomSheetProxyBinding
|
import ani.dantotsu.databinding.BottomSheetProxyBinding
|
||||||
|
import ani.dantotsu.restartApp
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.restartApp
|
|
||||||
|
|
||||||
class ProxyDialogFragment : BottomSheetDialogFragment() {
|
class ProxyDialogFragment : BottomSheetDialogFragment() {
|
||||||
private var _binding: BottomSheetProxyBinding? = null
|
private var _binding: BottomSheetProxyBinding? = null
|
||||||
|
@ -16,8 +16,10 @@ class ProxyDialogFragment : BottomSheetDialogFragment() {
|
||||||
|
|
||||||
private var proxyHost: String? = PrefManager.getVal<String>(PrefName.Socks5ProxyHost).orEmpty()
|
private var proxyHost: String? = PrefManager.getVal<String>(PrefName.Socks5ProxyHost).orEmpty()
|
||||||
private var proxyPort: String? = PrefManager.getVal<String>(PrefName.Socks5ProxyPort).orEmpty()
|
private var proxyPort: String? = PrefManager.getVal<String>(PrefName.Socks5ProxyPort).orEmpty()
|
||||||
private var proxyUsername: String? = PrefManager.getVal<String>(PrefName.Socks5ProxyUsername).orEmpty()
|
private var proxyUsername: String? =
|
||||||
private var proxyPassword: String? = PrefManager.getVal<String>(PrefName.Socks5ProxyPassword).orEmpty()
|
PrefManager.getVal<String>(PrefName.Socks5ProxyUsername).orEmpty()
|
||||||
|
private var proxyPassword: String? =
|
||||||
|
PrefManager.getVal<String>(PrefName.Socks5ProxyPassword).orEmpty()
|
||||||
private var authEnabled: Boolean = PrefManager.getVal<Boolean>(PrefName.ProxyAuthEnabled)
|
private var authEnabled: Boolean = PrefManager.getVal<Boolean>(PrefName.ProxyAuthEnabled)
|
||||||
private val proxyEnabled: Boolean = PrefManager.getVal<Boolean>(PrefName.EnableSocks5Proxy)
|
private val proxyEnabled: Boolean = PrefManager.getVal<Boolean>(PrefName.EnableSocks5Proxy)
|
||||||
|
|
||||||
|
|
|
@ -142,8 +142,10 @@ class SettingsAboutActivity : AppCompatActivity() {
|
||||||
icon = R.drawable.ic_incognito_24,
|
icon = R.drawable.ic_incognito_24,
|
||||||
onClick = {
|
onClick = {
|
||||||
val text = TextView(context)
|
val text = TextView(context)
|
||||||
val pPLink = "https://raw.githubusercontent.com/rebelonion/Dantotsu/main/privacy_policy.md"
|
val pPLink =
|
||||||
val backup = "https://gcore.jsdelivr.net/gh/rebelonion/dantotsu/privacy_policy.md"
|
"https://raw.githubusercontent.com/rebelonion/Dantotsu/main/privacy_policy.md"
|
||||||
|
val backup =
|
||||||
|
"https://gcore.jsdelivr.net/gh/rebelonion/dantotsu/privacy_policy.md"
|
||||||
text.text = getString(R.string.loading)
|
text.text = getString(R.string.loading)
|
||||||
val markWon = try {
|
val markWon = try {
|
||||||
buildMarkwon(this@SettingsAboutActivity, false)
|
buildMarkwon(this@SettingsAboutActivity, false)
|
||||||
|
@ -177,7 +179,7 @@ class SettingsAboutActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
binding.settingsRecyclerView.layoutManager =
|
binding.settingsRecyclerView.layoutManager =
|
||||||
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
|
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
|
||||||
|
|
|
@ -211,16 +211,16 @@ class SettingsAccountActivity : AppCompatActivity() {
|
||||||
binding.settingsRecyclerView.adapter = SettingsAdapter(
|
binding.settingsRecyclerView.adapter = SettingsAdapter(
|
||||||
arrayListOf(
|
arrayListOf(
|
||||||
Settings(
|
Settings(
|
||||||
type = 2,
|
type = 2,
|
||||||
name = getString(R.string.enable_rpc),
|
name = getString(R.string.enable_rpc),
|
||||||
desc = getString(R.string.enable_rpc_desc),
|
desc = getString(R.string.enable_rpc_desc),
|
||||||
icon = R.drawable.interests_24,
|
icon = R.drawable.interests_24,
|
||||||
isChecked = PrefManager.getVal(PrefName.rpcEnabled),
|
isChecked = PrefManager.getVal(PrefName.rpcEnabled),
|
||||||
switch = { isChecked, _ ->
|
switch = { isChecked, _ ->
|
||||||
PrefManager.setVal(PrefName.rpcEnabled, isChecked)
|
PrefManager.setVal(PrefName.rpcEnabled, isChecked)
|
||||||
},
|
},
|
||||||
isVisible = Discord.token != null
|
isVisible = Discord.token != null
|
||||||
),
|
),
|
||||||
Settings(
|
Settings(
|
||||||
type = 1,
|
type = 1,
|
||||||
name = getString(R.string.anilist_settings),
|
name = getString(R.string.anilist_settings),
|
||||||
|
@ -235,30 +235,31 @@ class SettingsAccountActivity : AppCompatActivity() {
|
||||||
isActivity = true
|
isActivity = true
|
||||||
),
|
),
|
||||||
Settings(
|
Settings(
|
||||||
type = 2,
|
type = 2,
|
||||||
name = getString(R.string.comments_button),
|
name = getString(R.string.comments_button),
|
||||||
desc = getString(R.string.comments_button_desc),
|
desc = getString(R.string.comments_button_desc),
|
||||||
icon = R.drawable.ic_round_comment_24,
|
icon = R.drawable.ic_round_comment_24,
|
||||||
isChecked = PrefManager.getVal<Int>(PrefName.CommentsEnabled) == 1,
|
isChecked = PrefManager.getVal<Int>(PrefName.CommentsEnabled) == 1,
|
||||||
switch = { isChecked, _ ->
|
switch = { isChecked, _ ->
|
||||||
PrefManager.setVal(PrefName.CommentsEnabled, if (isChecked) 1 else 2 )
|
PrefManager.setVal(PrefName.CommentsEnabled, if (isChecked) 1 else 2)
|
||||||
reload()
|
reload()
|
||||||
},
|
},
|
||||||
isVisible = Anilist.token != null
|
isVisible = Anilist.token != null
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
binding.settingsRecyclerView.layoutManager =
|
binding.settingsRecyclerView.layoutManager =
|
||||||
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
|
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reload() {
|
fun reload() {
|
||||||
snackString(getString(R.string.restart_app_extra))
|
snackString(getString(R.string.restart_app_extra))
|
||||||
//snackString(R.string.restart_app_extra)
|
//snackString(R.string.restart_app_extra)
|
||||||
//?.setDuration(Snackbar.LENGTH_LONG)
|
//?.setDuration(Snackbar.LENGTH_LONG)
|
||||||
//?.setAction(R.string.do_it) {
|
//?.setAction(R.string.do_it) {
|
||||||
//startMainActivity(this@SettingsAccountActivity)
|
//startMainActivity(this@SettingsAccountActivity)
|
||||||
//} Disabled for now. Doesn't update the ADDRESS even after this
|
//} Disabled for now. Doesn't update the ADDRESS even after this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.addons.AddonDownloader
|
import ani.dantotsu.addons.AddonDownloader
|
||||||
import ani.dantotsu.addons.download.DownloadAddonManager
|
import ani.dantotsu.addons.download.DownloadAddonManager
|
||||||
import ani.dantotsu.addons.torrent.TorrentServerService
|
|
||||||
import ani.dantotsu.addons.torrent.TorrentAddonManager
|
import ani.dantotsu.addons.torrent.TorrentAddonManager
|
||||||
|
import ani.dantotsu.addons.torrent.TorrentServerService
|
||||||
import ani.dantotsu.databinding.ActivitySettingsAddonsBinding
|
import ani.dantotsu.databinding.ActivitySettingsAddonsBinding
|
||||||
import ani.dantotsu.databinding.ItemSettingsBinding
|
import ani.dantotsu.databinding.ItemSettingsBinding
|
||||||
import ani.dantotsu.initActivity
|
import ani.dantotsu.initActivity
|
||||||
|
|
|
@ -8,8 +8,6 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import android.widget.CheckBox
|
|
||||||
import android.widget.EditText
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.biometric.BiometricManager
|
import androidx.biometric.BiometricManager
|
||||||
|
@ -231,7 +229,7 @@ class SettingsCommonActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setNegButton(R.string.cancel)
|
setNegButton(R.string.cancel)
|
||||||
setNeutralButton(R.string.remove){
|
setNeutralButton(R.string.remove) {
|
||||||
PrefManager.setVal(PrefName.AppPassword, "")
|
PrefManager.setVal(PrefName.AppPassword, "")
|
||||||
PrefManager.setVal(PrefName.BiometricToken, "")
|
PrefManager.setVal(PrefName.BiometricToken, "")
|
||||||
PrefManager.setVal(PrefName.OverridePassword, false)
|
PrefManager.setVal(PrefName.OverridePassword, false)
|
||||||
|
@ -315,10 +313,10 @@ class SettingsCommonActivity : AppCompatActivity() {
|
||||||
desc = getString(R.string.change_download_location_desc),
|
desc = getString(R.string.change_download_location_desc),
|
||||||
icon = R.drawable.ic_round_source_24,
|
icon = R.drawable.ic_round_source_24,
|
||||||
onClick = {
|
onClick = {
|
||||||
context.customAlertDialog().apply{
|
context.customAlertDialog().apply {
|
||||||
setTitle(R.string.change_download_location)
|
setTitle(R.string.change_download_location)
|
||||||
setMessage(R.string.download_location_msg)
|
setMessage(R.string.download_location_msg)
|
||||||
setPosButton(R.string.ok){
|
setPosButton(R.string.ok) {
|
||||||
val oldUri = PrefManager.getVal<String>(PrefName.DownloadsDir)
|
val oldUri = PrefManager.getVal<String>(PrefName.DownloadsDir)
|
||||||
launcher.registerForCallback { success ->
|
launcher.registerForCallback { success ->
|
||||||
if (success) {
|
if (success) {
|
||||||
|
|
|
@ -59,7 +59,8 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
val window = dialog?.window
|
val window = dialog?.window
|
||||||
window?.statusBarColor = Color.CYAN
|
window?.statusBarColor = Color.CYAN
|
||||||
window?.navigationBarColor = requireContext().getThemeColor(com.google.android.material.R.attr.colorSurface)
|
window?.navigationBarColor =
|
||||||
|
requireContext().getThemeColor(com.google.android.material.R.attr.colorSurface)
|
||||||
val notificationIcon = if (Anilist.unreadNotificationCount > 0) {
|
val notificationIcon = if (Anilist.unreadNotificationCount > 0) {
|
||||||
R.drawable.ic_round_notifications_active_24
|
R.drawable.ic_round_notifications_active_24
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,7 +71,7 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
|
||||||
if (Anilist.token != null) {
|
if (Anilist.token != null) {
|
||||||
binding.settingsLogin.setText(R.string.logout)
|
binding.settingsLogin.setText(R.string.logout)
|
||||||
binding.settingsLogin.setOnClickListener {
|
binding.settingsLogin.setOnClickListener {
|
||||||
requireContext().customAlertDialog().apply{
|
requireContext().customAlertDialog().apply {
|
||||||
setTitle(R.string.logout)
|
setTitle(R.string.logout)
|
||||||
setMessage(R.string.logout_confirm)
|
setMessage(R.string.logout_confirm)
|
||||||
setPosButton(R.string.yes) {
|
setPosButton(R.string.yes) {
|
||||||
|
|
|
@ -26,11 +26,8 @@ import ani.dantotsu.statusBarHeight
|
||||||
import ani.dantotsu.themes.ThemeManager
|
import ani.dantotsu.themes.ThemeManager
|
||||||
import ani.dantotsu.util.customAlertDialog
|
import ani.dantotsu.util.customAlertDialog
|
||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
|
||||||
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
|
|
||||||
class SettingsExtensionsActivity : AppCompatActivity() {
|
class SettingsExtensionsActivity : AppCompatActivity() {
|
||||||
private lateinit var binding: ActivitySettingsExtensionsBinding
|
private lateinit var binding: ActivitySettingsExtensionsBinding
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package ani.dantotsu.settings
|
package ani.dantotsu.settings
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
|
|
@ -82,9 +82,18 @@ class SettingsNotificationActivity : AppCompatActivity() {
|
||||||
setTitle(R.string.subscriptions_checking_time)
|
setTitle(R.string.subscriptions_checking_time)
|
||||||
singleChoiceItems(timeNames, curTime) { i ->
|
singleChoiceItems(timeNames, curTime) { i ->
|
||||||
curTime = i
|
curTime = i
|
||||||
it.settingsTitle.text = getString(R.string.subscriptions_checking_time_s, timeNames[i])
|
it.settingsTitle.text = getString(
|
||||||
PrefManager.setVal(PrefName.SubscriptionNotificationInterval, curTime)
|
R.string.subscriptions_checking_time_s,
|
||||||
TaskScheduler.create(context, PrefManager.getVal(PrefName.UseAlarmManager)).scheduleAllTasks(context)
|
timeNames[i]
|
||||||
|
)
|
||||||
|
PrefManager.setVal(
|
||||||
|
PrefName.SubscriptionNotificationInterval,
|
||||||
|
curTime
|
||||||
|
)
|
||||||
|
TaskScheduler.create(
|
||||||
|
context,
|
||||||
|
PrefManager.getVal(PrefName.UseAlarmManager)
|
||||||
|
).scheduleAllTasks(context)
|
||||||
}
|
}
|
||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
|
@ -124,8 +133,9 @@ class SettingsNotificationActivity : AppCompatActivity() {
|
||||||
.setMultiChoiceItems(
|
.setMultiChoiceItems(
|
||||||
types.map { name ->
|
types.map { name ->
|
||||||
name.replace("_", " ").lowercase().replaceFirstChar {
|
name.replace("_", " ").lowercase().replaceFirstChar {
|
||||||
if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString()
|
if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString()
|
||||||
} }.toTypedArray(),
|
}
|
||||||
|
}.toTypedArray(),
|
||||||
selected
|
selected
|
||||||
) { _, which, isChecked ->
|
) { _, which, isChecked ->
|
||||||
val type = types[which]
|
val type = types[which]
|
||||||
|
|
|
@ -47,7 +47,8 @@ class SettingsThemeActivity : AppCompatActivity(), SimpleDialog.OnDialogResultLi
|
||||||
val mainIntent = Intent.makeRestartActivityTask(
|
val mainIntent = Intent.makeRestartActivityTask(
|
||||||
packageManager.getLaunchIntentForPackage(packageName)!!.component
|
packageManager.getLaunchIntentForPackage(packageName)!!.component
|
||||||
)
|
)
|
||||||
val component = ComponentName(packageName, SettingsActivity::class.qualifiedName!!)
|
val component =
|
||||||
|
ComponentName(packageName, SettingsActivity::class.qualifiedName!!)
|
||||||
try {
|
try {
|
||||||
startActivity(Intent().setComponent(component))
|
startActivity(Intent().setComponent(component))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
|
@ -41,5 +41,6 @@ class SubscriptionItem(
|
||||||
|
|
||||||
override fun getLayout(): Int = R.layout.item_subscription
|
override fun getLayout(): Int = R.layout.item_subscription
|
||||||
|
|
||||||
override fun initializeViewBinding(view: View): ItemSubscriptionBinding = ItemSubscriptionBinding.bind(view)
|
override fun initializeViewBinding(view: View): ItemSubscriptionBinding =
|
||||||
|
ItemSubscriptionBinding.bind(view)
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
package ani.dantotsu.settings
|
package ani.dantotsu.settings
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -36,7 +35,8 @@ class SubscriptionSource(
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
binding.extensionIconImageView.visibility = View.VISIBLE
|
binding.extensionIconImageView.visibility = View.VISIBLE
|
||||||
val layoutParams = binding.extensionIconImageView.layoutParams as ViewGroup.MarginLayoutParams
|
val layoutParams =
|
||||||
|
binding.extensionIconImageView.layoutParams as ViewGroup.MarginLayoutParams
|
||||||
layoutParams.leftMargin = 28
|
layoutParams.leftMargin = 28
|
||||||
binding.extensionIconImageView.layoutParams = layoutParams
|
binding.extensionIconImageView.layoutParams = layoutParams
|
||||||
|
|
||||||
|
@ -55,11 +55,12 @@ class SubscriptionSource(
|
||||||
|
|
||||||
private fun updateSubscriptionCount() {
|
private fun updateSubscriptionCount() {
|
||||||
binding.subscriptionCount.text = subscriptions.size.toString()
|
binding.subscriptionCount.text = subscriptions.size.toString()
|
||||||
binding.subscriptionCount.visibility = if (subscriptions.isEmpty()) View.GONE else View.VISIBLE
|
binding.subscriptionCount.visibility =
|
||||||
|
if (subscriptions.isEmpty()) View.GONE else View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showRemoveAllSubscriptionsDialog(context: Context) {
|
private fun showRemoveAllSubscriptionsDialog(context: Context) {
|
||||||
context.customAlertDialog().apply{
|
context.customAlertDialog().apply {
|
||||||
setTitle(R.string.remove_all_subscriptions)
|
setTitle(R.string.remove_all_subscriptions)
|
||||||
setMessage(R.string.remove_all_subscriptions_desc, parserName)
|
setMessage(R.string.remove_all_subscriptions_desc, parserName)
|
||||||
setPosButton(R.string.ok) { removeAllSubscriptions() }
|
setPosButton(R.string.ok) { removeAllSubscriptions() }
|
||||||
|
@ -96,9 +97,11 @@ class SubscriptionSource(
|
||||||
val startPosition = adapter.getAdapterPosition(this) + 1
|
val startPosition = adapter.getAdapterPosition(this) + 1
|
||||||
if (isExpanded) {
|
if (isExpanded) {
|
||||||
subscriptions.forEachIndexed { index, subscribeMedia ->
|
subscriptions.forEachIndexed { index, subscribeMedia ->
|
||||||
adapter.add(startPosition + index, SubscriptionItem(subscribeMedia.id, subscribeMedia, adapter) { removedId ->
|
adapter.add(
|
||||||
removeSubscription(removedId)
|
startPosition + index,
|
||||||
})
|
SubscriptionItem(subscribeMedia.id, subscribeMedia, adapter) { removedId ->
|
||||||
|
removeSubscription(removedId)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
repeat(subscriptions.size) {
|
repeat(subscriptions.size) {
|
||||||
|
@ -109,5 +112,6 @@ class SubscriptionSource(
|
||||||
|
|
||||||
override fun getLayout(): Int = R.layout.item_extension
|
override fun getLayout(): Int = R.layout.item_extension
|
||||||
|
|
||||||
override fun initializeViewBinding(view: View): ItemExtensionBinding = ItemExtensionBinding.bind(view)
|
override fun initializeViewBinding(view: View): ItemExtensionBinding =
|
||||||
|
ItemExtensionBinding.bind(view)
|
||||||
}
|
}
|
|
@ -67,10 +67,13 @@ class SubscriptionsBottomDialog : BottomSheetDialogFragment() {
|
||||||
return when {
|
return when {
|
||||||
animeExtension.installedExtensionsFlow.value.any { it.name == parserName } ->
|
animeExtension.installedExtensionsFlow.value.any { it.name == parserName } ->
|
||||||
animeExtension.installedExtensionsFlow.value.find { it.name == parserName }?.icon
|
animeExtension.installedExtensionsFlow.value.find { it.name == parserName }?.icon
|
||||||
|
|
||||||
mangaExtensions.installedExtensionsFlow.value.any { it.name == parserName } ->
|
mangaExtensions.installedExtensionsFlow.value.any { it.name == parserName } ->
|
||||||
mangaExtensions.installedExtensionsFlow.value.find { it.name == parserName }?.icon
|
mangaExtensions.installedExtensionsFlow.value.find { it.name == parserName }?.icon
|
||||||
|
|
||||||
novelExtensions.installedExtensionsFlow.value.any { it.name == parserName } ->
|
novelExtensions.installedExtensionsFlow.value.any { it.name == parserName } ->
|
||||||
novelExtensions.installedExtensionsFlow.value.find { it.name == parserName }?.icon
|
novelExtensions.installedExtensionsFlow.value.find { it.name == parserName }?.icon
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package ani.dantotsu.settings
|
package ani.dantotsu.settings
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
@ -43,7 +42,8 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
|
||||||
setTitle(getString(R.string.home_layout_show))
|
setTitle(getString(R.string.home_layout_show))
|
||||||
multiChoiceItems(
|
multiChoiceItems(
|
||||||
items = views,
|
items = views,
|
||||||
checkedItems = PrefManager.getVal<List<Boolean>>(PrefName.HomeLayout).toBooleanArray()
|
checkedItems = PrefManager.getVal<List<Boolean>>(PrefName.HomeLayout)
|
||||||
|
.toBooleanArray()
|
||||||
) { selectedItems ->
|
) { selectedItems ->
|
||||||
for (i in selectedItems.indices) {
|
for (i in selectedItems.indices) {
|
||||||
set[i] = selectedItems[i]
|
set[i] = selectedItems[i]
|
||||||
|
@ -69,7 +69,8 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
|
||||||
PrefManager.setVal(PrefName.ImmersiveMode, isChecked)
|
PrefManager.setVal(PrefName.ImmersiveMode, isChecked)
|
||||||
restartApp()
|
restartApp()
|
||||||
}
|
}
|
||||||
binding.uiSettingsHideRedDot.isChecked = !PrefManager.getVal<Boolean>(PrefName.ShowNotificationRedDot)
|
binding.uiSettingsHideRedDot.isChecked =
|
||||||
|
!PrefManager.getVal<Boolean>(PrefName.ShowNotificationRedDot)
|
||||||
binding.uiSettingsHideRedDot.setOnCheckedChangeListener { _, isChecked ->
|
binding.uiSettingsHideRedDot.setOnCheckedChangeListener { _, isChecked ->
|
||||||
PrefManager.setVal(PrefName.ShowNotificationRedDot, !isChecked)
|
PrefManager.setVal(PrefName.ShowNotificationRedDot, !isChecked)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,7 @@ package ani.dantotsu.settings.extensionprefs
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.preference.DialogPreference
|
import androidx.preference.DialogPreference
|
||||||
|
@ -38,10 +32,12 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() {
|
||||||
preferenceManager.createPreferenceScreen(requireContext())
|
preferenceManager.createPreferenceScreen(requireContext())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
ThemeManager(requireActivity()).applyTheme()
|
ThemeManager(requireActivity()).applyTheme()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var onCloseAction: (() -> Unit)? = null
|
private var onCloseAction: (() -> Unit)? = null
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -104,7 +100,8 @@ class InitialAnimeSourcePreferencesFragment(
|
||||||
preferenceManager.createPreferenceScreen(requireContext())
|
preferenceManager.createPreferenceScreen(requireContext())
|
||||||
}
|
}
|
||||||
//set background color
|
//set background color
|
||||||
val color = requireContext().getThemeColor(com.google.android.material.R.attr.backgroundColor,)
|
val color =
|
||||||
|
requireContext().getThemeColor(com.google.android.material.R.attr.backgroundColor)
|
||||||
view?.setBackgroundColor(color)
|
view?.setBackgroundColor(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -203,7 +203,13 @@ enum class PrefName(val data: Pref) {
|
||||||
LogToFile(Pref(Location.Irrelevant, Boolean::class, false)),
|
LogToFile(Pref(Location.Irrelevant, Boolean::class, false)),
|
||||||
RecentGlobalNotification(Pref(Location.Irrelevant, Int::class, 0)),
|
RecentGlobalNotification(Pref(Location.Irrelevant, Int::class, 0)),
|
||||||
CommentNotificationStore(Pref(Location.Irrelevant, List::class, listOf<CommentStore>())),
|
CommentNotificationStore(Pref(Location.Irrelevant, List::class, listOf<CommentStore>())),
|
||||||
SubscriptionNotificationStore(Pref(Location.Irrelevant, List::class, listOf<SubscriptionStore>())),
|
SubscriptionNotificationStore(
|
||||||
|
Pref(
|
||||||
|
Location.Irrelevant,
|
||||||
|
List::class,
|
||||||
|
listOf<SubscriptionStore>()
|
||||||
|
)
|
||||||
|
),
|
||||||
UnreadCommentNotifications(Pref(Location.Irrelevant, Int::class, 0)),
|
UnreadCommentNotifications(Pref(Location.Irrelevant, Int::class, 0)),
|
||||||
DownloadsDir(Pref(Location.Irrelevant, String::class, "")),
|
DownloadsDir(Pref(Location.Irrelevant, String::class, "")),
|
||||||
OC(Pref(Location.Irrelevant, Boolean::class, false)),
|
OC(Pref(Location.Irrelevant, Boolean::class, false)),
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue