feat(profile): added fav characters and staff

This commit is contained in:
aayush262 2024-03-05 17:10:04 +05:30
parent 8a1097cd35
commit 89b6f28b9f
6 changed files with 212 additions and 89 deletions

View file

@ -32,13 +32,6 @@ import kotlin.system.measureTimeMillis
class AnilistQueries { class AnilistQueries {
suspend fun toggleFollow(id: Int): Query.ToggleFollow? {
val response = executeQuery<Query.ToggleFollow>(
"""mutation{ToggleFollow(userId:$id){id, isFollowing, isFollower}}"""
)
return response
}
suspend fun getUserData(): Boolean { suspend fun getUserData(): Boolean {
val response: Query.Viewer? val response: Query.Viewer?
measureTimeMillis { measureTimeMillis {
@ -59,47 +52,6 @@ class AnilistQueries {
return true return true
} }
suspend fun getUserProfile(id: Int): Query.UserProfileResponse? {
return executeQuery<Query.UserProfileResponse>(
"""{user:User(id:$id){id,name,about(asHtml:true)avatar{medium,large},bannerImage,isFollowing,isFollower,isBlocked,favourites{anime{nodes{id,coverImage{extraLarge,large,medium,color}}}manga{nodes{id,coverImage{extraLarge,large,medium,color}}}characters{nodes{id,image{large,medium}}}staff{nodes{id,image{large,medium}}}studios{nodes{id,name}}}statistics{anime{count,meanScore,standardDeviation,minutesWatched,episodesWatched,chaptersRead,volumesRead}manga{count,meanScore,standardDeviation,minutesWatched,episodesWatched,chaptersRead,volumesRead}}siteUrl}}""",
force = true
)
}
suspend fun getUserStatistics(id: Int, sort: String = "ID"): Query.StatisticsResponse? {
return executeQuery<Query.StatisticsResponse>(
"""{User(id:$id){id name mediaListOptions{scoreFormat}statistics{anime{...UserStatistics}manga{...UserStatistics}}}}fragment UserStatistics on UserStatistics{count meanScore standardDeviation minutesWatched episodesWatched chaptersRead volumesRead formats(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds format}statuses(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds status}scores(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds score}lengths(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds length}releaseYears(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds releaseYear}startYears(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds startYear}genres(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds genre}tags(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds tag{id name}}countries(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds country}voiceActors(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds voiceActor{id name{first middle last full native alternative userPreferred}}characterIds}staff(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds staff{id name{first middle last full native alternative userPreferred}}}studios(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds studio{id name isAnimationStudio}}}""",
force = true,
show = true
)
}
suspend fun userFavMedia(anime: Boolean, id: Int): ArrayList<Media> {
var hasNextPage = true
var page = 0
suspend fun getNextPage(page: Int): List<Media> {
val response = executeQuery<Query.User>("""{${userFavMediaQuery(anime, page, id)}}""")
val favourites = response?.data?.user?.favourites
val apiMediaList = if (anime) favourites?.anime else favourites?.manga
hasNextPage = apiMediaList?.pageInfo?.hasNextPage ?: false
return apiMediaList?.edges?.mapNotNull {
it.node?.let { i ->
Media(i).apply { isFav = true }
}
} ?: return listOf()
}
val responseArray = arrayListOf<Media>()
while (hasNextPage) {
page++
responseArray.addAll(getNextPage(page))
}
return responseArray
}
private fun userFavMediaQuery(anime: Boolean, page: Int, id: Int): String {
return """User(id:${id}){id favourites{${if (anime) "anime" else "manga"}(page:$page){pageInfo{hasNextPage}edges{favouriteOrder node{id idMal isAdult mediaListEntry{ progress private score(format:POINT_100) status } chapters isFavourite format episodes nextAiringEpisode{episode}meanScore isFavourite format startDate{year month day} title{english romaji userPreferred}type status(version:2)bannerImage coverImage{large}}}}}}"""
}
suspend fun getMedia(id: Int, mal: Boolean = false): Media? { suspend fun getMedia(id: Int, mal: Boolean = false): Media? {
val response = executeQuery<Query.Media>( val response = executeQuery<Query.Media>(
"""{Media(${if (!mal) "id:" else "idMal:"}$id){id idMal status chapters episodes nextAiringEpisode{episode}type meanScore isAdult isFavourite format bannerImage coverImage{large}title{english romaji userPreferred}mediaListEntry{progress private score(format:POINT_100)status}}}""", """{Media(${if (!mal) "id:" else "idMal:"}$id){id idMal status chapters episodes nextAiringEpisode{episode}type meanScore isAdult isFavourite format bannerImage coverImage{large}title{english romaji userPreferred}mediaListEntry{progress private score(format:POINT_100)status}}}""",
@ -368,12 +320,12 @@ class AnilistQueries {
return """ MediaListCollection(userId: ${Anilist.userid}, type: $type, status: $status , sort: UPDATED_TIME ) { lists { entries { progress private score(format:POINT_100) status media { id idMal type isAdult status chapters episodes nextAiringEpisode {episode} meanScore isFavourite format bannerImage coverImage{large} title { english romaji userPreferred } } } } } """ return """ MediaListCollection(userId: ${Anilist.userid}, type: $type, status: $status , sort: UPDATED_TIME ) { lists { entries { progress private score(format:POINT_100) status media { id idMal type isAdult status chapters episodes nextAiringEpisode {episode} meanScore isFavourite format bannerImage coverImage{large} title { english romaji userPreferred } } } } } """
} }
suspend fun favMedia(anime: Boolean): ArrayList<Media> { suspend fun favMedia(anime: Boolean, id: Int? = Anilist.userid ): ArrayList<Media> {
var hasNextPage = true var hasNextPage = true
var page = 0 var page = 0
suspend fun getNextPage(page: Int): List<Media> { suspend fun getNextPage(page: Int): List<Media> {
val response = executeQuery<Query.User>("""{${favMediaQuery(anime, page)}}""") val response = executeQuery<Query.User>("""{${favMediaQuery(anime, page, id)}}""")
val favourites = response?.data?.user?.favourites val favourites = response?.data?.user?.favourites
val apiMediaList = if (anime) favourites?.anime else favourites?.manga val apiMediaList = if (anime) favourites?.anime else favourites?.manga
hasNextPage = apiMediaList?.pageInfo?.hasNextPage ?: false hasNextPage = apiMediaList?.pageInfo?.hasNextPage ?: false
@ -392,8 +344,8 @@ class AnilistQueries {
return responseArray return responseArray
} }
private fun favMediaQuery(anime: Boolean, page: Int): String { private fun favMediaQuery(anime: Boolean, page: Int, id: Int?= Anilist.userid ): String {
return """User(id:${Anilist.userid}){id favourites{${if (anime) "anime" else "manga"}(page:$page){pageInfo{hasNextPage}edges{favouriteOrder node{id idMal isAdult mediaListEntry{ progress private score(format:POINT_100) status } chapters isFavourite format episodes nextAiringEpisode{episode}meanScore isFavourite format startDate{year month day} title{english romaji userPreferred}type status(version:2)bannerImage coverImage{large}}}}}}""" return """User(id:${id}){id favourites{${if (anime) "anime" else "manga"}(page:$page){pageInfo{hasNextPage}edges{favouriteOrder node{id idMal isAdult mediaListEntry{ progress private score(format:POINT_100) status } chapters isFavourite format episodes nextAiringEpisode{episode}meanScore isFavourite format startDate{year month day} title{english romaji userPreferred}type status(version:2)bannerImage coverImage{large}}}}}}"""
} }
suspend fun recommendations(): ArrayList<Media> { suspend fun recommendations(): ArrayList<Media> {
@ -676,7 +628,7 @@ class AnilistQueries {
if (!sorted.containsKey(it.key)) sorted[it.key] = it.value if (!sorted.containsKey(it.key)) sorted[it.key] = it.value
} }
sorted["Favourites"] = favMedia(anime) sorted["Favourites"] = favMedia(anime, userId)
sorted["Favourites"]?.sortWith(compareBy { it.userFavOrder }) sorted["Favourites"]?.sortWith(compareBy { it.userFavOrder })
//favMedia doesn't fill userProgress, so we need to fill it manually by searching :( //favMedia doesn't fill userProgress, so we need to fill it manually by searching :(
sorted["Favourites"]?.forEach { fav -> sorted["Favourites"]?.forEach { fav ->
@ -1281,4 +1233,70 @@ Page(page:$page,perPage:50) {
return author return author
} }
suspend fun toggleFollow(id: Int): Query.ToggleFollow? {
val response = executeQuery<Query.ToggleFollow>(
"""mutation{ToggleFollow(userId:$id){id, isFollowing, isFollower}}"""
)
return response
}
suspend fun getUserProfile(id: Int): Query.UserProfileResponse? {
return executeQuery<Query.UserProfileResponse>(
"""{user:User(id:$id){id,name,about(asHtml:true)avatar{medium,large},bannerImage,isFollowing,isFollower,isBlocked,favourites{anime{nodes{id,coverImage{extraLarge,large,medium,color}}}manga{nodes{id,coverImage{extraLarge,large,medium,color}}}characters{nodes{id,name{first,middle,last,full,native,alternative,userPreferred},image{large,medium}}}staff{nodes{id,name{first,middle,last,full,native,alternative,userPreferred},image{large,medium}}}studios{nodes{id,name}}}statistics{anime{count,meanScore,standardDeviation,minutesWatched,episodesWatched,chaptersRead,volumesRead}manga{count,meanScore,standardDeviation,minutesWatched,episodesWatched,chaptersRead,volumesRead}}siteUrl}}""",
force = true
)
}
suspend fun getUserStatistics(id: Int, sort: String = "ID"): Query.StatisticsResponse? {
return executeQuery<Query.StatisticsResponse>(
"""{User(id:$id){id name mediaListOptions{scoreFormat}statistics{anime{...UserStatistics}manga{...UserStatistics}}}}fragment UserStatistics on UserStatistics{count meanScore standardDeviation minutesWatched episodesWatched chaptersRead volumesRead formats(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds format}statuses(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds status}scores(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds score}lengths(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds length}releaseYears(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds releaseYear}startYears(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds startYear}genres(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds genre}tags(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds tag{id name}}countries(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds country}voiceActors(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds voiceActor{id name{first middle last full native alternative userPreferred}}characterIds}staff(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds staff{id name{first middle last full native alternative userPreferred}}}studios(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds studio{id name isAnimationStudio}}}""",
force = true,
show = true
)
}
suspend fun userFavMedia(anime: Boolean, id: Int): ArrayList<Media> {
var hasNextPage = true
var page = 0
suspend fun getNextPage(page: Int): List<Media> {
val response = executeQuery<Query.User>("""{${userFavMediaQuery(anime, page, id)}}""")
val favourites = response?.data?.user?.favourites
val apiMediaList = if (anime) favourites?.anime else favourites?.manga
hasNextPage = apiMediaList?.pageInfo?.hasNextPage ?: false
return apiMediaList?.edges?.mapNotNull {
it.node?.let { i ->
Media(i).apply { isFav = true }
}
} ?: return listOf()
}
val responseArray = arrayListOf<Media>()
while (hasNextPage) {
page++
responseArray.addAll(getNextPage(page))
}
return responseArray
}
private fun userFavMediaQuery(anime: Boolean, page: Int, id: Int): String {
return """User(id:${id}){id favourites{${if (anime) "anime" else "manga"}(page:$page){pageInfo{hasNextPage}edges{favouriteOrder node{id idMal isAdult mediaListEntry{ progress private score(format:POINT_100) status } chapters isFavourite format episodes nextAiringEpisode{episode}meanScore isFavourite format startDate{year month day} title{english romaji userPreferred}type status(version:2)bannerImage coverImage{large}}}}}}"""
}
private suspend fun userBannerImage(type: String,id: Int?): String? {
val response =
executeQuery<Query.MediaListCollection>("""{ MediaListCollection(userId: ${id}, type: $type, chunk:1,perChunk:25, sort: [SCORE_DESC,UPDATED_TIME_DESC]) { lists { entries{ media { id bannerImage } } } } } """)
val random = response?.data?.mediaListCollection?.lists?.mapNotNull {
it.entries?.mapNotNull { entry ->
val imageUrl = entry.media?.bannerImage
if (imageUrl != null && imageUrl != "null") imageUrl
else null
}
}?.flatten()?.randomOrNull() ?: return null
return random
}
suspend fun getUserBannerImages(id: Int? = Anilist.userid): ArrayList<String?> {
val default = arrayListOf<String?>(null, null)
default[0] = userBannerImage("ANIME", id)
default[1] = userBannerImage("MANGA",id)
return default
}
} }

View file

@ -10,6 +10,7 @@ import ani.dantotsu.R
import ani.dantotsu.connections.comments.CommentsAPI import ani.dantotsu.connections.comments.CommentsAPI
import ani.dantotsu.connections.discord.Discord import ani.dantotsu.connections.discord.Discord
import ani.dantotsu.connections.mal.MAL import ani.dantotsu.connections.mal.MAL
import ani.dantotsu.media.Character
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.others.AppUpdater import ani.dantotsu.others.AppUpdater
import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefManager
@ -334,18 +335,24 @@ class GenresViewModel : ViewModel() {
} }
} }
class ProfileViewModel : ViewModel(){ class ProfileViewModel : ViewModel(){
private val animeFav: MutableLiveData<ArrayList<Media>> =
MutableLiveData<ArrayList<Media>>(null)
fun getAnimeFav(): LiveData<ArrayList<Media>> = animeFav
suspend fun setAnimeFav(id: Int) {
animeFav.postValue(Anilist.query.userFavMedia(true, id))
}
private val mangaFav: MutableLiveData<ArrayList<Media>> = private val mangaFav: MutableLiveData<ArrayList<Media>> =
MutableLiveData<ArrayList<Media>>(null) MutableLiveData<ArrayList<Media>>(null)
fun getMangaFav(): LiveData<ArrayList<Media>> = mangaFav fun getMangaFav(): LiveData<ArrayList<Media>> = mangaFav
suspend fun setMangaFav(id: Int) {
private val animeFav: MutableLiveData<ArrayList<Media>> =
MutableLiveData<ArrayList<Media>>(null)
fun getAnimeFav(): LiveData<ArrayList<Media>> = animeFav
private val listImages: MutableLiveData<ArrayList<String?>> =
MutableLiveData<ArrayList<String?>>(arrayListOf())
fun getListImages(): LiveData<ArrayList<String?>> = listImages
suspend fun setData(id: Int) {
mangaFav.postValue(Anilist.query.userFavMedia(false, id)) mangaFav.postValue(Anilist.query.userFavMedia(false, id))
animeFav.postValue(Anilist.query.userFavMedia(true, id))
listImages.postValue(Anilist.query.getUserBannerImages(id))
} }
} }

View file

@ -143,7 +143,7 @@ class Query {
data class ToggleFollow( data class ToggleFollow(
@SerialName("data") @SerialName("data")
val data: Data? val data: Data?
) : java.io.Serializable { ) {
@Serializable @Serializable
data class Data( data class Data(
@SerialName("ToggleFollow") @SerialName("ToggleFollow")
@ -156,7 +156,7 @@ class Query {
data class GenreCollection( data class GenreCollection(
@SerialName("data") @SerialName("data")
val data: Data val data: Data
) : java.io.Serializable { ) {
@Serializable @Serializable
data class Data( data class Data(
@SerialName("GenreCollection") @SerialName("GenreCollection")
@ -168,7 +168,7 @@ class Query {
data class MediaTagCollection( data class MediaTagCollection(
@SerialName("data") @SerialName("data")
val data: Data val data: Data
) : java.io.Serializable { ) {
@Serializable @Serializable
data class Data( data class Data(
@SerialName("MediaTagCollection") @SerialName("MediaTagCollection")
@ -180,7 +180,7 @@ class Query {
data class User( data class User(
@SerialName("data") @SerialName("data")
val data: Data val data: Data
) : java.io.Serializable { ) {
@Serializable @Serializable
data class Data( data class Data(
@SerialName("User") @SerialName("User")
@ -192,7 +192,7 @@ class Query {
data class UserProfileResponse( data class UserProfileResponse(
@SerialName("data") @SerialName("data")
val data: Data val data: Data
) : java.io.Serializable { ) {
@Serializable @Serializable
data class Data( data class Data(
@SerialName("user") @SerialName("user")
@ -219,7 +219,7 @@ class Query {
@SerialName("isBlocked") @SerialName("isBlocked")
val isBlocked: Boolean, val isBlocked: Boolean,
@SerialName("favourites") @SerialName("favourites")
val favorites: UserFavorites?, val favourites: UserFavourites?,
@SerialName("statistics") @SerialName("statistics")
val statistics: NNUserStatisticTypes, val statistics: NNUserStatisticTypes,
@SerialName("siteUrl") @SerialName("siteUrl")
@ -244,21 +244,21 @@ class Query {
): java.io.Serializable ): java.io.Serializable
@Serializable @Serializable
data class UserFavorites( data class UserFavourites(
@SerialName("anime") @SerialName("anime")
val anime: UserMediaFavoritesCollection, val anime: UserMediaFavouritesCollection,
@SerialName("manga") @SerialName("manga")
val manga: UserMediaFavoritesCollection, val manga: UserMediaFavouritesCollection,
@SerialName("characters") @SerialName("characters")
val characters: UserCharacterFavoritesCollection, val characters: UserCharacterFavouritesCollection,
@SerialName("staff") @SerialName("staff")
val staff: UserStaffFavoritesCollection, val staff: UserStaffFavouritesCollection,
@SerialName("studios") @SerialName("studios")
val studios: UserStudioFavoritesCollection, val studios: UserStudioFavouritesCollection,
): java.io.Serializable ): java.io.Serializable
@Serializable @Serializable
data class UserMediaFavoritesCollection( data class UserMediaFavouritesCollection(
@SerialName("nodes") @SerialName("nodes")
val nodes: List<UserMediaImageFavorite>, val nodes: List<UserMediaImageFavorite>,
): java.io.Serializable ): java.io.Serializable
@ -272,7 +272,7 @@ class Query {
): java.io.Serializable ): java.io.Serializable
@Serializable @Serializable
data class UserCharacterFavoritesCollection( data class UserCharacterFavouritesCollection(
@SerialName("nodes") @SerialName("nodes")
val nodes: List<UserCharacterImageFavorite>, val nodes: List<UserCharacterImageFavorite>,
): java.io.Serializable ): java.io.Serializable
@ -281,18 +281,20 @@ class Query {
data class UserCharacterImageFavorite( data class UserCharacterImageFavorite(
@SerialName("id") @SerialName("id")
val id: Int, val id: Int,
@SerialName("name")
val name: CharacterName,
@SerialName("image") @SerialName("image")
val image: CharacterImage val image: CharacterImage
): java.io.Serializable ): java.io.Serializable
@Serializable @Serializable
data class UserStaffFavoritesCollection( data class UserStaffFavouritesCollection(
@SerialName("nodes") @SerialName("nodes")
val nodes: List<UserCharacterImageFavorite>, //downstream it's the same as character val nodes: List<UserCharacterImageFavorite>, //downstream it's the same as character
): java.io.Serializable ): java.io.Serializable
@Serializable @Serializable
data class UserStudioFavoritesCollection( data class UserStudioFavouritesCollection(
@SerialName("nodes") @SerialName("nodes")
val nodes: List<UserStudioFavorite>, val nodes: List<UserStudioFavorite>,
): java.io.Serializable ): java.io.Serializable

View file

@ -18,6 +18,8 @@ import ani.dantotsu.connections.anilist.ProfileViewModel
import ani.dantotsu.connections.anilist.api.Query import ani.dantotsu.connections.anilist.api.Query
import ani.dantotsu.databinding.FragmentProfileBinding import ani.dantotsu.databinding.FragmentProfileBinding
import ani.dantotsu.loadImage import ani.dantotsu.loadImage
import ani.dantotsu.media.Character
import ani.dantotsu.media.CharacterAdapter
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaAdaptor import ani.dantotsu.media.MediaAdaptor
import ani.dantotsu.media.user.ListActivity import ani.dantotsu.media.user.ListActivity
@ -45,8 +47,11 @@ class ProfileFragment() : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
activity = requireActivity() as ProfileActivity activity = requireActivity() as ProfileActivity
user = arguments?.getSerializable("user") as Query.UserProfile viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
model.setData(user.id)
}
user = arguments?.getSerializable("user") as Query.UserProfile
val backGroundColorTypedValue = TypedValue() val backGroundColorTypedValue = TypedValue()
val textColorTypedValue = TypedValue() val textColorTypedValue = TypedValue()
activity.theme.resolveAttribute( activity.theme.resolveAttribute(
@ -74,7 +79,8 @@ class ProfileFragment() : Fragment() {
"UTF-8", "UTF-8",
null null
) )
binding.userInfoContainer.visibility = if (user.about != null) View.VISIBLE else View.GONE binding.userInfoContainer.visibility =
if (user.about != null) View.VISIBLE else View.GONE
binding.profileAnimeList.setOnClickListener { binding.profileAnimeList.setOnClickListener {
ContextCompat.startActivity( ContextCompat.startActivity(
@ -92,8 +98,6 @@ class ProfileFragment() : Fragment() {
.putExtra("username", user.name), null .putExtra("username", user.name), null
) )
} }
binding.profileAnimeListImage.loadImage("https://bit.ly/31bsIHq")
binding.profileMangaListImage.loadImage("https://bit.ly/2ZGfcuG")
binding.statsEpisodesWatched.text = user.statistics.anime.episodesWatched.toString() binding.statsEpisodesWatched.text = user.statistics.anime.episodesWatched.toString()
binding.statsDaysWatched.text = binding.statsDaysWatched.text =
(user.statistics.anime.minutesWatched / (24 * 60)).toString() (user.statistics.anime.minutesWatched / (24 * 60)).toString()
@ -103,13 +107,12 @@ class ProfileFragment() : Fragment() {
binding.statsVolumeRead.text = (user.statistics.manga.volumesRead).toString() binding.statsVolumeRead.text = (user.statistics.manga.volumesRead).toString()
binding.statsTotalManga.text = user.statistics.manga.count.toString() binding.statsTotalManga.text = user.statistics.manga.count.toString()
binding.statsMangaMeanScore.text = user.statistics.manga.meanScore.toString() binding.statsMangaMeanScore.text = user.statistics.manga.meanScore.toString()
model.getListImages().observe(viewLifecycleOwner) {
if (it.isNotEmpty()) {
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) { binding.profileAnimeListImage.loadImage(it[0] ?: "https://bit.ly/31bsIHq")
model.setAnimeFav(user.id) binding.profileMangaListImage.loadImage(it[1] ?: "https://bit.ly/2ZGfcuG")
model.setMangaFav(user.id) }
} }
initRecyclerView( initRecyclerView(
model.getAnimeFav(), model.getAnimeFav(),
binding.profileFavAnimeContainer, binding.profileFavAnimeContainer,
@ -127,12 +130,42 @@ class ProfileFragment() : Fragment() {
binding.profileFavMangaEmpty, binding.profileFavMangaEmpty,
binding.profileFavManga binding.profileFavManga
) )
val favCharacter = arrayListOf<Character>()
user.favourites?.characters?.nodes?.forEach { i ->
favCharacter.add(Character(i.id, i.name.full, i.image.large, i.image.large, ""))
}
if (favCharacter.isEmpty()) {
binding.profileFavCharactersContainer.visibility = View.GONE
}
binding.profileFavCharactersRecycler.adapter = CharacterAdapter(favCharacter)
binding.profileFavCharactersRecycler.layoutManager = LinearLayoutManager(
requireContext(),
LinearLayoutManager.HORIZONTAL,
false
)
val favStaff = arrayListOf<Character>()
user.favourites?.staff?.nodes?.forEach { i ->
favStaff.add(Character(i.id, i.name.full, i.image.large, i.image.large, ""))
}
if (favStaff.isEmpty()) {
binding.profileFavStaffContainer.visibility = View.GONE
}
binding.profileFavStaffRecycler.adapter = CharacterAdapter(favStaff)
binding.profileFavStaffRecycler.layoutManager = LinearLayoutManager(
requireContext(),
LinearLayoutManager.HORIZONTAL,
false
)
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (this::binding.isInitialized) { if (this::binding.isInitialized) {
binding.root.requestLayout() binding.root.requestLayout()
} }
} }

View file

@ -442,7 +442,7 @@ class PlayerSettingsActivity : AppCompatActivity() {
"Poppins", "Poppins",
"Poppins Thin", "Poppins Thin",
"Century Gothic", "Century Gothic",
"Century Gothic Bold", "Levenim MT Bold",
"Blocky" "Blocky"
) )
val fontDialog = AlertDialog.Builder(this, R.style.MyPopup) val fontDialog = AlertDialog.Builder(this, R.style.MyPopup)

View file

@ -4,7 +4,8 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical"
tools:ignore="HardcodedText">
<LinearLayout <LinearLayout
android:id="@+id/userListContainer" android:id="@+id/userListContainer"
@ -333,6 +334,7 @@
android:id="@+id/userInfoContainer" android:id="@+id/userInfoContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
@ -506,4 +508,65 @@
tools:orientation="horizontal" /> tools:orientation="horizontal" />
</FrameLayout> </FrameLayout>
</LinearLayout> </LinearLayout>
<LinearLayout
android:id="@+id/profileFavCharactersContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:visibility="gone">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:fontFamily="@font/poppins_bold"
android:text="Favorite Characters"
android:textSize="16sp" />
<ani.dantotsu.FadingEdgeRecyclerView
android:id="@+id/profileFavCharactersRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:nestedScrollingEnabled="true"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:requiresFadingEdge="horizontal"
tools:itemCount="4"
tools:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
tools:listitem="@layout/item_media_compact"
tools:orientation="horizontal" />
</LinearLayout>
<LinearLayout
android:id="@+id/profileFavStaffContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:visibility="gone">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:fontFamily="@font/poppins_bold"
android:text="Favorite Staff"
android:textSize="16sp" />
<ani.dantotsu.FadingEdgeRecyclerView
android:id="@+id/profileFavStaffRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:nestedScrollingEnabled="true"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:requiresFadingEdge="horizontal"
tools:itemCount="4"
tools:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
tools:listitem="@layout/item_media_compact"
tools:orientation="horizontal" />
</LinearLayout>
</LinearLayout> </LinearLayout>