Merge pull request #559 from rebelonion/dev

Dev
This commit is contained in:
rebel onion 2025-01-06 08:29:48 -06:00 committed by GitHub
commit f606bef2a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
106 changed files with 951 additions and 612 deletions

View file

@ -18,7 +18,9 @@ import ani.dantotsu.Mapper
import ani.dantotsu.R
import ani.dantotsu.buildMarkwon
import ani.dantotsu.client
import ani.dantotsu.connections.comments.CommentsAPI
import ani.dantotsu.currContext
import ani.dantotsu.decodeBase64ToString
import ani.dantotsu.logError
import ani.dantotsu.openLinkInBrowser
import ani.dantotsu.settings.saving.PrefManager
@ -37,11 +39,34 @@ import java.text.SimpleDateFormat
import java.util.Locale
object AppUpdater {
suspend fun check(activity: FragmentActivity, post: Boolean = false) {
if (post) snackString(currContext()?.getString(R.string.checking_for_update))
val repo = activity.getString(R.string.repo)
tryWithSuspend {
val (md, version) = if (BuildConfig.DEBUG) {
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)
@ -53,10 +78,49 @@ object AppUpdater {
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
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) {
if (post) snackString(currContext()?.getString(R.string.checking_for_update))
val repo = activity.getString(R.string.repo)
tryWithSuspend {
val (md, version) = fetchUpdateInfo(repo, BuildConfig.DEBUG) ?: return@tryWithSuspend
Logger.log("Git Version : $version")
val dontShow = PrefManager.getCustomVal("dont_ask_for_update_$version", false)
@ -69,7 +133,7 @@ object AppUpdater {
)
addView(
TextView(activity).apply {
val markWon = try { //slower phones can destroy the activity before this is done
val markWon = try {
buildMarkwon(activity, false)
} catch (e: IllegalArgumentException) {
return@runOnUiThread
@ -89,17 +153,11 @@ object AppUpdater {
setPositiveButton(currContext()!!.getString(R.string.lets_go)) {
MainScope().launch(Dispatchers.IO) {
try {
val apks =
client.get("https://api.github.com/repos/$repo/releases/tags/v$version")
.parsed<GithubResponse>().assets?.filter {
it.browserDownloadURL.endsWith(
".apk"
)
}
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")
val apkUrl = fetchApkUrl(repo, version, BuildConfig.DEBUG)
if (apkUrl != null) {
activity.downloadUpdate(version, apkUrl)
} else {
openLinkInBrowser("https://github.com/repos/$repo/releases/tag/v$version")
}
} catch (e: Exception) {
logError(e)
@ -112,8 +170,7 @@ object AppUpdater {
}
show(activity.supportFragmentManager, "dialog")
}
}
else {
} else {
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
private fun Activity.downloadUpdate(version: String, url: String): Boolean {
private fun Activity.downloadUpdate(version: String, url: String) {
toast(getString(R.string.downloading_update, version))
val downloadManager = this.getSystemService<DownloadManager>()!!
@ -167,7 +223,7 @@ object AppUpdater {
logError(e)
-1
}
if (id == -1L) return true
if (id == -1L) return
ContextCompat.registerReceiver(
this,
object : BroadcastReceiver() {
@ -188,7 +244,6 @@ object AppUpdater {
}, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE),
ContextCompat.RECEIVER_EXPORTED
)
return true
}
private fun openApk(context: Context, uri: Uri) {

View file

@ -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"
xmlns:tools="http://schemas.android.com/tools">
@ -113,10 +113,8 @@
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:host="*"/>
<data android:mimeType="application/epub+zip"/>
<data android:mimeType="application/x-mobipocket-ebook" />
<data android:mimeType="application/vnd.amazon.ebook" />
@ -385,10 +383,10 @@
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.ani" />
<data android:pathPattern=".*\\.sani" />
<data android:host="*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />

View file

@ -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.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.target.Target
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
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.glide.GlideImagesPlugin
import jp.wasabeef.glide.transformations.BlurTransformation
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import nl.joery.animatedbottombar.AnimatedBottomBar
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -157,6 +153,8 @@ import java.util.TimeZone
import java.util.Timer
import java.util.TimerTask
import kotlin.collections.set
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi
import kotlin.math.log2
import kotlin.math.max
import kotlin.math.min
@ -854,6 +852,7 @@ fun savePrefsToDownloads(
}
)
}
@SuppressLint("StringFormatMatches")
fun savePrefs(serialized: String, path: String, title: String, context: Context): File? {
var file = File(path, "$title.ani")
@ -921,6 +920,7 @@ fun shareImage(title: String, bitmap: Bitmap, context: Context) {
intent.putExtra(Intent.EXTRA_STREAM, contentUri)
context.startActivity(Intent.createChooser(intent, "Share $title"))
}
@SuppressLint("StringFormatMatches")
fun saveImage(image: Bitmap, path: String, imageFileName: String): File? {
val imageFile = File(path, "$imageFileName.png")
@ -1467,6 +1467,7 @@ fun buildMarkwon(
}
return false
}
override fun onLoadFailed(
e: GlideException?,
model: Any?,
@ -1495,9 +1496,9 @@ fun buildMarkwon(
}
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)
return matchResult?.groupValues?.getOrNull(1) ?: ""
}
@ -1524,3 +1525,13 @@ fun getLanguageName(language: String): String? {
}
return null
}
@OptIn(ExperimentalEncodingApi::class)
fun String.decodeBase64ToString(): String {
return try {
String(Base64.decode(this), Charsets.UTF_8)
} catch (e: Exception) {
Logger.log(e)
""
}
}

View file

@ -26,9 +26,17 @@ interface DownloadAddonApiV2 {
statCallback: (Double) -> Unit
): 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

View file

@ -6,11 +6,11 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import ani.dantotsu.R
import ani.dantotsu.addons.AddonDownloader.Companion.hasUpdate
import ani.dantotsu.addons.AddonInstallReceiver
import ani.dantotsu.addons.AddonListener
import ani.dantotsu.addons.AddonLoader
import ani.dantotsu.addons.AddonManager
import ani.dantotsu.addons.LoadResult
import ani.dantotsu.addons.AddonInstallReceiver
import ani.dantotsu.media.AddonType
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName

View file

@ -41,7 +41,8 @@ class TorrentServerService : Service() {
flags: Int,
startId: Int,
): Int {
extension = Injekt.get<TorrentAddonManager>().extension?.extension ?: return START_NOT_STICKY
extension =
Injekt.get<TorrentAddonManager>().extension?.extension ?: return START_NOT_STICKY
intent?.let {
if (it.action != null) {
when (it.action) {

View file

@ -8,7 +8,6 @@ import androidx.media3.common.util.UnstableApi
import androidx.media3.database.StandaloneDatabaseProvider
import ani.dantotsu.addons.download.DownloadAddonManager
import ani.dantotsu.addons.torrent.TorrentAddonManager
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.media.manga.MangaCache
import ani.dantotsu.parsers.novel.NovelExtensionManager

View file

@ -145,7 +145,10 @@ class AnilistMutations {
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 = """
mutation (${"$"}animeListOptions: MediaListOptionsInput, ${"$"}mangaListOptions: MediaListOptionsInput) {
UpdateUser(animeListOptions: ${"$"}animeListOptions, mangaListOptions: ${"$"}mangaListOptions) {
@ -291,7 +294,8 @@ class AnilistMutations {
isFollower
}
}
""".trimIndent())
""".trimIndent()
)
}
suspend fun toggleLike(id: Int, type: String): ToggleLike? {
@ -302,7 +306,8 @@ class AnilistMutations {
__typename
}
}
""".trimIndent())
""".trimIndent()
)
}
suspend fun postActivity(text: String, edit: Int? = null): String {
@ -316,10 +321,16 @@ class AnilistMutations {
""".trimIndent()
val result = executeQuery<JsonObject>(query)
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 query = """
mutation {
@ -335,7 +346,8 @@ class AnilistMutations {
""".trimIndent()
val result = executeQuery<JsonObject>(query)
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 {
@ -353,7 +365,8 @@ class AnilistMutations {
""".trimIndent()
val result = executeQuery<JsonObject>(query)
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 {
@ -373,7 +386,8 @@ class AnilistMutations {
""".trimIndent()
val result = executeQuery<JsonObject>(query)
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 {

View file

@ -359,19 +359,24 @@ class AnilistSearch : ViewModel() {
var searched = false
var notSet = true
lateinit var aniMangaSearchResults: AniMangaSearchResults
private val aniMangaResult: MutableLiveData<AniMangaSearchResults?> = MutableLiveData<AniMangaSearchResults?>(null)
private val aniMangaResult: MutableLiveData<AniMangaSearchResults?> =
MutableLiveData<AniMangaSearchResults?>(null)
lateinit var characterSearchResults: CharacterSearchResults
private val characterResult: MutableLiveData<CharacterSearchResults?> = MutableLiveData<CharacterSearchResults?>(null)
private val characterResult: MutableLiveData<CharacterSearchResults?> =
MutableLiveData<CharacterSearchResults?>(null)
lateinit var studioSearchResults: StudioSearchResults
private val studioResult: MutableLiveData<StudioSearchResults?> = MutableLiveData<StudioSearchResults?>(null)
private val studioResult: MutableLiveData<StudioSearchResults?> =
MutableLiveData<StudioSearchResults?>(null)
lateinit var staffSearchResults: StaffSearchResults
private val staffResult: MutableLiveData<StaffSearchResults?> = MutableLiveData<StaffSearchResults?>(null)
private val staffResult: MutableLiveData<StaffSearchResults?> =
MutableLiveData<StaffSearchResults?>(null)
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?> {
return when (type) {
@ -517,7 +522,8 @@ class AnilistSearch : ViewModel() {
)
)
private suspend fun loadNextCharacterPage(r: CharacterSearchResults) = characterResult.postValue(
private suspend fun loadNextCharacterPage(r: CharacterSearchResults) =
characterResult.postValue(
Anilist.query.searchCharacters(
r.page + 1,
r.search,

View file

@ -34,7 +34,8 @@ fun characterInformation(includeMediaInfo: Boolean) = """
month
day
}
${if (includeMediaInfo) """
${
if (includeMediaInfo) """
media(page: 0,sort:[POPULARITY_DESC,SCORE_DESC]) {
$standardPageInformation
edges {
@ -79,7 +80,8 @@ fun characterInformation(includeMediaInfo: Boolean) = """
}
}
}
}""".prepare() else ""}
}""".prepare() else ""
}
""".prepare()
fun studioInformation(page: Int, perPage: Int) = """

View file

@ -14,6 +14,7 @@ data class FeedResponse(
val page: ActivityPage
) : java.io.Serializable
}
@Serializable
data class ActivityPage(
@SerialName("activities")

View file

@ -239,6 +239,7 @@ data class AiringSchedule(
// The associate media of the airing episode
@SerialName("media") var media: Media?,
)
@Serializable
data class MediaStreamingEpisode(
// The title of the episode
@ -253,6 +254,7 @@ data class MediaStreamingEpisode(
// The site location of the streaming episode
@SerialName("site") var site: String?,
)
@Serializable
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.

View file

@ -123,8 +123,10 @@ data class UserStatisticTypes(
enum class UserTitleLanguage {
@SerialName("ENGLISH")
ENGLISH,
@SerialName("ROMAJI")
ROMAJI,
@SerialName("NATIVE")
NATIVE
}
@ -133,8 +135,10 @@ enum class UserTitleLanguage {
enum class UserStaffNameLanguage {
@SerialName("ROMAJI_WESTERN")
ROMAJI_WESTERN,
@SerialName("ROMAJI")
ROMAJI,
@SerialName("NATIVE")
NATIVE
}
@ -143,12 +147,16 @@ enum class UserStaffNameLanguage {
enum class ScoreFormat {
@SerialName("POINT_100")
POINT_100,
@SerialName("POINT_10_DECIMAL")
POINT_10_DECIMAL,
@SerialName("POINT_10")
POINT_10,
@SerialName("POINT_5")
POINT_5,
@SerialName("POINT_3")
POINT_3,
}

View file

@ -372,6 +372,7 @@ object CommentsAPI {
}
errorMessage("Failed to login after multiple attempts")
}
private fun errorMessage(reason: String) {
if (commentsEnabled) Logger.log(reason)
if (isOnline && commentsEnabled) snackString(reason)
@ -410,7 +411,7 @@ object CommentsAPI {
return map
}
private fun requestBuilder(client: OkHttpClient = Injekt.get<NetworkHelper>().client): Requests {
fun requestBuilder(client: OkHttpClient = Injekt.get<NetworkHelper>().client): Requests {
return Requests(
client,
headerBuilder()

View file

@ -8,8 +8,8 @@ import ani.dantotsu.settings.saving.PrefName
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import okhttp3.OkHttpClient
import kotlin.coroutines.CoroutineContext
import java.util.concurrent.TimeUnit.SECONDS
import kotlin.coroutines.CoroutineContext
@Suppress("MemberVisibilityCanBePrivate")
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 buttons: MutableList<Link> = mutableListOf()
)
suspend fun createPresence(data: RPCData): String {
val json = Json {
encodeDefaults = true

View file

@ -30,7 +30,6 @@ import ani.dantotsu.bottomBar
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
import ani.dantotsu.currActivity
import ani.dantotsu.currContext
import ani.dantotsu.download.DownloadCompat
import ani.dantotsu.download.DownloadCompat.Companion.loadMediaCompat
import ani.dantotsu.download.DownloadCompat.Companion.loadOfflineAnimeModelCompat
import ani.dantotsu.download.DownloadedType
@ -209,7 +208,9 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
setMessage("Are you sure you want to delete ${item.title}?")
setPosButton(R.string.yes) {
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()) {
snackString("No media found") // if this happens, terrible things have happened
}
@ -287,10 +288,12 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
}
downloadsJob = Job()
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>()
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 offlineAnimeModel = loadOfflineAnimeModel(download)
if (offlineAnimeModel.title == "unknown") offlineAnimeModel.title = title

View file

@ -177,6 +177,7 @@ object Helper {
downloadManager
}
}
@Deprecated("exoplayer download manager is no longer used")
@OptIn(UnstableApi::class)
fun getSimpleCache(context: Context): SimpleCache {
@ -189,6 +190,7 @@ object Helper {
simpleCache!!
}
}
@Synchronized
@Deprecated("exoplayer download manager is no longer used")
private fun getDownloadDirectory(context: Context): File {
@ -200,12 +202,16 @@ object Helper {
}
return downloadDirectory!!
}
@Deprecated("exoplayer download manager is no longer used")
private var download: DownloadManager? = null
@Deprecated("exoplayer download manager is no longer used")
private const val DOWNLOAD_CONTENT_DIRECTORY = "Anime_Downloads"
@Deprecated("exoplayer download manager is no longer used")
private var simpleCache: SimpleCache? = null
@Deprecated("exoplayer download manager is no longer used")
private var downloadDirectory: File? = null
}

View file

@ -22,9 +22,9 @@ import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.Refresh
import ani.dantotsu.bottomBar
import ani.dantotsu.connections.anilist.AniMangaSearchResults
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.AnilistAnimeViewModel
import ani.dantotsu.connections.anilist.AniMangaSearchResults
import ani.dantotsu.connections.anilist.getUserId
import ani.dantotsu.databinding.FragmentAnimeBinding
import ani.dantotsu.media.MediaAdaptor
@ -277,7 +277,8 @@ class AnimeFragment : Fragment() {
running = true
scope.launch {
withContext(Dispatchers.IO) {
Anilist.userid = PrefManager.getNullableVal<String>(PrefName.AnilistUserId, null)
Anilist.userid =
PrefManager.getNullableVal<String>(PrefName.AnilistUserId, null)
?.toIntOrNull()
if (Anilist.userid == null) {
getUserId(requireContext()) {

View file

@ -20,7 +20,6 @@ import androidx.viewpager2.widget.ViewPager2
import ani.dantotsu.MediaPageTransformer
import ani.dantotsu.R
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.AnilistSearch.SearchType.Companion.toAnilistString
import ani.dantotsu.databinding.ItemAnimePageBinding
import ani.dantotsu.databinding.LayoutTrendingBinding
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
recyclerView.adapter = adaptor
recyclerView.layoutManager =

View file

@ -469,7 +469,9 @@ class HomeFragment : Fragment() {
scope.launch {
withContext(Dispatchers.IO) {
// 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) {
withContext(Dispatchers.Main) {
getUserId(requireContext()) {

View file

@ -20,9 +20,9 @@ import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.Refresh
import ani.dantotsu.bottomBar
import ani.dantotsu.connections.anilist.AniMangaSearchResults
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.AnilistMangaViewModel
import ani.dantotsu.connections.anilist.AniMangaSearchResults
import ani.dantotsu.connections.anilist.getUserId
import ani.dantotsu.databinding.FragmentMangaBinding
import ani.dantotsu.media.MediaAdaptor
@ -169,7 +169,10 @@ class MangaFragment : Fragment() {
}
model.getPopularManga().observe(viewLifecycleOwner) {
if (it != null) {
mangaPageAdapter.updateTrendingManga(MediaAdaptor(0, it, requireActivity()), it)
mangaPageAdapter.updateTrendingManga(
MediaAdaptor(0, it, requireActivity()),
it
)
}
}
model.getPopularManhwa().observe(viewLifecycleOwner) {
@ -262,7 +265,8 @@ class MangaFragment : Fragment() {
running = true
scope.launch {
withContext(Dispatchers.IO) {
Anilist.userid = PrefManager.getNullableVal<String>(PrefName.AnilistUserId, null)
Anilist.userid =
PrefManager.getNullableVal<String>(PrefName.AnilistUserId, null)
?.toIntOrNull()
if (Anilist.userid == null) {
getUserId(requireContext()) {

View file

@ -58,6 +58,7 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
}
}
private fun findFirstNonMatch(watchedActivity: Set<Int>, activity: List<Activity>): Int {
for (activityItem in activity) {
if (activityItem.id !in watchedActivity) {
@ -86,6 +87,7 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
binding.stories.pause()
}
}
override fun onStoriesEnd() {
position += 1
if (position < activity.size) {
@ -115,6 +117,7 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
finish()
}
}
companion object {
var user: ArrayList<User> = arrayListOf()
}

View file

@ -262,8 +262,6 @@ class Stories @JvmOverloads constructor(
}
private fun rightPanelTouch() {
Logger.log("rightPanelTouch: $storyIndex")
if (storyIndex == activityList.size) {
@ -469,6 +467,7 @@ class Stories @JvmOverloads constructor(
}
}
}
private var startClickTime = 0L
private var startX = 0f
private var startY = 0f
@ -478,6 +477,7 @@ class Stories @JvmOverloads constructor(
onTouchView(view, event)
return true
}
private fun onTouchView(view: View, event: MotionEvent, isText: Boolean = false) {
val maxClickDuration = 200
val screenWidth = view.width
@ -492,6 +492,7 @@ class Stories @JvmOverloads constructor(
pause()
isLongPress = false
}
MotionEvent.ACTION_MOVE -> {
val deltaX = event.x - startX
val deltaY = event.y - startY
@ -499,6 +500,7 @@ class Stories @JvmOverloads constructor(
isLongPress = true
}
}
MotionEvent.ACTION_UP -> {
val clickDuration = Calendar.getInstance().timeInMillis - startClickTime
if (isText) {

View file

@ -76,10 +76,15 @@ class UserStatusAdapter(private val user: ArrayList<User>) :
setAnimation(b.root.context, b.root)
val user = user[position]
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 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
)
}

View file

@ -55,7 +55,11 @@ class CharacterAdapter(
).toBundle()
)
}
itemView.setOnLongClickListener { copyToClipboard(characterList[bindingAdapterPosition].name ?: ""); true }
itemView.setOnLongClickListener {
copyToClipboard(
characterList[bindingAdapterPosition].name ?: ""
); true
}
}
}
}

View file

@ -7,11 +7,9 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.buildMarkwon
import ani.dantotsu.currActivity
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) :
RecyclerView.Adapter<CharacterDetailsAdapter.GenreViewHolder>() {
@ -24,6 +22,8 @@ class CharacterDetailsAdapter(private val character: Character, private val acti
override fun onBindViewHolder(holder: GenreViewHolder, position: Int) {
val binding = holder.binding
val desc =
(if (character.id == 4004)
"![za wardo](https://media1.tenor.com/m/_z1tmCJnL2wAAAAd/za-warudo.gif) \n" else "") +
(if (character.age != "null") "${currActivity()!!.getString(R.string.age)} ${character.age}" else "") +
(if (character.dateOfBirth.toString() != "")
"${currActivity()!!.getString(R.string.birthday)} ${character.dateOfBirth.toString()}" else "") +
@ -41,8 +41,7 @@ class CharacterDetailsAdapter(private val character: Character, private val acti
} else "") + "\n" + character.description
binding.characterDesc.isTextSelectable
val markWon = Markwon.builder(activity).usePlugin(SoftBreakAddsNewLinePlugin.create())
.usePlugin(SpoilerPlugin()).build()
val markWon = buildMarkwon(activity)
markWon.setMarkdown(binding.characterDesc, desc.replace("~!", "||").replace("!~", "||"))
binding.voiceActorRecycler.adapter = AuthorAdapter(character.voiceActor ?: arrayListOf())
binding.voiceActorRecycler.layoutManager = LinearLayoutManager(

View file

@ -147,7 +147,7 @@ fun Media?.deleteFromList(
scope.launch {
withContext(Dispatchers.IO) {
this@deleteFromList?.let { media ->
val _id = id ?: Anilist.query.userMediaDetails(media).userListId;
val _id = id ?: Anilist.query.userMediaDetails(media).userListId
_id?.let { listId ->
try {
Anilist.mutation.deleteList(listId)

View file

@ -251,10 +251,12 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
fun total() {
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) {
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}") } }
append(
if (media.anime != null) getString(R.string.episodes_out_of) else getString(

View file

@ -100,6 +100,7 @@ class MediaDetailsViewModel : ViewModel() {
if (kitsuEpisodes.value == null) kitsuEpisodes.postValue(Kitsu.getKitsuEpisodesDetails(s))
}
}
private val anifyEpisodes: MutableLiveData<Map<String, Episode>> =
MutableLiveData<Map<String, Episode>>(null)

View file

@ -18,7 +18,6 @@ import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager
import java.util.ArrayList
class MediaListViewActivity : AppCompatActivity() {
private lateinit var binding: ActivityMediaListViewBinding
@ -52,7 +51,8 @@ class MediaListViewActivity: AppCompatActivity() {
binding.listAppBar.setBackgroundColor(primaryColor)
binding.listTitle.setTextColor(primaryTextColor)
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
val view = PrefManager.getCustomVal("mediaView", 0)
var mediaView: View = when (view) {

View file

@ -44,7 +44,10 @@ class MediaSocialAdapter(
profileUserName.text = user.name
profileInfo.apply {
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 ?: ""
}
visibility = View.VISIBLE
@ -63,10 +66,12 @@ class MediaSocialAdapter(
profileCompactProgressContainer.visibility = View.VISIBLE
profileUserAvatar.setOnClickListener {
ContextCompat.startActivity(root.context,
ContextCompat.startActivity(
root.context,
Intent(root.context, ProfileActivity::class.java)
.putExtra("userId", user.id),
null)
null
)
}
profileUserAvatarContainer.setOnLongClickListener {
ImageViewDialog.newInstance(

View file

@ -1,23 +1,15 @@
package ani.dantotsu.media
import android.app.Activity
import android.content.Intent
import android.view.View
import androidx.activity.ComponentActivity
import androidx.core.app.ActivityOptionsCompat
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.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.api.Query
import ani.dantotsu.databinding.ItemReviewsBinding
import ani.dantotsu.loadImage
import ani.dantotsu.openImage
import ani.dantotsu.others.ImageViewDialog
import ani.dantotsu.profile.ProfileActivity
import ani.dantotsu.profile.activity.ActivityItemBuilder
import ani.dantotsu.toast
@ -85,6 +77,7 @@ class ReviewAdapter(
override fun initializeViewBinding(view: View): ItemReviewsBinding {
return ItemReviewsBinding.bind(view)
}
private fun userVote(type: String) {
when (type) {
"NO_VOTE" -> {

View file

@ -20,7 +20,6 @@ import ani.dantotsu.initActivity
import ani.dantotsu.loadImage
import ani.dantotsu.navBarHeight
import ani.dantotsu.openImage
import ani.dantotsu.others.ImageViewDialog
import ani.dantotsu.profile.ProfileActivity
import ani.dantotsu.profile.activity.ActivityItemBuilder
import ani.dantotsu.statusBarHeight
@ -52,7 +51,8 @@ class ReviewViewActivity : AppCompatActivity() {
binding.userAvatar.loadImage(review.user?.avatar?.medium)
binding.userTime.text = ActivityItemBuilder.getDateTime(review.createdAt)
binding.userContainer.setOnClickListener {
startActivity(Intent(this, ProfileActivity::class.java)
startActivity(
Intent(this, ProfileActivity::class.java)
.putExtra("userId", review.user?.id)
)
}
@ -61,7 +61,8 @@ class ReviewViewActivity : AppCompatActivity() {
review.user?.avatar?.medium ?: ""
)
binding.userAvatar.setOnClickListener {
startActivity(Intent(this, ProfileActivity::class.java)
startActivity(
Intent(this, ProfileActivity::class.java)
.putExtra("userId", review.user?.id)
)
}

View file

@ -13,10 +13,10 @@ import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.connections.anilist.AniMangaSearchResults
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.AnilistSearch
import ani.dantotsu.connections.anilist.AnilistSearch.SearchType
import ani.dantotsu.connections.anilist.AniMangaSearchResults
import ani.dantotsu.connections.anilist.CharacterSearchResults
import ani.dantotsu.connections.anilist.StaffSearchResults
import ani.dantotsu.connections.anilist.StudioSearchResults
@ -377,7 +377,10 @@ class SearchActivity : AppCompatActivity() {
}
SearchType.CHARACTER -> {
characterAdaptor.notifyItemRangeRemoved(0, model.characterSearchResults.results.size)
characterAdaptor.notifyItemRangeRemoved(
0,
model.characterSearchResults.results.size
)
model.characterSearchResults.results.clear()
}

View file

@ -57,6 +57,7 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Sear
searchHistoryAdapter = SearchHistoryAdapter(type) {
binding.searchBarText.setText(it)
binding.searchBarText.setSelection(it.length)
}
binding.searchHistoryList.layoutManager = LinearLayoutManager(binding.root.context)
binding.searchHistoryList.adapter = searchHistoryAdapter

View file

@ -346,7 +346,9 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() {
binding.searchGenresGrid.isChecked = false
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()
chip.isChecked = selectedTags.contains(tag)
chip.isCloseIconVisible = exTags.contains(tag)

View file

@ -55,7 +55,11 @@ class StudioAdapter(
).toBundle()
)
}
itemView.setOnLongClickListener { copyToClipboard(studioList[bindingAdapterPosition].name ?: ""); true }
itemView.setOnLongClickListener {
copyToClipboard(
studioList[bindingAdapterPosition].name
); true
}
}
}
}

View file

@ -31,6 +31,7 @@ class SupportingSearchAdapter(private val activity: SearchActivity, private val
searchHistoryAdapter = SearchHistoryAdapter(type) {
binding.searchBarText.setText(it)
binding.searchBarText.setSelection(it.length)
}
binding.searchHistoryList.layoutManager = LinearLayoutManager(binding.root.context)
binding.searchHistoryList.adapter = searchHistoryAdapter

View file

@ -20,8 +20,8 @@ import ani.dantotsu.R
import ani.dantotsu.currActivity
import ani.dantotsu.currContext
import ani.dantotsu.databinding.DialogLayoutBinding
import ani.dantotsu.databinding.ItemMediaSourceBinding
import ani.dantotsu.databinding.ItemChipBinding
import ani.dantotsu.databinding.ItemMediaSourceBinding
import ani.dantotsu.displayTimer
import ani.dantotsu.isOnline
import ani.dantotsu.loadImage
@ -61,7 +61,8 @@ class AnimeWatchAdapter(
private var _binding: ItemMediaSourceBinding? = null
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)
}
@ -478,7 +479,8 @@ class AnimeWatchAdapter(
binding.sourceProgressBar.visibility = View.GONE
val sourceFound = media.anime.episodes!!.isNotEmpty()
val isDownloadedSource = watchSources[media.selected!!.sourceIndex] is OfflineAnimeParser
val isDownloadedSource =
watchSources[media.selected!!.sourceIndex] is OfflineAnimeParser
if (isDownloadedSource) {
binding.sourceNotFound.text = if (sourceFound) {
@ -487,7 +489,8 @@ class AnimeWatchAdapter(
currActivity()!!.getString(R.string.download_not_found)
}
} 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

View file

@ -1,7 +1,6 @@
package ani.dantotsu.media.anime
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
@ -28,10 +27,8 @@ import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import ani.dantotsu.FileUrl
import ani.dantotsu.R
import ani.dantotsu.addons.download.DownloadAddonManager
import ani.dantotsu.connections.anilist.api.MediaStreamingEpisode
import ani.dantotsu.databinding.FragmentMediaSourceBinding
import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager
@ -49,7 +46,6 @@ import ani.dantotsu.media.MediaType
import ani.dantotsu.navBarHeight
import ani.dantotsu.notifications.subscription.SubscriptionHelper
import ani.dantotsu.notifications.subscription.SubscriptionHelper.Companion.saveSubscription
import ani.dantotsu.others.Anify
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.parsers.AnimeParser
import ani.dantotsu.parsers.AnimeSources
@ -236,13 +232,16 @@ class AnimeWatchFragment : Fragment() {
episodes.forEach { (i, episode) ->
if (media.anime?.anifyEpisodes != null) {
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 ?: ""
).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
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!!.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 ?: ""
).isBlank()
) media.anime!!.kitsuEpisodes!![i]?.title ?: episode.title else episode.title
) media.anime!!.kitsuEpisodes!![i]?.title
?: episode.title else episode.title
?: media.anime!!.kitsuEpisodes!![i]?.title ?: episode.title
episode.thumb = media.anime!!.kitsuEpisodes!![i]?.thumb ?: episode.thumb
episode.thumb =
media.anime!!.kitsuEpisodes!![i]?.thumb ?: episode.thumb
}
}
}
@ -405,7 +407,8 @@ class AnimeWatchFragment : Fragment() {
selectedSetting = allSettings[which]
itemSelected = true
requireActivity().runOnUiThread {
val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
val fragment =
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
changeUIVisibility(true)
loadEpisodes(media.selected!!.sourceIndex, true)
}

View file

@ -1,6 +1,5 @@
package ani.dantotsu.media.anime
import android.app.AlertDialog
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -13,7 +12,6 @@ import androidx.media3.common.util.UnstableApi
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.connections.updateProgress
import ani.dantotsu.currContext
import ani.dantotsu.databinding.ItemEpisodeCompactBinding
import ani.dantotsu.databinding.ItemEpisodeGridBinding
import ani.dantotsu.databinding.ItemEpisodeListBinding

View file

@ -12,8 +12,6 @@ import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Color
import android.graphics.drawable.Animatable
import android.hardware.SensorManager
import android.media.AudioManager
@ -72,12 +70,10 @@ import androidx.media3.common.MimeTypes
import androidx.media3.common.PlaybackException
import androidx.media3.common.PlaybackParameters
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.TrackSelectionOverride
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.datasource.DataSource
import androidx.media3.datasource.DefaultDataSource
@ -137,11 +133,11 @@ import ani.dantotsu.others.AniSkip
import ani.dantotsu.others.AniSkip.getType
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.others.ResettableTimer
import ani.dantotsu.others.Xubtitle
import ani.dantotsu.others.getSerialized
import ani.dantotsu.parsers.AnimeSources
import ani.dantotsu.parsers.HAnimeSources
import ani.dantotsu.parsers.Subtitle
import ani.dantotsu.others.Xubtitle
import ani.dantotsu.parsers.SubtitleType
import ani.dantotsu.parsers.Video
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.material.slider.Slider
import com.lagradost.nicehttp.ignoreAllSSLErrors
import io.github.anilbeesetti.nextlib.media3ext.ffdecoder.NextRenderersFactory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
@ -171,7 +168,6 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import io.github.anilbeesetti.nextlib.media3ext.ffdecoder.NextRenderersFactory
import java.util.Calendar
import java.util.Locale
import java.util.Timer
@ -423,7 +419,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
false -> 0f
}
val textElevation = PrefManager.getVal<Float>(PrefName.SubBottomMargin) / 50 * resources.displayMetrics.heightPixels
val textElevation =
PrefManager.getVal<Float>(PrefName.SubBottomMargin) / 50 * resources.displayMetrics.heightPixels
textView.translationY = -textElevation
}
@ -1340,7 +1337,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
else -> mutableListOf()
}
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 {
timeInMillis = startTimestamp.timeInMillis
@ -1376,6 +1374,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
}
}
}
private fun initPlayer() {
checkNotch()
@ -1451,7 +1450,13 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
null -> {
when (episode.selectedSubtitle) {
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!!)
}
}
@ -1743,7 +1748,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
if (PrefManager.getVal<Boolean>(PrefName.TextviewSubtitles)) {
exoSubtitleView.visibility = View.GONE
customSubtitleView.visibility = View.VISIBLE
val newCues = cueGroup.cues.map { it.text.toString() ?: "" }
val newCues = cueGroup.cues.map { it.text.toString() }
if (newCues.isEmpty()) {
customSubtitleView.text = ""
@ -1755,7 +1760,9 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
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()
}

View file

@ -2,7 +2,6 @@ package ani.dantotsu.media.anime
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.DialogInterface
@ -564,6 +563,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
snackString(R.string.no_video_selected)
}
}
fun checkAudioTracks() {
val audioTracks = extractor.audioTracks.map { it.lang }
if (audioTracks.isNotEmpty()) {
@ -574,7 +574,10 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
setTitle(R.string.download_audio_tracks)
multiChoiceItems(audioNamesArray, checkedItems) {
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) {
selectedAudioTracks.add(audioPair)
} else {
@ -606,7 +609,8 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
setTitle(R.string.download_subtitle)
multiChoiceItems(subtitleNamesArray, checkedItems) {
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) {
selectedSubtitles.add(subtitlePair)
} else {

View file

@ -63,8 +63,12 @@ class TrackGroupDialogFragment(
override fun onBindViewHolder(holder: StreamViewHolder, position: Int) {
val binding = holder.binding
trackGroups[position].let { trackGroup ->
if (overrideTrackNames?.getOrNull(position - (trackGroups.size - (overrideTrackNames?.size?:0))) != null) {
val pair = overrideTrackNames!![position - (trackGroups.size - overrideTrackNames!!.size)]
if (overrideTrackNames?.getOrNull(
position - (trackGroups.size - (overrideTrackNames?.size ?: 0))
) != null
) {
val pair =
overrideTrackNames!![position - (trackGroups.size - overrideTrackNames!!.size)]
binding.subtitleTitle.text =
"[${pair.second}] ${pair.first}"
} else when (val language = trackGroup.getTrackFormat(0).language?.lowercase()) {

View file

@ -15,7 +15,6 @@ import ani.dantotsu.databinding.ItemCommentsBinding
import ani.dantotsu.getAppString
import ani.dantotsu.loadImage
import ani.dantotsu.openImage
import ani.dantotsu.others.ImageViewDialog
import ani.dantotsu.profile.ProfileActivity
import ani.dantotsu.setAnimation
import ani.dantotsu.snackString

View file

@ -2,7 +2,6 @@ package ani.dantotsu.media.comments
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Context.INPUT_METHOD_SERVICE
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
@ -12,7 +11,6 @@ import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import androidx.appcompat.widget.PopupMenu
import androidx.core.animation.doOnEnd
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.PrefName
import ani.dantotsu.snackString
import ani.dantotsu.toast
import ani.dantotsu.util.Logger
import ani.dantotsu.util.customAlertDialog
import com.xwray.groupie.GroupieAdapter

View file

@ -1,6 +1,5 @@
package ani.dantotsu.media.manga
import android.app.AlertDialog
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

View file

@ -22,8 +22,8 @@ import ani.dantotsu.currActivity
import ani.dantotsu.currContext
import ani.dantotsu.databinding.CustomDialogLayoutBinding
import ani.dantotsu.databinding.DialogLayoutBinding
import ani.dantotsu.databinding.ItemMediaSourceBinding
import ani.dantotsu.databinding.ItemChipBinding
import ani.dantotsu.databinding.ItemMediaSourceBinding
import ani.dantotsu.isOnline
import ani.dantotsu.loadImage
import ani.dantotsu.media.Media
@ -75,7 +75,8 @@ class MangaReadAdapter(
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)
}
@ -331,12 +332,17 @@ class MangaReadAdapter(
val checkBox = CheckBox(currContext()).apply {
text = option
setOnCheckedChangeListener { _, _ ->
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
tickAllButton.setImageResource(
getToggleImageResource(
checkboxContainer
)
)
}
}
if (media.selected!!.scanlators != null) {
checkBox.isChecked = media.selected!!.scanlators?.contains(option) != true
checkBox.isChecked =
media.selected!!.scanlators?.contains(option) != true
scanlatorSelectionListener?.onScanlatorsSelected()
} else {
checkBox.isChecked = true
@ -488,10 +494,12 @@ class MangaReadAdapter(
}
}
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 }) {
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
handleProgress(
binding.itemMediaProgressCont,
@ -501,9 +509,11 @@ class MangaReadAdapter(
continueEp!!.number
)
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) {
continueEp = media.manga.chapters!![formattedChapters[numberPlusOne].second]
continueEp =
media.manga.chapters!![formattedChapters[numberPlusOne].second]
}
}
binding.itemMediaImage.loadImage(media.banner ?: media.cover)
@ -530,7 +540,8 @@ class MangaReadAdapter(
binding.sourceProgressBar.visibility = View.GONE
val sourceFound = filteredChapters.isNotEmpty()
val isDownloadedSource = mangaReadSources[media.selected!!.sourceIndex] is OfflineMangaParser
val isDownloadedSource =
mangaReadSources[media.selected!!.sourceIndex] is OfflineMangaParser
if (isDownloadedSource) {
binding.sourceNotFound.text = if (sourceFound) {
@ -539,7 +550,8 @@ class MangaReadAdapter(
currActivity()!!.getString(R.string.download_not_found)
}
} 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

View file

@ -261,7 +261,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
val chapters = loadedChapters[media.selected!!.sourceIndex]
if (chapters != null) {
headerAdapter.options = getScanlators(chapters)
val filteredChapters = if (model.mangaReadSources?.get(media.selected!!.sourceIndex) is OfflineMangaParser) {
val filteredChapters =
if (model.mangaReadSources?.get(media.selected!!.sourceIndex) is OfflineMangaParser) {
chapters
} else {
chapters.filterNot { (_, chapter) ->
@ -397,7 +398,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
selectedSetting = allSettings[which]
itemSelected = true
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
val fragment =
MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
changeUIVisibility(true)
loadChapters(media.selected!!.sourceIndex, true)
}
@ -590,7 +592,9 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
// Find latest chapter for subscription
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 =
media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest

View file

@ -78,7 +78,8 @@ class ChapterLoaderDialog : BottomSheetDialogFragment() {
_binding = BottomSheetSelectorBinding.inflate(inflater, container, false)
val window = dialog?.window
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
}

View file

@ -2,7 +2,6 @@ package ani.dantotsu.media.manga.mangareader
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
@ -58,8 +57,6 @@ import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaDetailsViewModel
import ani.dantotsu.media.MediaNameAdapter
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.MangaChapter
import ani.dantotsu.others.ImageViewDialog
@ -196,7 +193,8 @@ class MangaReaderActivity : AppCompatActivity() {
finish()
return@addCallback
}
val chapter = (MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!.number)
val chapter =
(MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!.number)
?.minus(1L) ?: 0).toString()
if (chapter == "0.0" && PrefManager.getVal(PrefName.ChapterZeroReader)
// Not asking individually or incognito

View file

@ -55,6 +55,7 @@ class Swipy @JvmOverloads constructor(
else
VerticalPosition.Top
}
!it.canScrollVertically(1) -> VerticalPosition.Bottom
!it.canScrollVertically(-1) -> VerticalPosition.Top
else -> VerticalPosition.None
@ -67,6 +68,7 @@ class Swipy @JvmOverloads constructor(
else
HorizontalPosition.Left
}
!it.canScrollHorizontally(1) -> HorizontalPosition.Right
!it.canScrollHorizontally(-1) -> HorizontalPosition.Left
else -> HorizontalPosition.None
@ -97,12 +99,14 @@ class Swipy @JvmOverloads constructor(
initialDown = if (vertical) ev.getY(0) else ev.getX(0)
isBeingDragged = false
}
MotionEvent.ACTION_MOVE -> {
val pointerIndex = ev.findPointerIndex(activePointerId)
if (pointerIndex >= 0) {
startDragging(if (vertical) ev.getY(pointerIndex) else ev.getX(pointerIndex))
}
}
MotionEvent.ACTION_POINTER_UP -> onSecondaryPointerUp(ev)
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
isBeingDragged = false
@ -122,6 +126,7 @@ class Swipy @JvmOverloads constructor(
activePointerId = ev.getPointerId(0)
isBeingDragged = false
}
MotionEvent.ACTION_MOVE -> {
pointerIndex = ev.findPointerIndex(activePointerId)
if (pointerIndex >= 0) {
@ -130,25 +135,33 @@ class Swipy @JvmOverloads constructor(
if (isBeingDragged) handleDrag(pos)
}
}
MotionEvent.ACTION_POINTER_DOWN -> {
pointerIndex = ev.actionIndex
if (pointerIndex >= 0) activePointerId = ev.getPointerId(pointerIndex)
}
MotionEvent.ACTION_POINTER_UP -> onSecondaryPointerUp(ev)
MotionEvent.ACTION_UP -> {
resetSwipes()
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
return false
}
MotionEvent.ACTION_CANCEL -> return false
}
return true
}
private fun startDragging(pos: Float) {
val posDiff = if ((vertical && verticalPos == VerticalPosition.Top) || (!vertical && horizontalPos == HorizontalPosition.Left))
val posDiff =
if ((vertical && verticalPos == VerticalPosition.Top) || (!vertical && horizontalPos == HorizontalPosition.Left))
pos - initialDown
else
initialDown - pos

View file

@ -14,8 +14,6 @@ import ani.dantotsu.setAnimation
import ani.dantotsu.snackString
import ani.dantotsu.util.Logger
import ani.dantotsu.util.customAlertDialog
import com.bumptech.glide.Glide
import com.bumptech.glide.load.model.GlideUrl
class NovelResponseAdapter(
val fragment: NovelReadFragment,
@ -41,7 +39,8 @@ class NovelResponseAdapter(
setAnimation(fragment.requireContext(), holder.binding.root)
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.itemEpisodeFiller.text =
if (downloadedCheckCallback.downloadedCheck(novel)) {

View file

@ -5,7 +5,6 @@ import ani.dantotsu.currContext
import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaNameAdapter
import ani.dantotsu.media.Selected
import ani.dantotsu.media.emptyMedia
import ani.dantotsu.parsers.AnimeParser
import ani.dantotsu.parsers.AnimeSources
import ani.dantotsu.parsers.BaseParser
@ -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(
id = subscribeMedia.id,
name = null,

View file

@ -127,8 +127,10 @@ class SubscriptionNotificationTask : Task {
banner = media.banner
)
)
PrefManager.setVal(PrefName.UnreadCommentNotifications,
PrefManager.getVal<Int>(PrefName.UnreadCommentNotifications) + 1)
PrefManager.setVal(
PrefName.UnreadCommentNotifications,
PrefManager.getVal<Int>(PrefName.UnreadCommentNotifications) + 1
)
val notification = createNotification(
context.applicationContext,
media,

View file

@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.Fragment
import ani.dantotsu.R

View file

@ -24,6 +24,7 @@ object Anify {
)
} ?: emptyMap()
}
@Serializable
data class AnifyElement(
@SerialName("providerId")

View file

@ -1,4 +1,3 @@
package ani.dantotsu.parsers
import android.graphics.drawable.Drawable
@ -6,7 +5,6 @@ import ani.dantotsu.FileUrl
import ani.dantotsu.R
import ani.dantotsu.currContext
import ani.dantotsu.media.Media
import ani.dantotsu.okHttpClient
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.util.Logger
import eu.kanade.tachiyomi.animesource.model.SAnime

View file

@ -266,8 +266,10 @@ class ExtensionTestItem(
)
binding.searchResultText.isVisible = true
if (searchResultData.size == 0) {
val text = context.getString(R.string.title_search_test,
context.getString(R.string.no_results_found))
val text = context.getString(
R.string.title_search_test,
context.getString(R.string.no_results_found)
)
binding.searchResultText.text = text
binding.searchResultText.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.ic_circle_cancel, 0, 0, 0
@ -277,8 +279,10 @@ class ExtensionTestItem(
)
return
}
val text = context.getString(R.string.title_search_test,
context.getString(R.string.results_found, searchResultData.size.toString()))
val text = context.getString(
R.string.title_search_test,
context.getString(R.string.results_found, searchResultData.size.toString())
)
binding.searchResultText.text = text + "\n${searchResultData.time}ms"
binding.searchResultText.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.ic_circle_check, 0, 0, 0
@ -298,12 +302,20 @@ class ExtensionTestItem(
binding.episodeResultText.isVisible = true
if (episodeResultData.size == 0) {
val text = when (extensionType) {
"anime" -> context.getString(R.string.episode_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))
"anime" -> context.getString(
R.string.episode_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.setCompoundDrawablesWithIntrinsicBounds(
@ -315,12 +327,20 @@ class ExtensionTestItem(
return
}
val text = when (extensionType) {
"anime" -> context.getString(R.string.episode_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()))
"anime" -> context.getString(
R.string.episode_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.setCompoundDrawablesWithIntrinsicBounds(
@ -349,12 +369,20 @@ class ExtensionTestItem(
binding.serverResultText.isVisible = true
if (serverResultData.size == 0) {
val text = when (extensionType) {
"anime" -> context.getString(R.string.video_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))
"anime" -> context.getString(
R.string.video_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.setCompoundDrawablesWithIntrinsicBounds(
@ -366,12 +394,20 @@ class ExtensionTestItem(
return
}
val text = when (extensionType) {
"anime" -> context.getString(R.string.video_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()))
"anime" -> context.getString(
R.string.video_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.setCompoundDrawablesWithIntrinsicBounds(

View file

@ -73,6 +73,7 @@ class ParserTestActivity : AppCompatActivity() {
}
}
}
"manga" -> {
ExtensionTestSettingsBottomDialog.extensionsToTest.forEach { name ->
val extension =
@ -89,6 +90,7 @@ class ParserTestActivity : AppCompatActivity() {
}
}
}
"novel" -> {
ExtensionTestSettingsBottomDialog.extensionsToTest.forEach { name ->
val extension =

View file

@ -120,8 +120,10 @@ class NovelExtensionManager(private val context: Context) {
* @param extension The anime extension to be installed.
*/
fun installExtension(extension: NovelExtension.Available): Observable<InstallStep> {
return installer.downloadAndInstall(api.getNovelApkUrl(extension), extension.pkgName,
extension.name, MediaType.NOVEL)
return installer.downloadAndInstall(
api.getNovelApkUrl(extension), extension.pkgName,
extension.name, MediaType.NOVEL
)
}
/**

View file

@ -53,7 +53,8 @@ class ChartBuilder {
scrollPos: Float? = null,
normalize: Boolean = false
): 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 aaChartType = passedAaChartType
var categories = passedCategories
@ -303,7 +304,8 @@ class ChartBuilder {
}
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(
AAColor.rgbaColor(
Color.red(backgroundColor),
@ -312,7 +314,8 @@ class ChartBuilder {
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(
AAColor.rgbaColor(
Color.red(colorOnBackground),

View file

@ -156,17 +156,28 @@ class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListene
openLinkInBrowser(getString(R.string.anilist_link, user.name))
true
}
R.id.action_share_profile -> {
val shareIntent = Intent(Intent.ACTION_SEND)
shareIntent.type = "text/plain"
shareIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.anilist_link, user.name))
startActivity(Intent.createChooser(shareIntent, "Share Profile"))
shareIntent.putExtra(
Intent.EXTRA_TEXT,
getString(R.string.anilist_link, user.name)
)
startActivity(
Intent.createChooser(
shareIntent,
"Share Profile"
)
)
true
}
R.id.action_copy_user_id -> {
copyToClipboard(user.id.toString(), true)
true
}
else -> false
}
}

View file

@ -16,8 +16,8 @@ import ani.dantotsu.profile.User
import ani.dantotsu.profile.UsersDialogFragment
import ani.dantotsu.setAnimation
import ani.dantotsu.snackString
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
import ani.dantotsu.util.ActivityMarkdownCreator
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
import com.xwray.groupie.GroupieAdapter
import com.xwray.groupie.viewbinding.BindableItem
import kotlinx.coroutines.CoroutineScope
@ -55,7 +55,12 @@ class ActivityItem(
.show((context as FragmentActivity).supportFragmentManager, "replies")
}
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 {
UsersDialogFragment().apply {
userList(userList)
@ -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 {
scope.launch {
val res = Anilist.mutation.deleteActivity(activity.id)
@ -161,7 +167,8 @@ class ActivityItem(
"MessageActivity" -> {
binding.activityBannerContainer.visibility = View.GONE
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) {
val markwon = buildMarkwon(context, false)
markwon.setMarkdown(

View file

@ -14,8 +14,8 @@ import ani.dantotsu.loadImage
import ani.dantotsu.profile.User
import ani.dantotsu.profile.UsersDialogFragment
import ani.dantotsu.snackString
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
import ani.dantotsu.util.ActivityMarkdownCreator
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
import com.xwray.groupie.GroupieAdapter
import com.xwray.groupie.viewbinding.BindableItem
import kotlinx.coroutines.CoroutineScope

View file

@ -1,26 +1,21 @@
package ani.dantotsu.profile.activity
import android.content.res.Configuration
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.updateLayoutParams
import androidx.core.view.updateMargins
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import ani.dantotsu.R
import ani.dantotsu.databinding.ActivityFeedBinding
import ani.dantotsu.databinding.ActivityNotificationBinding
import ani.dantotsu.initActivity
import ani.dantotsu.navBarHeight
import ani.dantotsu.profile.activity.ActivityFragment.Companion.ActivityType
import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.profile.activity.ActivityFragment.Companion.ActivityType
import ani.dantotsu.profile.notification.NotificationActivity
import nl.joery.animatedbottombar.AnimatedBottomBar
class FeedActivity : AppCompatActivity() {
@ -50,9 +45,12 @@ class FeedActivity : AppCompatActivity() {
binding.notificationBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
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.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle, getOne)
binding.notificationViewPager.adapter =
ViewPagerAdapter(supportFragmentManager, lifecycle, getOne)
binding.notificationViewPager.setOffscreenPageLimit(4)
binding.notificationViewPager.setCurrentItem(selected, false)
navBar.selectTabAt(selected)
@ -83,7 +81,11 @@ class FeedActivity : AppCompatActivity() {
override fun createFragment(position: Int): Fragment {
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)
}
}

View file

@ -9,17 +9,20 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import ani.dantotsu.R
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.databinding.ActivityNotificationBinding
import ani.dantotsu.initActivity
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.themes.ThemeManager
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.*
import ani.dantotsu.profile.notification.NotificationFragment.Companion.newInstance
import nl.joery.animatedbottombar.AnimatedBottomBar
class NotificationActivity : AppCompatActivity() {
@ -58,7 +61,8 @@ class NotificationActivity : AppCompatActivity() {
val getOne = intent.getIntExtra("activityId", -1)
if (getOne != -1) navBar.isVisible = 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)
navBar.selectTabAt(selected)
navBar.setOnTabSelectListener(object : AnimatedBottomBar.OnTabSelectListener {

View file

@ -60,7 +60,8 @@ class NotificationItem(
PrefName.SubscriptionNotificationStore,
null
) ?: 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)
parentAdapter.remove(this@NotificationItem)
}

View file

@ -110,7 +110,8 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
binding.repositoryInput.setOnEditorActionListener { textView, action, keyEvent ->
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()
if (url.isNotBlank()) {
val error = isValidUrl(url)
@ -215,6 +216,7 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
Injekt.get<AnimeExtensionManager>().findAvailableExtensions()
}
}
MediaType.MANGA -> {
val manga =
PrefManager.getVal<Set<String>>(PrefName.MangaExtensionRepos)
@ -224,6 +226,7 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
Injekt.get<MangaExtensionManager>().findAvailableExtensions()
}
}
MediaType.NOVEL -> {
val novel =
PrefManager.getVal<Set<String>>(PrefName.NovelExtensionRepos)
@ -247,6 +250,7 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
Injekt.get<AnimeExtensionManager>().findAvailableExtensions()
}
}
MediaType.MANGA -> {
val manga =
PrefManager.getVal<Set<String>>(PrefName.MangaExtensionRepos)
@ -256,6 +260,7 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
Injekt.get<MangaExtensionManager>().findAvailableExtensions()
}
}
MediaType.NOVEL -> {
val novel =
PrefManager.getVal<Set<String>>(PrefName.NovelExtensionRepos)

View file

@ -56,7 +56,8 @@ class AnilistSettingsActivity : AppCompatActivity() {
}
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.setAdapter(
@ -78,7 +79,9 @@ class AnilistSettingsActivity : AppCompatActivity() {
}
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.setAdapter(
@ -99,7 +102,8 @@ class AnilistSettingsActivity : AppCompatActivity() {
settingsAnilistStaffLanguage.clearFocus()
}
val currentMergeTimeDisplay = activityMergeTimeMap.entries.firstOrNull { it.value == Anilist.activityMergeTime }?.key
val currentMergeTimeDisplay =
activityMergeTimeMap.entries.firstOrNull { it.value == Anilist.activityMergeTime }?.key
?: "${Anilist.activityMergeTime} mins"
settingsAnilistActivityMergeTime.setText(currentMergeTimeDisplay)
settingsAnilistActivityMergeTime.setAdapter(
@ -117,7 +121,8 @@ class AnilistSettingsActivity : AppCompatActivity() {
}
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.setAdapter(
ArrayAdapter(context, R.layout.item_dropdown, scoreFormats)
@ -139,7 +144,8 @@ class AnilistSettingsActivity : AppCompatActivity() {
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.setAdapter(
ArrayAdapter(context, R.layout.item_dropdown, rowOrderMap.keys.toList())
@ -155,7 +161,8 @@ class AnilistSettingsActivity : AppCompatActivity() {
settingsAnilistRowOrder.clearFocus()
}
val containers = listOf(binding.animeCustomListsContainer, binding.mangaCustomListsContainer)
val containers =
listOf(binding.animeCustomListsContainer, binding.mangaCustomListsContainer)
val customLists = listOf(Anilist.animeCustomLists, Anilist.mangaCustomLists)
val buttons = listOf(binding.addAnimeListButton, binding.addMangaListButton)
@ -175,7 +182,8 @@ class AnilistSettingsActivity : AppCompatActivity() {
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.setAdapter(
ArrayAdapter(context, R.layout.item_dropdown, Anilist.timeZone)

View file

@ -169,8 +169,12 @@ class ExtensionsActivity : AppCompatActivity() {
customAlertDialog().apply {
setTitle("Language")
singleChoiceItems(languageOptions, index) { selected ->
PrefManager.setVal(PrefName.LangSort, LanguageMapper.Companion.Language.entries[selected].code)
val currentFragment = supportFragmentManager.findFragmentByTag("f${viewPager.currentItem}")
PrefManager.setVal(
PrefName.LangSort,
LanguageMapper.Companion.Language.entries[selected].code
)
val currentFragment =
supportFragmentManager.findFragmentByTag("f${viewPager.currentItem}")
if (currentFragment is SearchQueryHandler) {
currentFragment.notifyDataChanged()
}

View file

@ -70,7 +70,7 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
if (allSettings.isNotEmpty()) {
var selectedSetting = allSettings[0]
if (allSettings.size > 1) {
val names = allSettings.map { LanguageMapper.getLanguageName(it.lang) }
val names = allSettings.map { getLanguageName(it.lang) }
.toTypedArray()
var selectedIndex = 0
requireContext().customAlertDialog().apply {

View file

@ -290,7 +290,8 @@ class PlayerSettingsActivity :
PrefManager.setVal(PrefName.UseInternalCast, isChecked)
}
binding.playerSettingsAdditionalCodec.isChecked = PrefManager.getVal(PrefName.UseAdditionalCodec)
binding.playerSettingsAdditionalCodec.isChecked =
PrefManager.getVal(PrefName.UseAdditionalCodec)
binding.playerSettingsAdditionalCodec.setOnCheckedChangeListener { _, isChecked ->
PrefManager.setVal(PrefName.UseAdditionalCodec, isChecked)
}

View file

@ -6,9 +6,9 @@ import android.view.View
import android.view.ViewGroup
import ani.dantotsu.BottomSheetDialogFragment
import ani.dantotsu.databinding.BottomSheetProxyBinding
import ani.dantotsu.restartApp
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.restartApp
class ProxyDialogFragment : BottomSheetDialogFragment() {
private var _binding: BottomSheetProxyBinding? = null
@ -16,8 +16,10 @@ class ProxyDialogFragment : BottomSheetDialogFragment() {
private var proxyHost: String? = PrefManager.getVal<String>(PrefName.Socks5ProxyHost).orEmpty()
private var proxyPort: String? = PrefManager.getVal<String>(PrefName.Socks5ProxyPort).orEmpty()
private var proxyUsername: String? = PrefManager.getVal<String>(PrefName.Socks5ProxyUsername).orEmpty()
private var proxyPassword: String? = PrefManager.getVal<String>(PrefName.Socks5ProxyPassword).orEmpty()
private var proxyUsername: String? =
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 val proxyEnabled: Boolean = PrefManager.getVal<Boolean>(PrefName.EnableSocks5Proxy)

View file

@ -142,8 +142,10 @@ class SettingsAboutActivity : AppCompatActivity() {
icon = R.drawable.ic_incognito_24,
onClick = {
val text = TextView(context)
val pPLink = "https://raw.githubusercontent.com/rebelonion/Dantotsu/main/privacy_policy.md"
val backup = "https://gcore.jsdelivr.net/gh/rebelonion/dantotsu/privacy_policy.md"
val pPLink =
"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)
val markWon = try {
buildMarkwon(this@SettingsAboutActivity, false)

View file

@ -252,6 +252,7 @@ class SettingsAccountActivity : AppCompatActivity() {
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
}
fun reload() {
snackString(getString(R.string.restart_app_extra))
//snackString(R.string.restart_app_extra)

View file

@ -11,8 +11,8 @@ import androidx.recyclerview.widget.LinearLayoutManager
import ani.dantotsu.R
import ani.dantotsu.addons.AddonDownloader
import ani.dantotsu.addons.download.DownloadAddonManager
import ani.dantotsu.addons.torrent.TorrentServerService
import ani.dantotsu.addons.torrent.TorrentAddonManager
import ani.dantotsu.addons.torrent.TorrentServerService
import ani.dantotsu.databinding.ActivitySettingsAddonsBinding
import ani.dantotsu.databinding.ItemSettingsBinding
import ani.dantotsu.initActivity

View file

@ -8,8 +8,6 @@ import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.ArrayAdapter
import android.widget.CheckBox
import android.widget.EditText
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricManager

View file

@ -59,7 +59,8 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
super.onViewCreated(view, savedInstanceState)
val window = dialog?.window
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) {
R.drawable.ic_round_notifications_active_24
} else {

View file

@ -26,11 +26,8 @@ import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.util.customAlertDialog
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.api.get
import uy.kohesive.injekt.injectLazy
class SettingsExtensionsActivity : AppCompatActivity() {
private lateinit var binding: ActivitySettingsExtensionsBinding

View file

@ -1,6 +1,5 @@
package ani.dantotsu.settings
import android.app.AlertDialog
import android.content.Intent
import android.os.Bundle
import android.view.View

View file

@ -82,9 +82,18 @@ class SettingsNotificationActivity : AppCompatActivity() {
setTitle(R.string.subscriptions_checking_time)
singleChoiceItems(timeNames, curTime) { i ->
curTime = i
it.settingsTitle.text = getString(R.string.subscriptions_checking_time_s, timeNames[i])
PrefManager.setVal(PrefName.SubscriptionNotificationInterval, curTime)
TaskScheduler.create(context, PrefManager.getVal(PrefName.UseAlarmManager)).scheduleAllTasks(context)
it.settingsTitle.text = getString(
R.string.subscriptions_checking_time_s,
timeNames[i]
)
PrefManager.setVal(
PrefName.SubscriptionNotificationInterval,
curTime
)
TaskScheduler.create(
context,
PrefManager.getVal(PrefName.UseAlarmManager)
).scheduleAllTasks(context)
}
show()
}
@ -125,7 +134,8 @@ class SettingsNotificationActivity : AppCompatActivity() {
types.map { name ->
name.replace("_", " ").lowercase().replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString()
} }.toTypedArray(),
}
}.toTypedArray(),
selected
) { _, which, isChecked ->
val type = types[which]

View file

@ -47,7 +47,8 @@ class SettingsThemeActivity : AppCompatActivity(), SimpleDialog.OnDialogResultLi
val mainIntent = Intent.makeRestartActivityTask(
packageManager.getLaunchIntentForPackage(packageName)!!.component
)
val component = ComponentName(packageName, SettingsActivity::class.qualifiedName!!)
val component =
ComponentName(packageName, SettingsActivity::class.qualifiedName!!)
try {
startActivity(Intent().setComponent(component))
} catch (e: Exception) {

View file

@ -41,5 +41,6 @@ class SubscriptionItem(
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)
}

View file

@ -1,6 +1,5 @@
package ani.dantotsu.settings
import android.app.AlertDialog
import android.content.Context
import android.graphics.drawable.Drawable
import android.view.View
@ -36,7 +35,8 @@ class SubscriptionSource(
true
}
binding.extensionIconImageView.visibility = View.VISIBLE
val layoutParams = binding.extensionIconImageView.layoutParams as ViewGroup.MarginLayoutParams
val layoutParams =
binding.extensionIconImageView.layoutParams as ViewGroup.MarginLayoutParams
layoutParams.leftMargin = 28
binding.extensionIconImageView.layoutParams = layoutParams
@ -55,7 +55,8 @@ class SubscriptionSource(
private fun updateSubscriptionCount() {
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) {
@ -96,7 +97,9 @@ class SubscriptionSource(
val startPosition = adapter.getAdapterPosition(this) + 1
if (isExpanded) {
subscriptions.forEachIndexed { index, subscribeMedia ->
adapter.add(startPosition + index, SubscriptionItem(subscribeMedia.id, subscribeMedia, adapter) { removedId ->
adapter.add(
startPosition + index,
SubscriptionItem(subscribeMedia.id, subscribeMedia, adapter) { removedId ->
removeSubscription(removedId)
})
}
@ -109,5 +112,6 @@ class SubscriptionSource(
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)
}

View file

@ -67,10 +67,13 @@ class SubscriptionsBottomDialog : BottomSheetDialogFragment() {
return when {
animeExtension.installedExtensionsFlow.value.any { it.name == parserName } ->
animeExtension.installedExtensionsFlow.value.find { it.name == parserName }?.icon
mangaExtensions.installedExtensionsFlow.value.any { it.name == parserName } ->
mangaExtensions.installedExtensionsFlow.value.find { it.name == parserName }?.icon
novelExtensions.installedExtensionsFlow.value.any { it.name == parserName } ->
novelExtensions.installedExtensionsFlow.value.find { it.name == parserName }?.icon
else -> null
}
}

View file

@ -1,6 +1,5 @@
package ani.dantotsu.settings
import android.app.AlertDialog
import android.os.Bundle
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
@ -43,7 +42,8 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
setTitle(getString(R.string.home_layout_show))
multiChoiceItems(
items = views,
checkedItems = PrefManager.getVal<List<Boolean>>(PrefName.HomeLayout).toBooleanArray()
checkedItems = PrefManager.getVal<List<Boolean>>(PrefName.HomeLayout)
.toBooleanArray()
) { selectedItems ->
for (i in selectedItems.indices) {
set[i] = selectedItems[i]
@ -69,7 +69,8 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
PrefManager.setVal(PrefName.ImmersiveMode, isChecked)
restartApp()
}
binding.uiSettingsHideRedDot.isChecked = !PrefManager.getVal<Boolean>(PrefName.ShowNotificationRedDot)
binding.uiSettingsHideRedDot.isChecked =
!PrefManager.getVal<Boolean>(PrefName.ShowNotificationRedDot)
binding.uiSettingsHideRedDot.setOnCheckedChangeListener { _, isChecked ->
PrefManager.setVal(PrefName.ShowNotificationRedDot, !isChecked)
}

View file

@ -2,13 +2,7 @@ package ani.dantotsu.settings.extensionprefs
import android.content.Context
import android.content.SharedPreferences
import android.graphics.Typeface
import android.os.Build
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.lifecycle.lifecycleScope
import androidx.preference.DialogPreference
@ -38,10 +32,12 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() {
preferenceManager.createPreferenceScreen(requireContext())
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ThemeManager(requireActivity()).applyTheme()
}
private var onCloseAction: (() -> Unit)? = null
override fun onDestroyView() {
@ -104,7 +100,8 @@ class InitialAnimeSourcePreferencesFragment(
preferenceManager.createPreferenceScreen(requireContext())
}
//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 file

@ -203,7 +203,13 @@ enum class PrefName(val data: Pref) {
LogToFile(Pref(Location.Irrelevant, Boolean::class, false)),
RecentGlobalNotification(Pref(Location.Irrelevant, Int::class, 0)),
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)),
DownloadsDir(Pref(Location.Irrelevant, String::class, "")),
OC(Pref(Location.Irrelevant, Boolean::class, false)),

View file

@ -5,9 +5,9 @@ import android.content.Context
import android.content.res.Configuration
import android.graphics.Bitmap
import android.os.Build
import android.view.View
import android.view.Window
import android.view.WindowManager
import android.view.View
import ani.dantotsu.R
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName

View file

@ -140,6 +140,7 @@ class ActivityMarkdownCreator : AppCompatActivity() {
} else {
Anilist.mutation.postReply(parentId, text)
}
"message" -> if (isEdit) {
Anilist.mutation.postMessage(userId, text, editId)
} else {

View file

@ -30,10 +30,12 @@ class AlertDialogBuilder(private val context: Context) {
this.cancelable = cancelable
return this
}
fun setOnShowListener(onShow: () -> Unit): AlertDialogBuilder {
this.onShow = onShow
return this
}
fun setOnCancelListener(onCancel: () -> Unit): AlertDialogBuilder {
this.onCancel = onCancel
return this
@ -63,6 +65,7 @@ class AlertDialogBuilder(private val context: Context) {
this.customView = view
return this
}
fun setCustomView(layoutResId: Int): AlertDialogBuilder {
this.customView = View.inflate(context, layoutResId, null)
return this
@ -74,7 +77,11 @@ class AlertDialogBuilder(private val context: Context) {
return this
}
fun setPosButton(int: Int, formatArgs: Int? = null, onClick: (() -> Unit)? = null): AlertDialogBuilder {
fun setPosButton(
int: Int,
formatArgs: Int? = null,
onClick: (() -> Unit)? = null
): AlertDialogBuilder {
this.posButtonTitle = context.getString(int, formatArgs)
this.onPositiveButtonClick = onClick
return this
@ -86,7 +93,11 @@ class AlertDialogBuilder(private val context: Context) {
return this
}
fun setNegButton(int: Int, formatArgs: Int? = null, onClick: (() -> Unit)? = null): AlertDialogBuilder {
fun setNegButton(
int: Int,
formatArgs: Int? = null,
onClick: (() -> Unit)? = null
): AlertDialogBuilder {
this.negButtonTitle = context.getString(int, formatArgs)
this.onNegativeButtonClick = onClick
return this
@ -98,7 +109,11 @@ class AlertDialogBuilder(private val context: Context) {
return this
}
fun setNeutralButton(int: Int, formatArgs: Int? = null, onClick: (() -> Unit)? = null): AlertDialogBuilder {
fun setNeutralButton(
int: Int,
formatArgs: Int? = null,
onClick: (() -> Unit)? = null
): AlertDialogBuilder {
this.neutralButtonTitle = context.getString(int, formatArgs)
this.onNeutralButtonClick = onClick
return this
@ -114,14 +129,22 @@ class AlertDialogBuilder(private val context: Context) {
return this
}
fun singleChoiceItems(items: Array<String>, selectedItemIndex: Int = -1, onItemSelected: (Int) -> Unit): AlertDialogBuilder {
fun singleChoiceItems(
items: Array<String>,
selectedItemIndex: Int = -1,
onItemSelected: (Int) -> Unit
): AlertDialogBuilder {
this.items = items
this.selectedItemIndex = selectedItemIndex
this.onItemSelected = onItemSelected
return this
}
fun multiChoiceItems(items: Array<String>, checkedItems: BooleanArray? = null, onItemsSelected: (BooleanArray) -> Unit): AlertDialogBuilder {
fun multiChoiceItems(
items: Array<String>,
checkedItems: BooleanArray? = null,
onItemsSelected: (BooleanArray) -> Unit
): AlertDialogBuilder {
this.items = items
this.checkedItems = checkedItems ?: BooleanArray(items.size) { false }
this.onItemsSelected = onItemsSelected

View file

@ -6,11 +6,16 @@ import android.media.MediaPlayer
class AudioHelper(private val context: Context) {
private val audioManager: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
private val audioManager: AudioManager =
context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
private var mediaPlayer: MediaPlayer? = null
fun routeAudioToSpeaker() {
audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)
audioManager.requestAudioFocus(
null,
AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN
)
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
audioManager.isSpeakerphoneOn = true
}

View file

@ -129,6 +129,7 @@ object Logger {
file?.delete()
file = null
}
fun getDeviceAndAppInfo(context: Context): String {
val pm = context.packageManager
val pkgInfo = pm.getPackageInfo(context.packageName, 0)