feat(social): continue from where you left

This commit is contained in:
aayush262 2024-04-27 22:07:09 +05:30
parent 73ef5f4bbc
commit 133354a22d
8 changed files with 70 additions and 38 deletions

View file

@ -140,7 +140,7 @@
android:name=".settings.SettingsAboutActivity" android:name=".settings.SettingsAboutActivity"
android:parentActivityName=".MainActivity" /> android:parentActivityName=".MainActivity" />
<activity <activity
android:name=".home.StatusActivity" android:name=".home.status.StatusActivity"
android:parentActivityName=".MainActivity" /> android:parentActivityName=".MainActivity" />
<activity <activity
android:name=".settings.SettingsAccountActivity" android:name=".settings.SettingsAccountActivity"

View file

@ -1655,26 +1655,33 @@ Page(page:$page,perPage:50) {
}.timeInMillis }.timeInMillis
executeQuery<Social>(query(), force = true)?.data?.let { data -> executeQuery<Social>(query(), force = true)?.data?.let { data ->
val activities = listOf(data.page1.activities, data.page2.activities).flatten() val activities = listOf(data.page1.activities, data.page2.activities).flatten()
.filterNot { it.userId == Anilist.userid }
.sortedByDescending { it.createdAt } .sortedByDescending { it.createdAt }
.filter { it.createdAt < threeDaysAgo } .filter { it.createdAt < threeDaysAgo }
val anilistActivities = mutableListOf<User>()
val groupedActivities = activities.groupBy { it.userId } val groupedActivities = activities.groupBy { it.userId }
groupedActivities.forEach { (_, userActivities) -> groupedActivities.forEach { (_, userActivities) ->
val user = userActivities.firstOrNull()?.user val user = userActivities.firstOrNull()?.user
if (user != null) { if (user != null) {
list.add( val userToAdd = User(
User( user.id,
user.id, user.name ?: "",
user.name ?: "", user.avatar?.medium,
user.avatar?.medium, user.bannerImage,
user.bannerImage, activity = userActivities.toList()
activity = userActivities.toList()
)
) )
if (user.id == Anilist.userid) {
anilistActivities.add(0, userToAdd)
} else {
list.add(userToAdd)
}
} }
} }
list.addAll(0, anilistActivities)
} }
return list return list
} }

View file

@ -30,6 +30,7 @@ import ani.dantotsu.connections.anilist.AnilistHomeViewModel
import ani.dantotsu.connections.anilist.getUserId import ani.dantotsu.connections.anilist.getUserId
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.databinding.FragmentHomeBinding import ani.dantotsu.databinding.FragmentHomeBinding
import ani.dantotsu.home.status.UserStatusAdapter
import ani.dantotsu.loadImage import ani.dantotsu.loadImage
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaAdaptor import ani.dantotsu.media.MediaAdaptor
@ -321,7 +322,7 @@ class HomeFragment : Fragment() {
binding.homeUserStatusRecyclerView.visibility = View.GONE binding.homeUserStatusRecyclerView.visibility = View.GONE
if (it != null) { if (it != null) {
if (it.isNotEmpty()) { if (it.isNotEmpty()) {
binding.homeUserStatusRecyclerView.adapter = UserStatus(it) binding.homeUserStatusRecyclerView.adapter = UserStatusAdapter(it)
binding.homeUserStatusRecyclerView.layoutManager = LinearLayoutManager( binding.homeUserStatusRecyclerView.layoutManager = LinearLayoutManager(
requireContext(), requireContext(),
LinearLayoutManager.HORIZONTAL, LinearLayoutManager.HORIZONTAL,

View file

@ -14,6 +14,7 @@ class CircleView(context: Context, attrs: AttributeSet?) : View(context, attrs)
private var parts: Int = 3 private var parts: Int = 3
private var gapAngle: Float = 9f private var gapAngle: Float = 9f
private val path = Path() private val path = Path()
private var isUser = false
private var booleanList = listOf<Boolean>() private var booleanList = listOf<Boolean>()
private val paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { private val paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
style = Paint.Style.STROKE style = Paint.Style.STROKE
@ -32,13 +33,14 @@ class CircleView(context: Context, attrs: AttributeSet?) : View(context, attrs)
val typedValue = TypedValue() val typedValue = TypedValue()
context.theme.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue, true) context.theme.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue, true)
val primaryColor = typedValue.data val primaryColor = typedValue.data
val typedValue1 = TypedValue()
context.theme.resolveAttribute(com.google.android.material.R.attr.colorOnPrimary, typedValue1, true)
val secondColor = typedValue1.data
fun setColor(int: Int) { fun setColor(int: Int) {
if (int < booleanList.size && booleanList[int]) { paint.color = if (int < booleanList.size && booleanList[int]) {
if (isUser) secondColor else Color.GRAY
paint.color = Color.GRAY
} else { } else {
if (isUser) secondColor else primaryColor
paint.color = primaryColor
} }
canvas.drawPath(path, paint) canvas.drawPath(path, paint)
} }
@ -74,9 +76,10 @@ class CircleView(context: Context, attrs: AttributeSet?) : View(context, attrs)
} }
fun setParts(parts: Int, list : List<Boolean> = mutableListOf()) { fun setParts(parts: Int, list : List<Boolean> = mutableListOf(), isUser: Boolean) {
this.parts = parts this.parts = parts
this.booleanList = list this.booleanList = list
this.isUser = isUser
invalidate() invalidate()
} }
} }

View file

@ -1,6 +1,5 @@
package ani.dantotsu.home package ani.dantotsu.home.status
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.ViewGroup import android.view.ViewGroup
import android.view.animation.Animation import android.view.animation.Animation
@ -8,12 +7,11 @@ import android.view.animation.AnimationUtils
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.connections.anilist.api.Activity
import ani.dantotsu.databinding.ActivityStatusBinding import ani.dantotsu.databinding.ActivityStatusBinding
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
import ani.dantotsu.others.getSerialized
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.home.status.listener.StoriesCallback import ani.dantotsu.home.status.listener.StoriesCallback
import ani.dantotsu.media.Media
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.profile.User import ani.dantotsu.profile.User
import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefManager
@ -44,10 +42,21 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
slideOutLeft = AnimationUtils.loadAnimation(this, R.anim.slide_out_left) slideOutLeft = AnimationUtils.loadAnimation(this, R.anim.slide_out_left)
slideInRight = AnimationUtils.loadAnimation(this, R.anim.slide_in_right) slideInRight = AnimationUtils.loadAnimation(this, R.anim.slide_in_right)
binding.stories.setStoriesList(activity[position].activity, this) val watchedActivity = PrefManager.getCustomVal<Set<Int>>("${activity[position].id}_activities", setOf())
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity )
val startIndex = if ( startFrom > 0) startFrom else 0
binding.stories.setStoriesList(activity[position].activity, this, startIndex + 1)
} }
private fun findFirstNonMatch(watchedActivity: Set<Int>, activity: List<Activity>): Int {
for (activityItem in activity) {
if (activityItem.id !in watchedActivity) {
return activity.indexOf(activityItem)
}
}
return -1
}
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
binding.stories.pause() binding.stories.pause()
@ -68,8 +77,11 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
override fun onStoriesEnd() { override fun onStoriesEnd() {
position += 1 position += 1
if (position < activity.size - 1) { if (position < activity.size - 1) {
val watchedActivity = PrefManager.getCustomVal<Set<Int>>("${activity[position].id}_activities", setOf())
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity )
val startIndex= if ( startFrom > 0) startFrom else 0
binding.stories.startAnimation(slideOutLeft) binding.stories.startAnimation(slideOutLeft)
binding.stories.setStoriesList(activity[position].activity, this) binding.stories.setStoriesList(activity[position].activity, this, startIndex + 1)
binding.stories.startAnimation(slideInRight) binding.stories.startAnimation(slideInRight)
} else { } else {
finish() finish()
@ -79,8 +91,11 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
override fun onStoriesStart() { override fun onStoriesStart() {
position -= 1 position -= 1
if (position >= 0) { if (position >= 0) {
val watchedActivity = PrefManager.getCustomVal<Set<Int>>("${activity[position].id}_activities", setOf())
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity )
val startIndex = if ( startFrom > 0) startFrom else 0
binding.stories.startAnimation(slideOutRight) binding.stories.startAnimation(slideOutRight)
binding.stories.setStoriesList(activity[position].activity, this) binding.stories.setStoriesList(activity[position].activity, this, startIndex + 1)
binding.stories.startAnimation(slideInLeft) binding.stories.startAnimation(slideInLeft)
} else { } else {
finish() finish()

View file

@ -67,7 +67,7 @@ constructor(
private lateinit var time: TextView private lateinit var time: TextView
private lateinit var infoText: TextView private lateinit var infoText: TextView
private lateinit var coverImage: ImageView private lateinit var coverImage: ImageView
private var storyDuration: String = "4" private var storyDuration: String = "6"
private lateinit var animation: ObjectAnimator private lateinit var animation: ObjectAnimator
private var storyIndex: Int = 1 private var storyIndex: Int = 1
private var userClicked: Boolean = false private var userClicked: Boolean = false
@ -110,9 +110,10 @@ constructor(
} }
fun setStoriesList(activityList: List<Activity>, activity: FragmentActivity) { fun setStoriesList(activityList: List<Activity>, activity: FragmentActivity, startIndex : Int = 1) {
this.activityList = activityList this.activityList = activityList
this.activ = activity this.activ = activity
this.storyIndex = startIndex
addLoadingViews(activityList) addLoadingViews(activityList)
} }
@ -234,6 +235,9 @@ constructor(
} }
private fun showStory() { private fun showStory() {
if (storyIndex > 1) {
completeProgressBar(storyIndex - 1)
}
val progressBar = findViewWithTag<ProgressBar>("story${storyIndex}") val progressBar = findViewWithTag<ProgressBar>("story${storyIndex}")
loadingView.visibility = View.VISIBLE loadingView.visibility = View.VISIBLE
animation = ObjectAnimator.ofInt(progressBar, "progress", 0, 100) animation = ObjectAnimator.ofInt(progressBar, "progress", 0, 100)
@ -292,9 +296,11 @@ constructor(
} }
private fun completeProgressBar(storyIndex: Int) { private fun completeProgressBar(storyIndex: Int) {
val lastProgressBar = findViewWithTag<ProgressBar>("story${storyIndex}") for (i in 1 until storyIndex + 1) {
lastProgressBar?.let { val progressBar = findViewWithTag<ProgressBar>("story${i}")
it.progress = 100 progressBar?.let {
it.progress = 100
}
} }
} }

View file

@ -1,10 +1,11 @@
package ani.dantotsu.home package ani.dantotsu.home.status
import android.content.Intent import android.content.Intent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.databinding.ItemUserStatusBinding import ani.dantotsu.databinding.ItemUserStatusBinding
import ani.dantotsu.loadImage import ani.dantotsu.loadImage
import ani.dantotsu.profile.ProfileActivity import ani.dantotsu.profile.ProfileActivity
@ -12,8 +13,8 @@ import ani.dantotsu.profile.User
import ani.dantotsu.setAnimation import ani.dantotsu.setAnimation
import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefManager
class UserStatus(private val user: ArrayList<User>) : class UserStatusAdapter(private val user: ArrayList<User>) :
RecyclerView.Adapter<UserStatus.UsersViewHolder>() { RecyclerView.Adapter<UserStatusAdapter.UsersViewHolder>() {
inner class UsersViewHolder(val binding: ItemUserStatusBinding) : inner class UsersViewHolder(val binding: ItemUserStatusBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
@ -58,12 +59,12 @@ class UserStatus(private val user: ArrayList<User>) :
setAnimation(b.root.context, b.root) setAnimation(b.root.context, b.root)
val user = user[position] val user = user[position]
b.profileUserAvatar.loadImage(user.pfp) b.profileUserAvatar.loadImage(user.pfp)
b.profileUserName.text = user.name b.profileUserName.text = if (Anilist.userid == user.id) "You" else user.name
val watchedActivityIds = val watchedActivity =
PrefManager.getCustomVal<Set<Int>>("${user.id}_activities", setOf()) PrefManager.getCustomVal<Set<Int>>("${user.id}_activities", setOf())
val activityIdToStatusList = user.activity.map { watchedActivityIds.contains(it.id) } val booleanList = user.activity.map { watchedActivity.contains(it.id) }
b.profileUserStatusIndicator.setParts(user.activity.size, activityIdToStatusList) b.profileUserStatusIndicator.setParts(user.activity.size, booleanList, user.id == Anilist.userid)
} }

View file

@ -195,7 +195,6 @@
android:ellipsize="marquee" android:ellipsize="marquee"
android:fontFamily="@font/poppins_semi_bold" android:fontFamily="@font/poppins_semi_bold"
android:gravity="start" android:gravity="start"
android:lineSpacingExtra="-8sp"
android:maxLines="3" android:maxLines="3"
android:paddingHorizontal="12dp" android:paddingHorizontal="12dp"
android:textAlignment="textStart" android:textAlignment="textStart"