feat: replies in stories
This commit is contained in:
parent
d355cc561e
commit
001c384d11
8 changed files with 220 additions and 32 deletions
|
@ -11,6 +11,7 @@ import ani.dantotsu.connections.anilist.api.FuzzyDate
|
|||
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
|
||||
|
@ -1612,8 +1613,17 @@ Page(page:$page,perPage:50) {
|
|||
force = true
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun getReplies(
|
||||
activityId: Int,
|
||||
page: Int = 1
|
||||
) : ReplyResponse? {
|
||||
val query = """{Page(page:$page,perPage:50){activityReplies(activityId:$activityId){id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}}}"""
|
||||
return executeQuery(query, force = true)
|
||||
}
|
||||
|
||||
private fun status(page: Int = 1): String {
|
||||
return """Page(page:$page,perPage:50){activities(isFollowing: true,sort:ID_DESC){__typename ... on TextActivity{id userId type replyCount text(asHtml:true)siteUrl isLocked isSubscribed likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}... on ListActivity{id userId type replyCount status progress siteUrl isLocked isSubscribed likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}media{id isAdult title{english romaji native userPreferred}bannerImage coverImage{extraLarge medium large}}likes{id name bannerImage avatar{medium large}}}... on MessageActivity{id type createdAt}}}"""
|
||||
return """Page(page:$page,perPage:50){activities(isFollowing: true,sort:ID_DESC){__typename ... on TextActivity{id userId type replyCount text(asHtml:true)siteUrl isLocked isSubscribed replyCount likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}... on ListActivity{id userId type replyCount status progress siteUrl isLocked isSubscribed replyCount likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}media{id isAdult title{english romaji native userPreferred}bannerImage coverImage{extraLarge medium large}}likes{id name bannerImage avatar{medium large}}}... on MessageActivity{id type createdAt}}}"""
|
||||
}
|
||||
|
||||
suspend fun getUpcomingAnime(id: String): List<Media> {
|
||||
|
|
|
@ -74,6 +74,24 @@ data class Activity(
|
|||
val likes: List<User>?,
|
||||
) : java.io.Serializable
|
||||
|
||||
@Serializable
|
||||
data class ReplyResponse(
|
||||
@SerialName("data")
|
||||
val data: Data
|
||||
) : java.io.Serializable {
|
||||
@Serializable
|
||||
data class Data(
|
||||
@SerialName("Page")
|
||||
val page: ReplyPage
|
||||
) : java.io.Serializable
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class ReplyPage(
|
||||
@SerialName("activityReplies")
|
||||
val activityReplies: List<ActivityReply>
|
||||
) : java.io.Serializable
|
||||
|
||||
@Serializable
|
||||
data class ActivityReply(
|
||||
@SerialName("id")
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package ani.dantotsu.home.status
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import ani.dantotsu.BottomSheetDialogFragment
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.connections.anilist.api.ActivityReply
|
||||
import ani.dantotsu.databinding.BottomSheetRecyclerBinding
|
||||
import ani.dantotsu.profile.activity.ActivityReplyItem
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class RepliesBottomDialog : BottomSheetDialogFragment() {
|
||||
private var _binding: BottomSheetRecyclerBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val adapter: GroupieAdapter = GroupieAdapter()
|
||||
private val replies: MutableList<ActivityReply> = mutableListOf()
|
||||
private var activityId: Int = -1
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = BottomSheetRecyclerBinding.inflate(inflater, container, false)
|
||||
return _binding?.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
binding.repliesRecyclerView.adapter = adapter
|
||||
binding.repliesRecyclerView.layoutManager = LinearLayoutManager(
|
||||
requireContext(),
|
||||
LinearLayoutManager.VERTICAL,
|
||||
false
|
||||
)
|
||||
binding.replyButton.setOnClickListener {
|
||||
val context = requireContext()
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
.putExtra("type", "replyActivity")
|
||||
.putExtra("parentId", activityId),
|
||||
null
|
||||
)
|
||||
}
|
||||
activityId = requireArguments().getInt("activityId")
|
||||
loading(true)
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val response = Anilist.query.getReplies(activityId)
|
||||
withContext(Dispatchers.Main) {
|
||||
loading(false)
|
||||
if (response != null) {
|
||||
replies.clear()
|
||||
replies.addAll(response.data.page.activityReplies)
|
||||
adapter.update(replies.map { ActivityReplyItem(it, requireActivity()) { _, _ -> } })
|
||||
} else {
|
||||
snackString("Failed to load replies")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun loading(load: Boolean) {
|
||||
binding.repliesRefresh.isVisible = load
|
||||
binding.repliesRecyclerView.isVisible = !load
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
_binding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(activityId: Int): RepliesBottomDialog {
|
||||
return RepliesBottomDialog().apply {
|
||||
arguments = Bundle().apply {
|
||||
putInt("activityId", activityId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import androidx.constraintlayout.widget.ConstraintSet
|
|||
import androidx.core.app.ActivityOptionsCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.blurImage
|
||||
|
@ -214,10 +215,6 @@ class Stories @JvmOverloads constructor(
|
|||
timer.setOnTimerCompletedListener {
|
||||
Logger.log("onAnimationEnd: $storyIndex")
|
||||
if (storyIndex - 1 <= activityList.size) {
|
||||
if (false) {
|
||||
Logger.log("userClicked: $storyIndex")
|
||||
userClicked = false
|
||||
} else {
|
||||
Logger.log("userNotClicked: $storyIndex")
|
||||
if (storyIndex < activityList.size) {
|
||||
storyIndex += 1
|
||||
|
@ -227,7 +224,6 @@ class Stories @JvmOverloads constructor(
|
|||
binding.androidStoriesLoadingView.visibility = View.GONE
|
||||
onStoriesCompleted()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// on stories end
|
||||
binding.androidStoriesLoadingView.visibility = View.GONE
|
||||
|
@ -447,6 +443,9 @@ class Stories @JvmOverloads constructor(
|
|||
}
|
||||
val likeColor = ContextCompat.getColor(context, R.color.yt_red)
|
||||
val notLikeColor = ContextCompat.getColor(context, R.color.bg_opp)
|
||||
binding.activityReplies.setOnClickListener {
|
||||
RepliesBottomDialog.newInstance(story.id).show(activity.supportFragmentManager, "replies")
|
||||
}
|
||||
binding.activityLikeCount.text = story.likeCount.toString()
|
||||
binding.activityLike.setColorFilter(if (story.isLiked == true) likeColor else notLikeColor)
|
||||
binding.activityLikeContainer.setOnClickListener {
|
||||
|
|
|
@ -54,8 +54,9 @@ class ActivityItem(
|
|||
val likeColor = ContextCompat.getColor(binding.root.context, R.color.yt_red)
|
||||
val notLikeColor = ContextCompat.getColor(binding.root.context, R.color.bg_opp)
|
||||
binding.activityLike.setColorFilter(if (activity.isLiked == true) likeColor else notLikeColor)
|
||||
binding.commentRepliesContainer.isVisible = activity.replyCount > 0
|
||||
binding.commentRepliesContainer.setOnClickListener {
|
||||
binding.commentTotalReplies.isVisible = activity.replyCount > 0
|
||||
binding.dot.isVisible = activity.replyCount > 0
|
||||
binding.commentTotalReplies.setOnClickListener {
|
||||
when (binding.activityReplies.visibility) {
|
||||
View.GONE -> {
|
||||
val replyItems = activity.replies?.map {
|
||||
|
@ -69,6 +70,16 @@ class ActivityItem(
|
|||
repliesAdapter.addAll(replyItems)
|
||||
binding.activityReplies.visibility = View.VISIBLE
|
||||
binding.commentTotalReplies.setText(R.string.hide_replies)
|
||||
}
|
||||
|
||||
else -> {
|
||||
repliesAdapter.clear()
|
||||
binding.activityReplies.visibility = View.GONE
|
||||
binding.commentTotalReplies.setText(R.string.view_replies)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if (activity.isLocked != true) {
|
||||
binding.commentReply.setOnClickListener {
|
||||
val context = binding.root.context
|
||||
|
@ -84,16 +95,6 @@ class ActivityItem(
|
|||
binding.commentReply.visibility = View.GONE
|
||||
binding.dot.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
repliesAdapter.clear()
|
||||
binding.activityReplies.visibility = View.GONE
|
||||
binding.commentTotalReplies.setText(R.string.view_replies)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
val userList = arrayListOf<User>()
|
||||
activity.likes?.forEach { i ->
|
||||
userList.add(User(i.id, i.name.toString(), i.avatar?.medium, i.bannerImage))
|
||||
|
|
55
app/src/main/res/layout/bottom_sheet_recycler.xml
Normal file
55
app/src/main/res/layout/bottom_sheet_recycler.xml
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="64dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingHorizontal="32dp"
|
||||
android:text="@string/replies"
|
||||
android:textColor="?attr/colorPrimary"
|
||||
android:textSize="22sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/replyButton"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:contentDescription="@string/reply"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:gravity="center_vertical"
|
||||
android:src="@drawable/ic_add"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/title"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/repliesRefresh"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:layout_marginTop="32dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.498"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/repliesRecyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/replyButton" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -176,8 +176,18 @@
|
|||
tools:srcCompat="@tools:sample/backgrounds/scenic" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/activityReplies"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:src="@drawable/ic_round_comment_24"
|
||||
app:layout_constraintBottom_toTopOf="@+id/linearLayout"
|
||||
app:layout_constraintEnd_toEndOf="@+id/linearLayout"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
|
@ -204,7 +214,6 @@
|
|||
tools:ignore="SpUsage"
|
||||
tools:text="@string/slogan" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/activityLikeContainer"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -221,12 +230,13 @@
|
|||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:textSize="15sp"
|
||||
tools:text="12" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/activityLike"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_gravity="center|end"
|
||||
android:layout_marginStart="12dp"
|
||||
android:src="@drawable/ic_round_favorite_24"
|
||||
tools:ignore="ContentDescription" />
|
||||
</LinearLayout>
|
||||
|
|
|
@ -987,4 +987,5 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
|||
<string name="preview">Preview</string>
|
||||
<string name="cannot_be_empty">Text cannot be empty</string>
|
||||
<string name="reply">Reply</string>
|
||||
<string name="replies">Replies</string>
|
||||
</resources>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue