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 9fe7e9d7..a10f327c 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt @@ -66,6 +66,32 @@ class AnilistQueries { show = true ) } + suspend fun userFavMedia(anime: Boolean, id: Int): ArrayList { + var hasNextPage = true + var page = 0 + + suspend fun getNextPage(page: Int): List { + val response = executeQuery("""{${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() + 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? { val response = executeQuery( 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 f9a5850e..ce25b539 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt @@ -332,4 +332,20 @@ class GenresViewModel : ViewModel() { } } } +} + +class ProfileViewModel : ViewModel(){ + private val animeFav: MutableLiveData> = + MutableLiveData>(null) + fun getAnimeFav(): LiveData> = animeFav + suspend fun setAnimeFav(id: Int) { + animeFav.postValue(Anilist.query.userFavMedia(true, id)) + } + + private val mangaFav: MutableLiveData> = + MutableLiveData>(null) + fun getMangaFav(): LiveData> = mangaFav + suspend fun setMangaFav(id: Int) { + mangaFav.postValue(Anilist.query.userFavMedia(false, id)) + } } \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/profile/ProfileActivity.kt b/app/src/main/java/ani/dantotsu/profile/ProfileActivity.kt index b8517523..05a452f0 100644 --- a/app/src/main/java/ani/dantotsu/profile/ProfileActivity.kt +++ b/app/src/main/java/ani/dantotsu/profile/ProfileActivity.kt @@ -53,7 +53,7 @@ class ProfileActivity : AppCompatActivity(){ navBar.addTab(profileTab) navBar.addTab(statsTab) navBar.visibility = View.GONE - binding.mediaViewPager.isUserInputEnabled = false + binding.profileViewPager.isUserInputEnabled = false lifecycleScope.launch(Dispatchers.IO) { val userid = intent.getIntExtra("userId", 0) val respond = Anilist.query.getUserProfile(userid) @@ -64,7 +64,8 @@ class ProfileActivity : AppCompatActivity(){ return@launch } withContext(Dispatchers.Main) { - binding.mediaViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle, user, this@ProfileActivity) + binding.profileViewPager.updateLayoutParams { bottomMargin = navBarHeight } + binding.profileViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle, user, this@ProfileActivity) navBar.visibility = View.VISIBLE navBar.selectTabAt(selected) navBar.setOnTabSelectListener(object : AnimatedBottomBar.OnTabSelectListener { @@ -75,7 +76,7 @@ class ProfileActivity : AppCompatActivity(){ newTab: AnimatedBottomBar.Tab ) { selected = newIndex - binding.mediaViewPager.setCurrentItem(selected, true) + binding.profileViewPager.setCurrentItem(selected, true) } }) val userLevel = intent.getStringExtra("username")?: "" diff --git a/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt b/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt index 2fa98c9c..7ff3f0cc 100644 --- a/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt +++ b/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt @@ -5,13 +5,27 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.animation.LayoutAnimationController import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.LiveData +import androidx.lifecycle.lifecycleScope +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import ani.dantotsu.bottomBar import ani.dantotsu.buildMarkwon +import ani.dantotsu.connections.anilist.ProfileViewModel import ani.dantotsu.connections.anilist.api.Query import ani.dantotsu.databinding.FragmentProfileBinding import ani.dantotsu.loadImage +import ani.dantotsu.media.Media +import ani.dantotsu.media.MediaAdaptor import ani.dantotsu.media.user.ListActivity +import ani.dantotsu.setSlideIn +import ani.dantotsu.setSlideUp +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch class ProfileFragment(private val user: Query.UserProfile, private val activity: ProfileActivity): Fragment() { lateinit var binding: FragmentProfileBinding @@ -24,6 +38,7 @@ class ProfileFragment(private val user: Query.UserProfile, private val activity: return binding.root } + val model: ProfileViewModel by activityViewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val markwon = buildMarkwon(activity, false) @@ -58,5 +73,66 @@ class ProfileFragment(private val user: Query.UserProfile, private val activity: binding.statsMangaMeanScore.text = user.statistics.manga.meanScore.toString() + viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) { + model.setAnimeFav(user.id) + model.setMangaFav(user.id) + } + + initRecyclerView( + model.getAnimeFav(), + binding.profileFavAnimeContainer, + binding.profileFavAnimeRecyclerView, + binding.profileFavAnimeProgressBar, + binding.profileFavAnimeEmpty, + binding.profileFavAnime + ) + + initRecyclerView( + model.getMangaFav(), + binding.profileFavMangaContainer, + binding.profileFavMangaRecyclerView, + binding.profileFavMangaProgressBar, + binding.profileFavMangaEmpty, + binding.profileFavManga + ) } + private fun initRecyclerView( + mode: LiveData>, + container: View, + recyclerView: RecyclerView, + progress: View, + empty: View, + title: View + ) { + container.visibility = View.VISIBLE + progress.visibility = View.VISIBLE + recyclerView.visibility = View.GONE + empty.visibility = View.GONE + title.visibility = View.INVISIBLE + + mode.observe(viewLifecycleOwner) { + recyclerView.visibility = View.GONE + empty.visibility = View.GONE + if (it != null) { + if (it.isNotEmpty()) { + recyclerView.adapter = MediaAdaptor(0, it, requireActivity()) + recyclerView.layoutManager = LinearLayoutManager( + requireContext(), + LinearLayoutManager.HORIZONTAL, + false + ) + recyclerView.visibility = View.VISIBLE + recyclerView.layoutAnimation = + LayoutAnimationController(setSlideIn(), 0.25f) + + } else { + empty.visibility = View.VISIBLE + } + title.visibility = View.VISIBLE + title.startAnimation(setSlideUp()) + progress.visibility = View.GONE + } + } + } + } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_profile.xml b/app/src/main/res/layout/activity_profile.xml index 99eaf7ca..622026fc 100644 --- a/app/src/main/res/layout/activity_profile.xml +++ b/app/src/main/res/layout/activity_profile.xml @@ -22,6 +22,7 @@ @@ -94,7 +96,7 @@ app:layout_behavior="@string/appbar_scrolling_view_behavior"> @@ -337,10 +337,10 @@ android:id="@+id/profileUserBioTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="18dp" - android:layout_marginTop="24dp" - android:textColor="?attr/colorPrimary" - android:fontFamily="@font/poppins_semi_bold" + android:layout_marginStart="32dp" + android:layout_marginTop="8dp" + android:layout_marginEnd="32dp" + android:fontFamily="@font/poppins_bold" android:text="Bio" android:textSize="18sp" tools:ignore="HardcodedText" /> @@ -349,13 +349,159 @@ android:id="@+id/profileUserBio" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:fontFamily="@font/poppins_semi_bold" - android:paddingStart="32dp" - android:paddingTop="16dp" - android:paddingEnd="32dp" - android:alpha="0.58" - android:textSize="12sp" - tools:text="@tools:sample/lorem"/> + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:ellipsize="end" + android:maxLines="5" + android:padding="16dp" + tools:text="@string/slogan"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file