diff --git a/app/src/main/java/ani/dantotsu/MainActivity.kt b/app/src/main/java/ani/dantotsu/MainActivity.kt index 68f42922..7b2e0b1d 100644 --- a/app/src/main/java/ani/dantotsu/MainActivity.kt +++ b/app/src/main/java/ani/dantotsu/MainActivity.kt @@ -313,7 +313,6 @@ class MainActivity : AppCompatActivity() { mainViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle) mainViewPager.setPageTransformer(ZoomOutPageTransformer()) - mainViewPager.offscreenPageLimit = 1 navbar.selectTabAt(selectedOption) navbar.setOnTabSelectListener(object : AnimatedBottomBar.OnTabSelectListener { diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt index 438dc7ad..a834acc3 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt @@ -6,14 +6,14 @@ import ani.dantotsu.checkGenreTime import ani.dantotsu.checkId import ani.dantotsu.connections.anilist.Anilist.authorRoles import ani.dantotsu.connections.anilist.Anilist.executeQuery -import ani.dantotsu.connections.anilist.api.Activity import ani.dantotsu.connections.anilist.api.FeedResponse import ani.dantotsu.connections.anilist.api.FuzzyDate +import ani.dantotsu.connections.anilist.api.MediaEdge +import ani.dantotsu.connections.anilist.api.MediaList import ani.dantotsu.connections.anilist.api.NotificationResponse import ani.dantotsu.connections.anilist.api.Page import ani.dantotsu.connections.anilist.api.Query import ani.dantotsu.connections.anilist.api.ReplyResponse -import ani.dantotsu.connections.anilist.api.ToggleLike import ani.dantotsu.currContext import ani.dantotsu.isOnline import ani.dantotsu.logError @@ -28,6 +28,7 @@ import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.runBlocking import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream @@ -422,9 +423,7 @@ class AnilistQueries { val toShow: List = PrefManager.getVal(PrefName.HomeLayout) if (toShow.getOrNull(7) != true) return null - var query = """{""" - query += "Page1:${status(1)}Page2:${status(2)}" - query += """}""".trimEnd(',') + val query = """{Page1:${status(1)}Page2:${status(2)}}""" val response = executeQuery(query, show = true) val list = mutableListOf() val threeDaysAgo = Calendar.getInstance().apply { @@ -461,8 +460,9 @@ class AnilistQueries { } } - if (anilistActivities.isEmpty() && Anilist.token != null){ - anilistActivities.add(0, + if (anilistActivities.isEmpty() && Anilist.token != null) { + anilistActivities.add( + 0, User( Anilist.userid!!, Anilist.username!!, @@ -477,206 +477,176 @@ class AnilistQueries { } else return null } - suspend fun initHomePage(): Map> { + suspend fun initHomePage(): Map> { val removeList = PrefManager.getCustomVal("removeList", setOf()) val hidePrivate = PrefManager.getVal(PrefName.HidePrivate) val removedMedia = ArrayList() val toShow: List = - PrefManager.getVal(PrefName.HomeLayout) // anime continue, anime fav, anime planned, manga continue, manga fav, manga planned, recommendations - var query = """{""" - if (toShow.getOrNull(0) == true) query += """currentAnime: ${ - continueMediaQuery( - "ANIME", - "CURRENT" - ) - }, repeatingAnime: ${continueMediaQuery("ANIME", "REPEATING")}""" - if (toShow.getOrNull(1) == true) query += """favoriteAnime: ${favMediaQuery(true, 1)}""" - if (toShow.getOrNull(2) == true) query += """plannedAnime: ${ - continueMediaQuery( - "ANIME", - "PLANNING" - ) - }""" - if (toShow.getOrNull(3) == true) query += """currentManga: ${ - continueMediaQuery( - "MANGA", - "CURRENT" - ) - }, repeatingManga: ${continueMediaQuery("MANGA", "REPEATING")}""" - if (toShow.getOrNull(4) == true) query += """favoriteManga: ${favMediaQuery(false, 1)}""" - if (toShow.getOrNull(5) == true) query += """plannedManga: ${ - continueMediaQuery( - "MANGA", - "PLANNING" - ) - }""" - if (toShow.getOrNull(6) == true) query += """recommendationQuery: ${recommendationQuery()}, recommendationPlannedQueryAnime: ${ - recommendationPlannedQuery( - "ANIME" - ) - }, recommendationPlannedQueryManga: ${recommendationPlannedQuery("MANGA")}""" - query += """}""".trimEnd(',') + PrefManager.getVal(PrefName.HomeLayout) // list of booleans for what to show + val queries = mutableListOf() + if (toShow.getOrNull(0) == true) { + queries.add("""currentAnime: ${continueMediaQuery("ANIME", "CURRENT")}""") + queries.add("""repeatingAnime: ${continueMediaQuery("ANIME", "REPEATING")}""") + } + if (toShow.getOrNull(1) == true) queries.add("""favoriteAnime: ${favMediaQuery(true, 1)}""") + if (toShow.getOrNull(2) == true) queries.add( + """plannedAnime: ${ + continueMediaQuery( + "ANIME", + "PLANNING" + ) + }""" + ) + if (toShow.getOrNull(3) == true) { + queries.add("""currentManga: ${continueMediaQuery("MANGA", "CURRENT")}""") + queries.add("""repeatingManga: ${continueMediaQuery("MANGA", "REPEATING")}""") + } + if (toShow.getOrNull(4) == true) queries.add( + """favoriteManga: ${ + favMediaQuery( + false, + 1 + ) + }""" + ) + if (toShow.getOrNull(5) == true) queries.add( + """plannedManga: ${ + continueMediaQuery( + "MANGA", + "PLANNING" + ) + }""" + ) + if (toShow.getOrNull(6) == true) { + queries.add("""recommendationQuery: ${recommendationQuery()}""") + queries.add("""recommendationPlannedQueryAnime: ${recommendationPlannedQuery("ANIME")}""") + queries.add("""recommendationPlannedQueryManga: ${recommendationPlannedQuery("MANGA")}""") + } + + val query = "{${queries.joinToString(",")}}" val response = executeQuery(query, show = true) - val returnMap = mutableMapOf>() - fun current(type: String) { + val returnMap = mutableMapOf>() + + fun processMedia( + type: String, + currentMedia: List?, + repeatingMedia: List? + ) { val subMap = mutableMapOf() val returnArray = arrayListOf() - val current = - if (type == "Anime") response?.data?.currentAnime else response?.data?.currentManga - val repeating = - if (type == "Anime") response?.data?.repeatingAnime else response?.data?.repeatingManga - current?.lists?.forEach { li -> - li.entries?.reversed()?.forEach { - val m = Media(it) - if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) { - m.cameFromContinue = true - subMap[m.id] = m - } else { - removedMedia.add(m) - } + + (currentMedia ?: emptyList()).forEach { entry -> + val media = Media(entry) + if (media.id !in removeList && (!hidePrivate || !media.isListPrivate)) { + media.cameFromContinue = true + subMap[media.id] = media + } else { + removedMedia.add(media) } } - repeating?.lists?.forEach { li -> - li.entries?.reversed()?.forEach { - val m = Media(it) - if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) { - m.cameFromContinue = true - subMap[m.id] = m - } else { - removedMedia.add(m) - } + (repeatingMedia ?: emptyList()).forEach { entry -> + val media = Media(entry) + if (media.id !in removeList && (!hidePrivate || !media.isListPrivate)) { + media.cameFromContinue = true + subMap[media.id] = media + } else { + removedMedia.add(media) } } - if (type != "Anime") { + @Suppress("UNCHECKED_CAST") + val list = PrefManager.getNullableCustomVal( + "continue${type}List", + listOf(), + List::class.java + ) as List + if (list.isNotEmpty()) { + list.reversed().forEach { id -> + subMap[id]?.let { returnArray.add(it) } + } + subMap.values.forEach { + if (!returnArray.contains(it)) returnArray.add(it) + } + } else { returnArray.addAll(subMap.values) - returnMap["current$type"] = returnArray - return } - @Suppress("UNCHECKED_CAST") - val list = PrefManager.getNullableCustomVal( - "continueAnimeList", - listOf(), - List::class.java - ) as List - if (list.isNotEmpty()) { - list.reversed().forEach { - if (subMap.containsKey(it)) returnArray.add(subMap[it]!!) - } - for (i in subMap) { - if (i.value !in returnArray) returnArray.add(i.value) - } - } else returnArray.addAll(subMap.values) returnMap["current$type"] = returnArray - } - fun planned(type: String) { - val subMap = mutableMapOf() - val returnArray = arrayListOf() - val current = - if (type == "Anime") response?.data?.plannedAnime else response?.data?.plannedManga - current?.lists?.forEach { li -> - li.entries?.reversed()?.forEach { - val m = Media(it) - if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) { - m.cameFromContinue = true - subMap[m.id] = m - } else { - removedMedia.add(m) - } - } - } - @Suppress("UNCHECKED_CAST") - val list = PrefManager.getNullableCustomVal( - "continueAnimeList", - listOf(), - List::class.java - ) as List - if (list.isNotEmpty()) { - list.reversed().forEach { - if (subMap.containsKey(it)) returnArray.add(subMap[it]!!) - } - for (i in subMap) { - if (i.value !in returnArray) returnArray.add(i.value) - } - } else returnArray.addAll(subMap.values) - returnMap["planned$type"] = returnArray - } + if (toShow.getOrNull(0) == true) processMedia( + "Anime", + response?.data?.currentAnime?.lists?.flatMap { it.entries ?: emptyList() }?.reversed(), + response?.data?.repeatingAnime?.lists?.flatMap { it.entries ?: emptyList() }?.reversed() + ) + if (toShow.getOrNull(2) == true) processMedia( + "AnimePlanned", + response?.data?.plannedAnime?.lists?.flatMap { it.entries ?: emptyList() }?.reversed(), + null + ) + if (toShow.getOrNull(3) == true) processMedia( + "Manga", + response?.data?.currentManga?.lists?.flatMap { it.entries ?: emptyList() }?.reversed(), + response?.data?.repeatingManga?.lists?.flatMap { it.entries ?: emptyList() }?.reversed() + ) + if (toShow.getOrNull(5) == true) processMedia( + "MangaPlanned", + response?.data?.plannedManga?.lists?.flatMap { it.entries ?: emptyList() }?.reversed(), + null + ) - fun favorite(type: String) { - val favourites = - if (type == "Anime") response?.data?.favoriteAnime?.favourites else response?.data?.favoriteManga?.favourites - val apiMediaList = if (type == "Anime") favourites?.anime else favourites?.manga + fun processFavorites(type: String, favorites: List?) { val returnArray = arrayListOf() - apiMediaList?.edges?.forEach { - it.node?.let { i -> - val m = Media(i).apply { isFav = true } - if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) { - returnArray.add(m) + favorites?.forEach { edge -> + edge.node?.let { + val media = Media(it).apply { isFav = true } + if (media.id !in removeList && (!hidePrivate || !media.isListPrivate)) { + returnArray.add(media) } else { - removedMedia.add(m) + removedMedia.add(media) } } } returnMap["favorite$type"] = returnArray } - if (toShow.getOrNull(0) == true) { - current("Anime") - } - if (toShow.getOrNull(1) == true) { - favorite("Anime") - } - if (toShow.getOrNull(2) == true) { - planned("Anime") - } - if (toShow.getOrNull(3) == true) { - current("Manga") - } - if (toShow.getOrNull(4) == true) { - favorite("Manga") - } - if (toShow.getOrNull(5) == true) { - planned("Manga") - } + if (toShow.getOrNull(1) == true) processFavorites( + "Anime", + response?.data?.favoriteAnime?.favourites?.anime?.edges + ) + if (toShow.getOrNull(4) == true) processFavorites( + "Manga", + response?.data?.favoriteManga?.favourites?.manga?.edges + ) + if (toShow.getOrNull(6) == true) { val subMap = mutableMapOf() - response?.data?.recommendationQuery?.apply { - recommendations?.onEach { - val json = it.mediaRecommendation - if (json != null) { - val m = Media(json) - m.relation = json.type?.toString() - subMap[m.id] = m - } + response?.data?.recommendationQuery?.recommendations?.forEach { + it.mediaRecommendation?.let { json -> + val media = Media(json) + media.relation = json.type?.toString() + subMap[media.id] = media } } - response?.data?.recommendationPlannedQueryAnime?.apply { - lists?.forEach { li -> - li.entries?.forEach { - val m = Media(it) - if (m.status == "RELEASING" || m.status == "FINISHED") { - m.relation = it.media?.type?.toString() - subMap[m.id] = m - } - } + response?.data?.recommendationPlannedQueryAnime?.lists?.flatMap { + it.entries ?: emptyList() + }?.forEach { + val media = Media(it) + if (media.status in listOf("RELEASING", "FINISHED")) { + media.relation = it.media?.type?.toString() + subMap[media.id] = media } } - response?.data?.recommendationPlannedQueryManga?.apply { - lists?.forEach { li -> - li.entries?.forEach { - val m = Media(it) - if (m.status == "RELEASING" || m.status == "FINISHED") { - m.relation = it.media?.type?.toString() - subMap[m.id] = m - } - } + response?.data?.recommendationPlannedQueryManga?.lists?.flatMap { + it.entries ?: emptyList() + }?.forEach { + val media = Media(it) + if (media.status in listOf("RELEASING", "FINISHED")) { + media.relation = it.media?.type?.toString() + subMap[media.id] = media } } - val list = ArrayList(subMap.values.toList()) - list.sortByDescending { it.meanScore } + val list = ArrayList(subMap.values).apply { sortByDescending { it.meanScore } } returnMap["recommendations"] = list } @@ -1061,102 +1031,97 @@ query (${"$"}page: Int = 1, ${"$"}id: Int, ${"$"}type: MediaType, ${"$"}isAdult: media1?.media?.mapTo(combinedList) { Media(it) } return combinedList } - private fun getPreference(pref: PrefName): Boolean = PrefManager.getVal(pref) - private fun buildQueryString(sort: String, type: String, format: String? = null, country: String? = null): String { - val includeList = if (type == "ANIME" && !getPreference(PrefName.IncludeAnimeList)) "onList:false" else if (type == "MANGA" && !getPreference(PrefName.IncludeMangaList)) "onList:false" else "" - val isAdult = if (getPreference(PrefName.AdultOnly)) "isAdult:true" else "" - val formatFilter = format?.let { "format: $it, " } ?: "" - val countryFilter = country?.let { "countryOfOrigin: $it, " } ?: "" - return """Page(page:1,perPage:50){ - pageInfo{hasNextPage total} - media(sort:$sort, type:$type, $formatFilter $countryFilter $includeList $isAdult){ - id idMal status chapters episodes nextAiringEpisode{episode} - isAdult type meanScore isFavourite format bannerImage countryOfOrigin - coverImage{large} title{english romaji userPreferred} - mediaListEntry{progress private score(format:POINT_100) status} + private fun getPreference(pref: PrefName): Boolean = PrefManager.getVal(pref) + + private fun buildQueryString( + sort: String, + type: String, + format: String? = null, + country: String? = null + ): String { + val includeList = when { + type == "ANIME" && !getPreference(PrefName.IncludeAnimeList) -> "onList:false" + type == "MANGA" && !getPreference(PrefName.IncludeMangaList) -> "onList:false" + else -> "" + } + val isAdult = if (getPreference(PrefName.AdultOnly)) "isAdult:true" else "" + val formatFilter = format?.let { "format:$it, " } ?: "" + val countryFilter = country?.let { "countryOfOrigin:$it, " } ?: "" + + return buildString { + append("""Page(page:1,perPage:50){pageInfo{hasNextPage total}media(sort:$sort, type:$type, $formatFilter $countryFilter $includeList $isAdult){id idMal status chapters episodes nextAiringEpisode{episode} isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large} title{english romaji userPreferred} mediaListEntry{progress private score(format:POINT_100) status}}}""") } - }""" } private fun recentAnimeUpdates(page: Int): String { val currentTime = System.currentTimeMillis() / 1000 - return """Page(page:$page,perPage:50){ - pageInfo{hasNextPage total} - airingSchedules(airingAt_greater:0 airingAt_lesser:${currentTime - 10000} sort:TIME_DESC){ - episode airingAt media{ - id idMal status chapters episodes nextAiringEpisode{episode} - isAdult type meanScore isFavourite format bannerImage countryOfOrigin - coverImage{large} title{english romaji userPreferred} - mediaListEntry{progress private score(format:POINT_100) status} - } + return buildString { + append("""Page(page:$page,perPage:50){pageInfo{hasNextPage total}airingSchedules(airingAt_greater:0 airingAt_lesser:${currentTime - 10000} sort:TIME_DESC){episode airingAt media{id idMal status chapters episodes nextAiringEpisode{episode} isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large} title{english romaji userPreferred} mediaListEntry{progress private score(format:POINT_100) status}}}}""") } - }""" - } - private fun queryAnimeList(): String { - return """{ - recentUpdates:${recentAnimeUpdates(1)} - recentUpdates2:${recentAnimeUpdates(2)} - trendingMovies:${buildQueryString("POPULARITY_DESC", "ANIME", "MOVIE")} - topRated:${buildQueryString("SCORE_DESC", "ANIME")} - mostFav:${buildQueryString("FAVOURITES_DESC", "ANIME")} - }""" - } - private fun queryMangaList(): String { - return """{ - trendingManga:${buildQueryString("POPULARITY_DESC", "MANGA", country = "JP")} - trendingManhwa:${buildQueryString("POPULARITY_DESC", "MANGA", country = "KR")} - trendingNovel:${buildQueryString("POPULARITY_DESC", "MANGA", format = "NOVEL", country = "JP")} - topRated:${buildQueryString("SCORE_DESC", "MANGA")} - mostFav:${buildQueryString("FAVOURITES_DESC", "MANGA")} - - }""" } - suspend fun loadAnimeList(): Map> { + private fun queryAnimeList(): String { + return buildString { + append("""{recentUpdates:${recentAnimeUpdates(1)} recentUpdates2:${recentAnimeUpdates(2)} trendingMovies:${buildQueryString("POPULARITY_DESC", "ANIME", "MOVIE")} topRated:${buildQueryString("SCORE_DESC", "ANIME")} mostFav:${buildQueryString("FAVOURITES_DESC", "ANIME")}}""") + } + } + + private fun queryMangaList(): String { + return buildString { + append("""{trendingManga:${buildQueryString("POPULARITY_DESC", "MANGA", country = "JP")} trendingManhwa:${buildQueryString("POPULARITY_DESC", "MANGA", country = "KR")} trendingNovel:${buildQueryString("POPULARITY_DESC", "MANGA", format = "NOVEL", country = "JP")} topRated:${buildQueryString("SCORE_DESC", "MANGA")} mostFav:${buildQueryString("FAVOURITES_DESC", "MANGA")}}""") + } + } + + suspend fun loadAnimeList(): Map> = coroutineScope { val list = mutableMapOf>() - fun filterRecentUpdates( - page: Page?, - ): ArrayList { - val listOnly: Boolean = PrefManager.getVal(PrefName.RecentlyListOnly) - val adultOnly: Boolean = PrefManager.getVal(PrefName.AdultOnly) - val idArr = mutableListOf() + fun filterRecentUpdates(page: Page?): ArrayList { + val listOnly = getPreference(PrefName.RecentlyListOnly) + val adultOnly = getPreference(PrefName.AdultOnly) + val idArr = mutableSetOf() return page?.airingSchedules?.mapNotNull { i -> - i.media?.let { - if (!idArr.contains(it.id)) { - val shouldAdd = when { - !listOnly && it.countryOfOrigin == "JP" && Anilist.adult && adultOnly && it.isAdult == true -> true - !listOnly && !adultOnly && it.countryOfOrigin == "JP" && it.isAdult == false -> true - listOnly && it.mediaListEntry != null -> true - else -> false - } - if (shouldAdd) { - idArr.add(it.id) - Media(it) - } else null + i.media?.takeIf { !idArr.contains(it.id) }?.let { + val shouldAdd = when { + !listOnly && it.countryOfOrigin == "JP" && adultOnly && it.isAdult == true -> true + !listOnly && !adultOnly && it.countryOfOrigin == "JP" && it.isAdult == false -> true + listOnly && it.mediaListEntry != null -> true + else -> false + } + if (shouldAdd) { + idArr.add(it.id) + Media(it) } else null } }?.toCollection(ArrayList()) ?: arrayListOf() } - executeQuery(queryAnimeList(), force = true)?.data?.apply { + + val animeList = async { executeQuery(queryAnimeList(), force = true) } + + animeList.await()?.data?.apply { list["recentUpdates"] = filterRecentUpdates(recentUpdates) list["trendingMovies"] = mediaList(trendingMovies) list["topRated"] = mediaList(topRated) list["mostFav"] = mediaList(mostFav) } - return list + + list } - suspend fun loadMangaList(): Map> { + + suspend fun loadMangaList(): Map> = coroutineScope { val list = mutableMapOf>() - executeQuery(queryMangaList(), force = true)?.data?.apply { + + val mangaList = async { executeQuery(queryMangaList(), force = true) } + + mangaList.await()?.data?.apply { list["trendingManga"] = mediaList(trendingManga) list["trendingManhwa"] = mediaList(trendingManhwa) list["trendingNovel"] = mediaList(trendingNovel) list["topRated"] = mediaList(topRated) list["mostFav"] = mediaList(mostFav) } - return list + + list } @@ -1560,10 +1525,10 @@ Page(page:$page,perPage:50) { resetNotification: Boolean = true, type: Boolean? = null ): NotificationResponse? { - val type_in = "type_in:[AIRING,MEDIA_MERGE,MEDIA_DELETION,MEDIA_DATA_CHANGE]" + val typeIn = "type_in:[AIRING,MEDIA_MERGE,MEDIA_DELETION,MEDIA_DATA_CHANGE]" val reset = if (resetNotification) "true" else "false" val res = executeQuery( - """{User(id:$id){unreadNotificationCount}Page(page:$page,perPage:$ITEMS_PER_PAGE){pageInfo{currentPage,hasNextPage}notifications(resetNotificationCount:$reset , ${if (type == true) type_in else ""}){__typename...on AiringNotification{id,type,animeId,episode,contexts,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}},}...on FollowingNotification{id,userId,type,context,createdAt,user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMessageNotification{id,userId,type,activityId,context,createdAt,message{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMentionNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplySubscribedNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentMentionNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentReplyNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentSubscribedNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentLikeNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadLikeNotification{id,userId,type,threadId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on RelatedMediaAdditionNotification{id,type,context,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDataChangeNotification{id,type,mediaId,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaMergeNotification{id,type,mediaId,deletedMediaTitles,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDeletionNotification{id,type,deletedMediaTitle,context,reason,createdAt,}}}}""", + """{User(id:$id){unreadNotificationCount}Page(page:$page,perPage:$ITEMS_PER_PAGE){pageInfo{currentPage,hasNextPage}notifications(resetNotificationCount:$reset , ${if (type == true) typeIn else ""}){__typename...on AiringNotification{id,type,animeId,episode,contexts,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}},}...on FollowingNotification{id,userId,type,context,createdAt,user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMessageNotification{id,userId,type,activityId,context,createdAt,message{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMentionNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplySubscribedNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentMentionNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentReplyNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentSubscribedNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentLikeNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadLikeNotification{id,userId,type,threadId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on RelatedMediaAdditionNotification{id,type,context,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDataChangeNotification{id,type,mediaId,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaMergeNotification{id,type,mediaId,deletedMediaTitles,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDeletionNotification{id,type,deletedMediaTitle,context,reason,createdAt,}}}}""", force = true ) if (res != null && resetNotification) { diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt index e75383a1..f1db7ff6 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt @@ -91,17 +91,16 @@ class AnilistHomeViewModel : ViewModel() { fun getHidden(): LiveData> = hidden - @Suppress("UNCHECKED_CAST") suspend fun initHomePage() { val res = Anilist.query.initHomePage() - res["currentAnime"]?.let { animeContinue.postValue(it as ArrayList?) } - res["favoriteAnime"]?.let { animeFav.postValue(it as ArrayList?) } - res["plannedAnime"]?.let { animePlanned.postValue(it as ArrayList?) } - res["currentManga"]?.let { mangaContinue.postValue(it as ArrayList?) } - res["favoriteManga"]?.let { mangaFav.postValue(it as ArrayList?) } - res["plannedManga"]?.let { mangaPlanned.postValue(it as ArrayList?) } - res["recommendations"]?.let { recommendation.postValue(it as ArrayList?) } - res["hidden"]?.let { hidden.postValue(it as ArrayList?) } + res["currentAnime"]?.let { animeContinue.postValue(it) } + res["favoriteAnime"]?.let { animeFav.postValue(it) } + res["currentAnimePlanned"]?.let { animePlanned.postValue(it) } + res["currentManga"]?.let { mangaContinue.postValue(it) } + res["favoriteManga"]?.let { mangaFav.postValue(it) } + res["currentMangaPlanned"]?.let { mangaPlanned.postValue(it) } + res["recommendations"]?.let { recommendation.postValue(it) } + res["hidden"]?.let { hidden.postValue(it) } } suspend fun loadMain(context: FragmentActivity) { diff --git a/app/src/main/java/ani/dantotsu/home/HomeFragment.kt b/app/src/main/java/ani/dantotsu/home/HomeFragment.kt index 43bf8bea..dfd39e6a 100644 --- a/app/src/main/java/ani/dantotsu/home/HomeFragment.kt +++ b/app/src/main/java/ani/dantotsu/home/HomeFragment.kt @@ -50,6 +50,7 @@ import ani.dantotsu.statusBarHeight import ani.dantotsu.util.Logger import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlin.math.max @@ -457,53 +458,56 @@ class HomeFragment : Fragment() { var running = false val live = Refresh.activity.getOrPut(1) { MutableLiveData(true) } - live.observe(viewLifecycleOwner) - { - if (!running && it) { + live.observe(viewLifecycleOwner) { shouldRefresh -> + if (!running && shouldRefresh) { running = true scope.launch { withContext(Dispatchers.IO) { - //Get userData First - Anilist.userid = - PrefManager.getNullableVal(PrefName.AnilistUserId, null) - ?.toIntOrNull() + // Get user data first + Anilist.userid = PrefManager.getNullableVal(PrefName.AnilistUserId, null)?.toIntOrNull() if (Anilist.userid == null) { - getUserId(requireContext()) { - load() - } - } else { - CoroutineScope(Dispatchers.IO).launch { + withContext(Dispatchers.Main) { getUserId(requireContext()) { load() } } + } else { + getUserId(requireContext()) { + load() + } } model.loaded = true - CoroutineScope(Dispatchers.IO).launch { - model.setListImages() - } + model.setListImages() + } - var empty = true - val homeLayoutShow: List = - PrefManager.getVal(PrefName.HomeLayout) - model.initHomePage() - model.initUserStatus() - (array.indices).forEach { i -> + var empty = true + val homeLayoutShow: List = PrefManager.getVal(PrefName.HomeLayout) + + withContext(Dispatchers.Main) { + homeLayoutShow.indices.forEach { i -> if (homeLayoutShow.elementAt(i)) { empty = false - } else withContext(Dispatchers.Main) { + } else { containers[i].visibility = View.GONE } } - model.empty.postValue(empty) } + + val initHomePage = async(Dispatchers.IO) { model.initHomePage() } + val initUserStatus = async(Dispatchers.IO) { model.initUserStatus() } + initHomePage.await() + initUserStatus.await() + + withContext(Dispatchers.Main) { + model.empty.postValue(empty) + binding.homeHiddenItemsContainer.visibility = View.GONE + } + live.postValue(false) _binding?.homeRefresh?.isRefreshing = false running = false } - binding.homeHiddenItemsContainer.visibility = View.GONE } - } }