Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
aayush262 2024-04-30 20:00:43 +05:30
commit 390ce9a022
16 changed files with 134 additions and 127 deletions

View file

@ -28,7 +28,9 @@ import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import logcat.AndroidLogcatLogger import logcat.AndroidLogcatLogger
@ -57,6 +59,7 @@ class App : MultiDexApplication() {
val mFTActivityLifecycleCallbacks = FTActivityLifecycleCallbacks() val mFTActivityLifecycleCallbacks = FTActivityLifecycleCallbacks()
@OptIn(DelicateCoroutinesApi::class)
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
@ -98,43 +101,35 @@ class App : MultiDexApplication() {
LogcatLogger.install(AndroidLogcatLogger(LogPriority.VERBOSE)) LogcatLogger.install(AndroidLogcatLogger(LogPriority.VERBOSE))
} }
animeExtensionManager = Injekt.get() CoroutineScope(Dispatchers.IO).launch {
mangaExtensionManager = Injekt.get() animeExtensionManager = Injekt.get()
novelExtensionManager = Injekt.get()
torrentAddonManager = Injekt.get()
downloadAddonManager = Injekt.get()
val animeScope = CoroutineScope(Dispatchers.Default)
animeScope.launch {
animeExtensionManager.findAvailableExtensions() animeExtensionManager.findAvailableExtensions()
Logger.log("Anime Extensions: ${animeExtensionManager.installedExtensionsFlow.first()}") Logger.log("Anime Extensions: ${animeExtensionManager.installedExtensionsFlow.first()}")
AnimeSources.init(animeExtensionManager.installedExtensionsFlow) AnimeSources.init(animeExtensionManager.installedExtensionsFlow)
} }
val mangaScope = CoroutineScope(Dispatchers.Default) CoroutineScope(Dispatchers.IO).launch {
mangaScope.launch { mangaExtensionManager = Injekt.get()
mangaExtensionManager.findAvailableExtensions() mangaExtensionManager.findAvailableExtensions()
Logger.log("Manga Extensions: ${mangaExtensionManager.installedExtensionsFlow.first()}") Logger.log("Manga Extensions: ${mangaExtensionManager.installedExtensionsFlow.first()}")
MangaSources.init(mangaExtensionManager.installedExtensionsFlow) MangaSources.init(mangaExtensionManager.installedExtensionsFlow)
} }
val novelScope = CoroutineScope(Dispatchers.Default) CoroutineScope(Dispatchers.IO).launch {
novelScope.launch { novelExtensionManager = Injekt.get()
novelExtensionManager.findAvailableExtensions() novelExtensionManager.findAvailableExtensions()
Logger.log("Novel Extensions: ${novelExtensionManager.installedExtensionsFlow.first()}") Logger.log("Novel Extensions: ${novelExtensionManager.installedExtensionsFlow.first()}")
NovelSources.init(novelExtensionManager.installedExtensionsFlow) NovelSources.init(novelExtensionManager.installedExtensionsFlow)
} }
val addonScope = CoroutineScope(Dispatchers.Default) GlobalScope.launch {
addonScope.launch { torrentAddonManager = Injekt.get()
downloadAddonManager = Injekt.get()
torrentAddonManager.init() torrentAddonManager.init()
downloadAddonManager.init() downloadAddonManager.init()
}
val commentsScope = CoroutineScope(Dispatchers.Default)
commentsScope.launch {
CommentsAPI.fetchAuthToken() CommentsAPI.fetchAuthToken()
}
val useAlarmManager = PrefManager.getVal<Boolean>(PrefName.UseAlarmManager) val useAlarmManager = PrefManager.getVal<Boolean>(PrefName.UseAlarmManager)
val scheduler = TaskScheduler.create(this, useAlarmManager) val scheduler = TaskScheduler.create(this@App, useAlarmManager)
scheduler.scheduleAllTasks(this) scheduler.scheduleAllTasks(this@App)
}
} }
private fun setupNotificationChannels() { private fun setupNotificationChannels() {

View file

@ -35,7 +35,7 @@ class AddonDownloader {
val md = r.body ?: "" val md = r.body ?: ""
val version = v.ifEmpty { throw Exception("Weird Version : ${r.tagName}") } val version = v.ifEmpty { throw Exception("Weird Version : ${r.tagName}") }
Logger.log("Git Version : $version") Logger.log("Git Version for $repo: $version")
Pair(md, version) Pair(md, version)
} catch (e: Exception) { } catch (e: Exception) {
Logger.log("Error checking for update") Logger.log("Error checking for update")

View file

@ -24,7 +24,7 @@ class DownloadAddonManager(
override var name: String = "Download Addon" override var name: String = "Download Addon"
override var type = AddonType.DOWNLOAD override var type = AddonType.DOWNLOAD
private val _isInitialized = MutableLiveData<Boolean>().apply { value = false } private val _isInitialized = MutableLiveData<Boolean>().apply { postValue(false) }
val isInitialized: LiveData<Boolean> = _isInitialized val isInitialized: LiveData<Boolean> = _isInitialized
private var error: String? = null private var error: String? = null

View file

@ -25,7 +25,7 @@ class TorrentAddonManager(
override var type: AddonType = AddonType.TORRENT override var type: AddonType = AddonType.TORRENT
var torrentHash: String? = null var torrentHash: String? = null
private val _isInitialized = MutableLiveData<Boolean>().apply { value = false } private val _isInitialized = MutableLiveData<Boolean>().apply { postValue(false) }
val isInitialized: LiveData<Boolean> = _isInitialized val isInitialized: LiveData<Boolean> = _isInitialized
private var error: String? = null private var error: String? = null

View file

@ -202,7 +202,6 @@ object Anilist {
if (!json.text.startsWith("{")) { if (!json.text.startsWith("{")) {
throw Exception(currContext()?.getString(R.string.anilist_down)) throw Exception(currContext()?.getString(R.string.anilist_down))
} }
if (show) Logger.log("Anilist Response: ${json.text}")
json.parsed() json.parsed()
} else null } else null
} catch (e: Exception) { } catch (e: Exception) {

View file

@ -25,7 +25,6 @@ import ani.dantotsu.profile.User
import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.util.Logger
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -413,7 +412,7 @@ class AnilistQueries {
return """ MediaListCollection(userId: ${Anilist.userid}, type: $type, status: PLANNING${if (type == "ANIME") ", sort: MEDIA_POPULARITY_DESC" else ""} ) { lists { entries { media { id mediaListEntry { progress private score(format:POINT_100) status } idMal type isAdult popularity status(version: 2) chapters episodes nextAiringEpisode {episode} meanScore isFavourite format bannerImage coverImage{large} title { english romaji userPreferred } } } } }""" return """ MediaListCollection(userId: ${Anilist.userid}, type: $type, status: PLANNING${if (type == "ANIME") ", sort: MEDIA_POPULARITY_DESC" else ""} ) { lists { entries { media { id mediaListEntry { progress private score(format:POINT_100) status } idMal type isAdult popularity status(version: 2) chapters episodes nextAiringEpisode {episode} meanScore isFavourite format bannerImage coverImage{large} title { english romaji userPreferred } } } } }"""
} }
suspend fun initHomePage(): Map<String, ArrayList<Media>> { suspend fun initHomePage(): Map<String, ArrayList<*>> {
val toShow: List<Boolean> = val toShow: List<Boolean> =
PrefManager.getVal(PrefName.HomeLayout) // anime continue, anime fav, anime planned, manga continue, manga fav, manga planned, recommendations PrefManager.getVal(PrefName.HomeLayout) // anime continue, anime fav, anime planned, manga continue, manga fav, manga planned, recommendations
var query = """{""" var query = """{"""
@ -448,11 +447,11 @@ class AnilistQueries {
"ANIME" "ANIME"
) )
}, recommendationPlannedQueryManga: ${recommendationPlannedQuery("MANGA")}""" }, recommendationPlannedQueryManga: ${recommendationPlannedQuery("MANGA")}"""
if (toShow.getOrNull(7) == true) query += "Page1:${status(1)}Page2:${status(2)}"
query += """}""".trimEnd(',') query += """}""".trimEnd(',')
val response = executeQuery<Query.HomePageMedia>(query, show = true) val response = executeQuery<Query.HomePageMedia>(query, show = true)
Logger.log(response.toString()) val returnMap = mutableMapOf<String, ArrayList<*>>()
val returnMap = mutableMapOf<String, ArrayList<Media>>()
fun current(type: String) { fun current(type: String) {
val subMap = mutableMapOf<Int, Media>() val subMap = mutableMapOf<Int, Media>()
val returnArray = arrayListOf<Media>() val returnArray = arrayListOf<Media>()
@ -595,6 +594,45 @@ class AnilistQueries {
list.sortByDescending { it.meanScore } list.sortByDescending { it.meanScore }
returnMap["recommendations"] = list returnMap["recommendations"] = list
} }
if (toShow.getOrNull(7) == true) {
val list = mutableListOf<User>()
val threeDaysAgo = Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, -3)
}.timeInMillis
if (response?.data?.page1 != null && response.data.page2 != null) {
val activities = listOf(
response.data.page1.activities,
response.data.page2.activities
).flatten()
.filter { it.typename != "MessageActivity" }
.sortedByDescending { it.createdAt }
.filter { it.createdAt * 1000L > threeDaysAgo }
val anilistActivities = mutableListOf<User>()
val groupedActivities = activities.groupBy { it.userId }
groupedActivities.forEach { (_, userActivities) ->
val user = userActivities.firstOrNull()?.user
if (user != null) {
val userToAdd = User(
user.id,
user.name ?: "",
user.avatar?.medium,
user.bannerImage,
activity = userActivities.sortedBy { it.createdAt }.toList()
)
if (user.id == Anilist.userid) {
anilistActivities.add(0, userToAdd)
} else {
list.add(userToAdd)
}
}
}
list.addAll(0, anilistActivities)
returnMap["status"] = ArrayList(list)
}
}
return returnMap return returnMap
} }
@ -1546,48 +1584,9 @@ Page(page:$page,perPage:50) {
) )
} }
private fun status(page: Int = 1): String { private fun status(page: Int = 1): String {
return """Page(page:$page,perPage:50){activities(isFollowing: true,sort:ID_DESC){__typename ... on TextActivity{id userId type replyCount text(asHtml:true)siteUrl isLocked isSubscribed likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}... on ListActivity{id userId type replyCount status progress siteUrl isLocked isSubscribed likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}media{id title{english romaji native userPreferred}bannerImage coverImage{extraLarge medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}... on MessageActivity{id recipientId messengerId type replyCount likeCount message(asHtml:true)isLocked isSubscribed isLiked isPrivate siteUrl createdAt recipient{id name bannerImage avatar{medium large}}messenger{id name bannerImage avatar{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}}}""" return """Page(page:$page,perPage:50){activities(isFollowing: true,sort:ID_DESC){__typename ... on TextActivity{id userId type replyCount text(asHtml:true)siteUrl isLocked isSubscribed likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}... on ListActivity{id userId type replyCount status progress siteUrl isLocked isSubscribed likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}media{id title{english romaji native userPreferred}bannerImage coverImage{extraLarge medium large}}likes{id name bannerImage avatar{medium large}}}... on MessageActivity{id type createdAt}}}"""
} }
suspend fun getStatus(
): MutableList<User> {
fun query() = """{
Page1:${status(1)}
Page2:${status(2)}
}""".trimIndent()
val list = mutableListOf<User>()
val threeDaysAgo = Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, -3)
}.timeInMillis
executeQuery<Social>(query(), force = true)?.data?.let { data ->
val activities = listOf(data.page1.activities, data.page2.activities).flatten()
.sortedByDescending { it.createdAt }
.filter { it.createdAt * 1000L > threeDaysAgo }
val anilistActivities = mutableListOf<User>()
val groupedActivities = activities.groupBy { it.userId }
groupedActivities.forEach { (_, userActivities) ->
val user = userActivities.firstOrNull()?.user
if (user != null) {
val userToAdd = User(
user.id,
user.name ?: "",
user.avatar?.medium,
user.bannerImage,
activity = userActivities.sortedBy { it.createdAt }.toList()
)
if (user.id == Anilist.userid) {
anilistActivities.add(0, userToAdd)
} else {
list.add(userToAdd)
}
}
}
list.addAll(0, anilistActivities)
}
return list
}
suspend fun getUpcomingAnime(id: String): List<Media> { suspend fun getUpcomingAnime(id: String): List<Media> {
val res = executeQuery<Query.MediaListCollection>( val res = executeQuery<Query.MediaListCollection>(
"""{MediaListCollection(userId:$id,type:ANIME){lists{name entries{media{id,isFavourite,title{userPreferred,romaji}coverImage{medium}nextAiringEpisode{timeUntilAiring}}}}}}""", """{MediaListCollection(userId:$id,type:ANIME){lists{name entries{media{id,isFavourite,title{userPreferred,romaji}coverImage{medium}nextAiringEpisode{timeUntilAiring}}}}}}""",

View file

@ -23,16 +23,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
suspend fun getUserId(context: Context, block: () -> Unit) { suspend fun getUserId(context: Context, block: () -> Unit) {
CoroutineScope(Dispatchers.IO).launch {
val token = PrefManager.getVal(PrefName.DiscordToken, null as String?)
val userid = PrefManager.getVal(PrefName.DiscordId, null as String?)
if (userid == null && token != null) {
/*if (!Discord.getUserData())
snackString(context.getString(R.string.error_loading_discord_user_data))*/
//TODO: Discord.getUserData()
}
}
val anilist = if (Anilist.userid == null && Anilist.token != null) { val anilist = if (Anilist.userid == null && Anilist.token != null) {
if (Anilist.query.getUserData()) { if (Anilist.query.getUserData()) {
tryWithSuspend { tryWithSuspend {
@ -91,26 +81,23 @@ class AnilistHomeViewModel : ViewModel() {
fun getRecommendation(): LiveData<ArrayList<Media>> = recommendation fun getRecommendation(): LiveData<ArrayList<Media>> = recommendation
@Suppress("UNCHECKED_CAST")
suspend fun initHomePage() { suspend fun initHomePage() {
val res = Anilist.query.initHomePage() val res = Anilist.query.initHomePage()
Logger.log("AnilistHomeViewModel : res=$res") res["currentAnime"]?.let { animeContinue.postValue(it as ArrayList<Media>?) }
res["currentAnime"]?.let { animeContinue.postValue(it) } res["favoriteAnime"]?.let { animeFav.postValue(it as ArrayList<Media>?) }
res["favoriteAnime"]?.let { animeFav.postValue(it) } res["plannedAnime"]?.let { animePlanned.postValue(it as ArrayList<Media>?) }
res["plannedAnime"]?.let { animePlanned.postValue(it) } res["currentManga"]?.let { mangaContinue.postValue(it as ArrayList<Media>?) }
res["currentManga"]?.let { mangaContinue.postValue(it) } res["favoriteManga"]?.let { mangaFav.postValue(it as ArrayList<Media>?) }
res["favoriteManga"]?.let { mangaFav.postValue(it) } res["plannedManga"]?.let { mangaPlanned.postValue(it as ArrayList<Media>?) }
res["plannedManga"]?.let { mangaPlanned.postValue(it) } res["recommendations"]?.let { recommendation.postValue(it as ArrayList<Media>?) }
res["recommendations"]?.let { recommendation.postValue(it) } res["status"]?.let { userStatus.postValue(it as ArrayList<User>?) }
} }
private val userStatus: MutableLiveData<ArrayList<User>> = private val userStatus: MutableLiveData<ArrayList<User>> =
MutableLiveData<ArrayList<User>>(null) MutableLiveData<ArrayList<User>>(null)
fun getUserStatus(): LiveData<ArrayList<User>> = userStatus fun getUserStatus(): LiveData<ArrayList<User>> = userStatus
suspend fun initUserStatus() {
Anilist.query.getStatus().let { userStatus.postValue(ArrayList(it)) }
}
suspend fun loadMain(context: FragmentActivity) { suspend fun loadMain(context: FragmentActivity) {
Anilist.getSavedToken() Anilist.getSavedToken()
MAL.getSavedToken() MAL.getSavedToken()

View file

@ -138,6 +138,8 @@ class Query {
@SerialName("recommendationQuery") val recommendationQuery: ani.dantotsu.connections.anilist.api.Page?, @SerialName("recommendationQuery") val recommendationQuery: ani.dantotsu.connections.anilist.api.Page?,
@SerialName("recommendationPlannedQueryAnime") val recommendationPlannedQueryAnime: ani.dantotsu.connections.anilist.api.MediaListCollection?, @SerialName("recommendationPlannedQueryAnime") val recommendationPlannedQueryAnime: ani.dantotsu.connections.anilist.api.MediaListCollection?,
@SerialName("recommendationPlannedQueryManga") val recommendationPlannedQueryManga: ani.dantotsu.connections.anilist.api.MediaListCollection?, @SerialName("recommendationPlannedQueryManga") val recommendationPlannedQueryManga: ani.dantotsu.connections.anilist.api.MediaListCollection?,
@SerialName("Page1") val page1: ActivityPage?,
@SerialName("Page2") val page2: ActivityPage?
) )
} }

View file

@ -46,7 +46,7 @@ data class Activity(
@SerialName("type") @SerialName("type")
val type: String, val type: String,
@SerialName("replyCount") @SerialName("replyCount")
val replyCount: Int, val replyCount: Int = 0,
@SerialName("status") @SerialName("status")
val status: String?, val status: String?,
@SerialName("progress") @SerialName("progress")
@ -58,9 +58,9 @@ data class Activity(
@SerialName("siteUrl") @SerialName("siteUrl")
val siteUrl: String?, val siteUrl: String?,
@SerialName("isLocked") @SerialName("isLocked")
val isLocked: Boolean, val isLocked: Boolean?,
@SerialName("isSubscribed") @SerialName("isSubscribed")
val isSubscribed: Boolean, val isSubscribed: Boolean?,
@SerialName("likeCount") @SerialName("likeCount")
var likeCount: Int?, var likeCount: Int?,
@SerialName("isLiked") @SerialName("isLiked")

View file

@ -205,15 +205,17 @@ enum class MediaStatus {
FINISHED, RELEASING, NOT_YET_RELEASED, CANCELLED, HIATUS; FINISHED, RELEASING, NOT_YET_RELEASED, CANCELLED, HIATUS;
override fun toString(): String { override fun toString(): String {
return when (super.toString()) { currContext()?.let {
"FINISHED" -> currContext()!!.getString(R.string.status_finished) return when (super.toString()) {
"RELEASING" -> currContext()!!.getString(R.string.status_releasing) "FINISHED" -> it.getString(R.string.status_finished)
"NOT_YET_RELEASED" -> currContext()!!.getString(R.string.status_not_yet_released) "RELEASING" -> it.getString(R.string.status_releasing)
"CANCELLED" -> currContext()!!.getString(R.string.status_cancelled) "NOT_YET_RELEASED" -> it.getString(R.string.status_not_yet_released)
"HIATUS" -> currContext()!!.getString(R.string.status_hiatus) "CANCELLED" -> it.getString(R.string.status_cancelled)
else -> "" "HIATUS" -> it.getString(R.string.status_hiatus)
else -> ""
}
} }
return super.toString().replace("_", " ")
} }
} }
@ -445,17 +447,20 @@ enum class MediaRelation {
ADAPTATION, PREQUEL, SEQUEL, PARENT, SIDE_STORY, CHARACTER, SUMMARY, ALTERNATIVE, SPIN_OFF, OTHER, SOURCE, COMPILATION, CONTAINS; ADAPTATION, PREQUEL, SEQUEL, PARENT, SIDE_STORY, CHARACTER, SUMMARY, ALTERNATIVE, SPIN_OFF, OTHER, SOURCE, COMPILATION, CONTAINS;
override fun toString(): String { override fun toString(): String {
return when (super.toString()) { currContext()?.let {
"ADAPTATION" -> currContext()!!.getString(R.string.type_adaptation) return when (super.toString()) {
"PARENT" -> currContext()!!.getString(R.string.type_parent) "ADAPTATION" -> it.getString(R.string.type_adaptation)
"CHARACTER" -> currContext()!!.getString(R.string.type_character) "PARENT" -> it.getString(R.string.type_parent)
"SUMMARY" -> currContext()!!.getString(R.string.type_summary) "CHARACTER" -> it.getString(R.string.type_character)
"ALTERNATIVE" -> currContext()!!.getString(R.string.type_alternative) "SUMMARY" -> it.getString(R.string.type_summary)
"OTHER" -> currContext()!!.getString(R.string.type_other) "ALTERNATIVE" -> it.getString(R.string.type_alternative)
"SOURCE" -> currContext()!!.getString(R.string.type_source) "OTHER" -> it.getString(R.string.type_other)
"CONTAINS" -> currContext()!!.getString(R.string.type_contains) "SOURCE" -> it.getString(R.string.type_source)
else -> super.toString().replace("_", " ") "CONTAINS" -> it.getString(R.string.type_contains)
else -> super.toString().replace("_", " ")
}
} }
return super.toString().replace("_", " ")
} }
} }

View file

@ -291,8 +291,8 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
val animeTitles = downloadManager.animeDownloadedTypes.map { it.titleName.findValidName() }.distinct() val animeTitles = downloadManager.animeDownloadedTypes.map { it.titleName.findValidName() }.distinct()
val newAnimeDownloads = mutableListOf<OfflineAnimeModel>() val newAnimeDownloads = mutableListOf<OfflineAnimeModel>()
for (title in animeTitles) { for (title in animeTitles) {
val tDownloads = downloadManager.animeDownloadedTypes.filter { it.titleName == title } val tDownloads = downloadManager.animeDownloadedTypes.filter { it.titleName.findValidName() == title }
val download = tDownloads.first() val download = tDownloads.firstOrNull() ?: continue
val offlineAnimeModel = loadOfflineAnimeModel(download) val offlineAnimeModel = loadOfflineAnimeModel(download)
newAnimeDownloads += offlineAnimeModel newAnimeDownloads += offlineAnimeModel
} }

View file

@ -282,8 +282,8 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
val mangaTitles = downloadManager.mangaDownloadedTypes.map { it.titleName.findValidName() }.distinct() val mangaTitles = downloadManager.mangaDownloadedTypes.map { it.titleName.findValidName() }.distinct()
val newMangaDownloads = mutableListOf<OfflineMangaModel>() val newMangaDownloads = mutableListOf<OfflineMangaModel>()
for (title in mangaTitles) { for (title in mangaTitles) {
val tDownloads = downloadManager.mangaDownloadedTypes.filter { it.titleName == title } val tDownloads = downloadManager.mangaDownloadedTypes.filter { it.titleName.findValidName() == title }
val download = tDownloads.first() val download = tDownloads.firstOrNull() ?: continue
val offlineMangaModel = loadOfflineMangaModel(download) val offlineMangaModel = loadOfflineMangaModel(download)
newMangaDownloads += offlineMangaModel newMangaDownloads += offlineMangaModel
} }
@ -291,8 +291,8 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
val novelTitles = downloadManager.novelDownloadedTypes.map { it.titleName }.distinct() val novelTitles = downloadManager.novelDownloadedTypes.map { it.titleName }.distinct()
val newNovelDownloads = mutableListOf<OfflineMangaModel>() val newNovelDownloads = mutableListOf<OfflineMangaModel>()
for (title in novelTitles) { for (title in novelTitles) {
val tDownloads = downloadManager.novelDownloadedTypes.filter { it.titleName == title } val tDownloads = downloadManager.novelDownloadedTypes.filter { it.titleName.findValidName() == title }
val download = tDownloads.first() val download = tDownloads.firstOrNull() ?: continue
val offlineMangaModel = loadOfflineMangaModel(download) val offlineMangaModel = loadOfflineMangaModel(download)
newNovelDownloads += offlineMangaModel newNovelDownloads += offlineMangaModel
} }

View file

@ -46,6 +46,7 @@ import ani.dantotsu.settings.saving.PrefManager.asLiveBool
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import ani.dantotsu.util.Logger
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -75,7 +76,9 @@ class HomeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val scope = lifecycleScope val scope = lifecycleScope
Logger.log("HomeFragment")
fun load() { fun load() {
Logger.log("Loading HomeFragment")
if (activity != null && _binding != null) lifecycleScope.launch(Dispatchers.Main) { if (activity != null && _binding != null) lifecycleScope.launch(Dispatchers.Main) {
binding.homeUserName.text = Anilist.username binding.homeUserName.text = Anilist.username
binding.homeUserEpisodesWatched.text = Anilist.episodesWatched.toString() binding.homeUserEpisodesWatched.text = Anilist.episodesWatched.toString()
@ -315,7 +318,7 @@ class HomeFragment : Fragment() {
binding.homeRecommendedEmpty, binding.homeRecommendedEmpty,
binding.homeRecommended binding.homeRecommended
) )
binding.homeUserStatusContainer.visibility =View.VISIBLE binding.homeUserStatusContainer.visibility = View.VISIBLE
binding.homeUserStatusProgressBar.visibility = View.VISIBLE binding.homeUserStatusProgressBar.visibility = View.VISIBLE
binding.homeUserStatusRecyclerView.visibility = View.GONE binding.homeUserStatusRecyclerView.visibility = View.GONE
model.getUserStatus().observe(viewLifecycleOwner) { model.getUserStatus().observe(viewLifecycleOwner) {
@ -391,13 +394,12 @@ class HomeFragment : Fragment() {
} }
model.loaded = true model.loaded = true
model.setListImages() model.setListImages()
Logger.log("HomeFragment: Refreshing")
var empty = true var empty = true
val homeLayoutShow: List<Boolean> = val homeLayoutShow: List<Boolean> =
PrefManager.getVal(PrefName.HomeLayout) PrefManager.getVal(PrefName.HomeLayout)
runBlocking { model.initHomePage()
if (homeLayoutShow.getOrNull(7) == true) model.initUserStatus()
model.initHomePage()
}
(array.indices).forEach { i -> (array.indices).forEach { i ->
if (homeLayoutShow.elementAt(i)) { if (homeLayoutShow.elementAt(i)) {
empty = false empty = false

View file

@ -573,7 +573,7 @@ class MediaInfoFragment : Fragment() {
parent.addView(root) parent.addView(root)
} }
} }
val users = media.users!! val users: ArrayList<User> = media.users ?: arrayListOf()
if (Anilist.token != null && media.userStatus != null) { if (Anilist.token != null && media.userStatus != null) {
users.add(0, users.add(0,
User( User(

View file

@ -23,7 +23,7 @@ class SubscriptionHelper {
mediaId: Int mediaId: Int
): Selected { ): Selected {
val data = val data =
PrefManager.getNullableCustomVal("${mediaId}-select", null, Selected::class.java) PrefManager.getNullableCustomVal("Selected-${mediaId}", null, Selected::class.java)
?: Selected().let { ?: Selected().let {
it.sourceIndex = 0 it.sourceIndex = 0
it.preferDub = PrefManager.getVal(PrefName.SettingsPreferDub) it.preferDub = PrefManager.getVal(PrefName.SettingsPreferDub)
@ -33,13 +33,16 @@ class SubscriptionHelper {
} }
private fun saveSelected(mediaId: Int, data: Selected) { private fun saveSelected(mediaId: Int, data: Selected) {
PrefManager.setCustomVal("${mediaId}-select", data) PrefManager.setCustomVal("Selected-${mediaId}", data)
} }
fun getAnimeParser(id: Int): AnimeParser { fun getAnimeParser(id: Int): AnimeParser {
val sources = AnimeSources val sources = AnimeSources
Logger.log("getAnimeParser size: ${sources.list.size}") Logger.log("getAnimeParser size: ${sources.list.size}")
val selected = loadSelected(id) val selected = loadSelected(id)
if (selected.sourceIndex >= sources.list.size) {
selected.sourceIndex = 0
}
val parser = sources[selected.sourceIndex] val parser = sources[selected.sourceIndex]
parser.selectDub = selected.preferDub parser.selectDub = selected.preferDub
return parser return parser
@ -76,7 +79,11 @@ class SubscriptionHelper {
fun getMangaParser(id: Int): MangaParser { fun getMangaParser(id: Int): MangaParser {
val sources = MangaSources val sources = MangaSources
Logger.log("getMangaParser size: ${sources.list.size}")
val selected = loadSelected(id) val selected = loadSelected(id)
if (selected.sourceIndex >= sources.list.size) {
selected.sourceIndex = 0
}
return sources[selected.sourceIndex] return sources[selected.sourceIndex]
} }

View file

@ -117,6 +117,17 @@ object Logger {
} }
} }
fun uncaughtException(t: Thread, e: Throwable) {
loggerExecutor.execute {
if (file == null) e.printStackTrace() else {
file?.appendText("---------------------------Uncaught Exception---------------------------\n")
file?.appendText("thread: ${t.name}\n")
file?.appendText("date/time: ${Date()} | ${e.message}\n")
file?.appendText("trace: ${e.stackTraceToString()}\n")
}
}
}
fun shareLog(context: Context) { fun shareLog(context: Context) {
if (file == null) { if (file == null) {
snackString("No log file found") snackString("No log file found")
@ -151,7 +162,7 @@ class FinalExceptionHandler : Thread.UncaughtExceptionHandler {
Thread.getDefaultUncaughtExceptionHandler() Thread.getDefaultUncaughtExceptionHandler()
override fun uncaughtException(t: Thread, e: Throwable) { override fun uncaughtException(t: Thread, e: Throwable) {
Logger.log(e) Logger.uncaughtException(t, e)
Injekt.get<CrashlyticsInterface>().logException(e) Injekt.get<CrashlyticsInterface>().logException(e)
defaultUEH?.uncaughtException(t, e) defaultUEH?.uncaughtException(t, e)
} }