feat: following / followers page

This commit is contained in:
rebelonion 2024-03-05 19:33:42 -06:00
parent 8da0092561
commit 31afbd547e
17 changed files with 546 additions and 215 deletions

View file

@ -1,12 +1,24 @@
package ani.dantotsu.profile
import android.content.Intent
import android.os.Bundle
import android.view.ViewGroup.MarginLayoutParams
import android.widget.ImageButton
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import ani.dantotsu.R
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.api.User
import ani.dantotsu.databinding.ActivityFollowBinding
import ani.dantotsu.initActivity
import ani.dantotsu.navBarHeight
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.themes.ThemeManager
import com.xwray.groupie.GroupieAdapter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -14,19 +26,98 @@ import kotlinx.coroutines.withContext
class FollowActivity : AppCompatActivity(){
private lateinit var binding: ActivityFollowBinding
val adapter = GroupieAdapter()
var users: List<User>? = null
private lateinit var selected: ImageButton
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
initActivity(this)
binding = ActivityFollowBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.listTitle.text = intent.getStringExtra("title")
val layoutType = PrefManager.getVal<Int>(PrefName.FollowerLayout)
selected = getSelected(layoutType)
binding.followerGrid.alpha = 0.33f
binding.followerList.alpha = 0.33f
selected(selected)
binding.root.updateLayoutParams<MarginLayoutParams> { topMargin += navBarHeight }
binding.listRecyclerView.layoutManager = LinearLayoutManager(
this,
LinearLayoutManager.VERTICAL,
false
)
binding.listRecyclerView.adapter = adapter
binding.listBack.setOnClickListener { finish() }
val title = intent.getStringExtra("title")
binding.listTitle.text = title
lifecycleScope.launch(Dispatchers.IO) {
val respond = Anilist.query.userFollowing(intent.getIntExtra("userId", 0))
val user = respond?.data?.following
val respond = when (title) {
"Following" -> Anilist.query.userFollowing(intent.getIntExtra("userId", 0))?.data?.page?.following
"Followers" -> Anilist.query.userFollowers(intent.getIntExtra("userId", 0))?.data?.page?.followers
else -> null
}
users = respond
withContext(Dispatchers.Main) {
user?.id
fillList()
}
}
binding.followerList.setOnClickListener {
selected(it as ImageButton)
PrefManager.setVal(PrefName.FollowerLayout, 0)
fillList()
}
binding.followerGrid.setOnClickListener {
selected(it as ImageButton)
PrefManager.setVal(PrefName.FollowerLayout, 1)
fillList()
}
}
private fun fillList() {
adapter.clear()
binding.listRecyclerView.layoutManager = when (getLayoutType(selected)) {
0 -> LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
1 -> GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false)
else -> LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
}
users?.forEach { user ->
if (getLayoutType(selected) == 0) {
adapter.add(FollowerItem(user.id, user.name ?: "Unknown", user.avatar?.medium, user.bannerImage) { onUserClick(it) })
} else {
adapter.add(GridFollowerItem(user.id, user.name ?: "Unknown", user.avatar?.medium) { onUserClick(it) })
}
}
}
fun selected(it: ImageButton) {
selected.alpha = 0.33f
selected = it
selected.alpha = 1f
}
private fun getSelected(pos: Int): ImageButton {
return when (pos) {
0 -> binding.followerList
1 -> binding.followerGrid
else -> binding.followerList
}
}
private fun getLayoutType(it: ImageButton): Int {
return when (it) {
binding.followerList -> 0
binding.followerGrid -> 1
else -> 0
}
}
private fun onUserClick(id: Int) {
val intent = Intent(this, ProfileActivity::class.java)
intent.putExtra("userId", id)
startActivity(intent)
}
}

View file

@ -0,0 +1,33 @@
package ani.dantotsu.profile
import android.view.View
import ani.dantotsu.R
import ani.dantotsu.databinding.ItemFollowerBinding
import ani.dantotsu.loadImage
import com.xwray.groupie.viewbinding.BindableItem
class FollowerItem(
private val id: Int,
private val name: String,
private val avatar: String?,
private val banner: String?,
val clickCallback: (Int) -> Unit
): BindableItem<ItemFollowerBinding>() {
private lateinit var binding: ItemFollowerBinding
override fun bind(viewBinding: ItemFollowerBinding, position: Int) {
binding = viewBinding
binding.profileUserName.text = name
avatar?.let { binding.profileUserAvatar.loadImage(it) }
banner?.let { binding.profileBannerImage.loadImage(it) }
binding.root.setOnClickListener { clickCallback(id) }
}
override fun getLayout(): Int {
return R.layout.item_follower
}
override fun initializeViewBinding(view: View): ItemFollowerBinding {
return ItemFollowerBinding.bind(view)
}
}

View file

@ -0,0 +1,31 @@
package ani.dantotsu.profile
import android.view.View
import ani.dantotsu.R
import ani.dantotsu.databinding.ItemFollowerGridBinding
import ani.dantotsu.loadImage
import com.xwray.groupie.viewbinding.BindableItem
class GridFollowerItem (
private val id: Int,
private val name: String,
private val avatar: String?,
val clickCallback: (Int) -> Unit
): BindableItem<ItemFollowerGridBinding>() {
private lateinit var binding: ItemFollowerGridBinding
override fun bind(viewBinding: ItemFollowerGridBinding, position: Int) {
binding = viewBinding
binding.profileUserName.text = name
avatar?.let { binding.profileUserAvatar.loadImage(it) }
binding.root.setOnClickListener { clickCallback(id) }
}
override fun getLayout(): Int {
return R.layout.item_follower_grid
}
override fun initializeViewBinding(view: View): ItemFollowerGridBinding {
return ItemFollowerGridBinding.bind(view)
}
}

View file

@ -5,6 +5,7 @@ import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.PopupMenu
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.updateLayoutParams
@ -82,8 +83,10 @@ class ProfileActivity : AppCompatActivity() {
}
})
val userLevel = intent.getStringExtra("username") ?: ""
binding.followButton.visibility = if (user.id == Anilist.userid || Anilist.userid == null) View.GONE else View.VISIBLE
binding.followButton.text = if (user.isFollowing) "Unfollow" else if(user.isFollower) "Follows you" else "Follow"
binding.followButton.visibility =
if (user.id == Anilist.userid || Anilist.userid == null) View.GONE else View.VISIBLE
binding.followButton.text =
if (user.isFollowing) "Unfollow" else if (user.isFollower) "Follows you" else "Follow"
if (user.isFollowing && user.isFollower) binding.followButton.text = "Mutual"
binding.followButton.setOnClickListener {
lifecycleScope.launch(Dispatchers.IO) {
@ -92,8 +95,10 @@ class ProfileActivity : AppCompatActivity() {
withContext(Dispatchers.Main) {
snackString("Success")
user.isFollowing = res.data.toggleFollow.isFollowing
binding.followButton.text = if (user.isFollowing) "Unfollow" else if(user.isFollower) "Follows you" else "Follow"
if (user.isFollowing && user.isFollower) binding.followButton.text = "Mutual"
binding.followButton.text =
if (user.isFollowing) "Unfollow" else if (user.isFollower) "Follows you" else "Follow"
if (user.isFollowing && user.isFollower) binding.followButton.text =
"Mutual"
}
}
}
@ -101,12 +106,35 @@ class ProfileActivity : AppCompatActivity() {
binding.profileProgressBar.visibility = View.GONE
binding.profileTopContainer.visibility = View.VISIBLE
binding.temp.setOnClickListener {
ContextCompat.startActivity(
this@ProfileActivity, Intent(this@ProfileActivity, FollowActivity::class.java)
.putExtra("title", "Following")
.putExtra("userId", user.id), null
)
binding.profileMenuButton.setOnClickListener {
val popup = PopupMenu(this@ProfileActivity, binding.profileMenuButton)
popup.menuInflater.inflate(R.menu.menu_profile, popup.menu)
popup.setOnMenuItemClickListener { item ->
when (item.itemId) {
R.id.action_view_following -> {
ContextCompat.startActivity(
this@ProfileActivity,
Intent(this@ProfileActivity, FollowActivity::class.java)
.putExtra("title", "Following")
.putExtra("userId", user.id),
null
)
true
}
R.id.action_view_followers -> {
ContextCompat.startActivity(
this@ProfileActivity,
Intent(this@ProfileActivity, FollowActivity::class.java)
.putExtra("title", "Followers")
.putExtra("userId", user.id),
null
)
true
}
else -> false
}
}
popup.show()
}
binding.profileUserAvatar.loadImage(user.avatar?.medium)
@ -122,6 +150,10 @@ class ProfileActivity : AppCompatActivity() {
if (!(PrefManager.getVal(PrefName.BannerAnimations) as Boolean)) binding.profileBannerImage.pause()
binding.profileBannerImage.loadImage(user.bannerImage)
binding.profileBannerImage.updateLayoutParams { height += statusBarHeight }
binding.profileBannerGradient.updateLayoutParams { height += statusBarHeight }
binding.profileMenuButton.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin += statusBarHeight
}
binding.profileBannerImage.setOnLongClickListener {
ImageViewDialog.newInstance(
this@ProfileActivity,
@ -132,7 +164,6 @@ class ProfileActivity : AppCompatActivity() {
}
}
}
override fun onResume() {

View file

@ -47,11 +47,11 @@ class ProfileFragment() : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
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 textColorTypedValue = TypedValue()
activity.theme.resolveAttribute(