feat: Delete,edit activity

This commit is contained in:
aayush262 2024-05-28 01:04:07 +05:30
parent 6878d12b5c
commit ea75197120
16 changed files with 336 additions and 208 deletions

View file

@ -3,9 +3,9 @@ package ani.dantotsu.connections.anilist
import ani.dantotsu.connections.anilist.Anilist.executeQuery
import ani.dantotsu.connections.anilist.api.FuzzyDate
import ani.dantotsu.connections.anilist.api.Query
import ani.dantotsu.connections.anilist.api.ToggleLike
import ani.dantotsu.currContext
import com.google.gson.Gson
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
class AnilistMutations {
@ -76,38 +76,66 @@ class AnilistMutations {
suspend fun rateReview(reviewId: Int, rating: String): Query.RateReviewResponse? {
val query = "mutation{RateReview(reviewId:$reviewId,rating:$rating){id mediaId mediaType summary body(asHtml:true)rating ratingAmount userRating score private siteUrl createdAt updatedAt user{id name bannerImage avatar{medium large}}}}"
val query =
"mutation{RateReview(reviewId:$reviewId,rating:$rating){id mediaId mediaType summary body(asHtml:true)rating ratingAmount userRating score private siteUrl createdAt updatedAt user{id name bannerImage avatar{medium large}}}}"
return executeQuery<Query.RateReviewResponse>(query)
}
suspend fun postActivity(text:String): String {
suspend fun toggleFollow(id: Int): Query.ToggleFollow? {
return executeQuery<Query.ToggleFollow>(
"""mutation{ToggleFollow(userId:$id){id, isFollowing, isFollower}}"""
)
}
suspend fun toggleLike(id: Int, type: String): ToggleLike? {
return executeQuery<ToggleLike>(
"""mutation Like{ToggleLikeV2(id:$id,type:$type){__typename}}"""
)
}
suspend fun postActivity(text: String, edit : Int? = null): String {
val encodedText = text.stringSanitizer()
val query = "mutation{SaveTextActivity(text:$encodedText){siteUrl}}"
val query = "mutation{SaveTextActivity(${if (edit != null) "id:$edit," else ""} text:$encodedText){siteUrl}}"
val result = executeQuery<JsonObject>(query)
val errors = result?.get("errors")
return errors?.toString()
?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
}
suspend fun postReply(activityId: Int, text: String, edit: Int? = null ): String {
val encodedText = text.stringSanitizer()
val query = "mutation{SaveActivityReply(${if (edit != null) "id:$edit," else ""} activityId:$activityId,text:$encodedText){id}}"
val result = executeQuery<JsonObject>(query)
val errors = result?.get("errors")
return errors?.toString()
?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
}
suspend fun postReview(summary: String, body: String, mediaId: Int, score: Int): String {
val encodedSummary = summary.stringSanitizer()
val encodedBody = body.stringSanitizer()
val query = "mutation{SaveReview(mediaId:$mediaId,summary:$encodedSummary,body:$encodedBody,score:$score){siteUrl}}"
val query =
"mutation{SaveReview(mediaId:$mediaId,summary:$encodedSummary,body:$encodedBody,score:$score){siteUrl}}"
val result = executeQuery<JsonObject>(query)
val errors = result?.get("errors")
return errors?.toString()
?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
}
suspend fun postReply(activityId: Int, text: String): String {
val encodedText = text.stringSanitizer()
val query = "mutation{SaveActivityReply(activityId:$activityId,text:$encodedText){id}}"
suspend fun deleteActivityReply(activityId: Int): Boolean {
val query = "mutation{DeleteActivityReply(id:$activityId){deleted}}"
val result = executeQuery<JsonObject>(query)
val errors = result?.get("errors")
return errors?.toString()
?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
return errors == null
}
suspend fun deleteActivity(activityId: Int): Boolean {
val query = "mutation{DeleteActivity(id:$activityId){deleted}}"
val result = executeQuery<JsonObject>(query)
val errors = result?.get("errors")
return errors == null
}
private fun String.stringSanitizer(): String {
val sb = StringBuilder()
var i = 0

View file

@ -1548,18 +1548,6 @@ Page(page:$page,perPage:50) {
)
}
suspend fun toggleFollow(id: Int): Query.ToggleFollow? {
return executeQuery<Query.ToggleFollow>(
"""mutation{ToggleFollow(userId:$id){id, isFollowing, isFollower}}"""
)
}
suspend fun toggleLike(id: Int, type: String): ToggleLike? {
return executeQuery<ToggleLike>(
"""mutation Like{ToggleLikeV2(id:$id,type:$type){__typename}}"""
)
}
suspend fun getUserProfile(id: Int): Query.UserProfileResponse? {
return executeQuery<Query.UserProfileResponse>(
"""{followerPage:Page{followers(userId:$id){id}pageInfo{total}}followingPage:Page{following(userId:$id){id}pageInfo{total}}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}isFavourite}}staff{nodes{id name{first middle last full native alternative userPreferred}image{large medium}isFavourite}}studios{nodes{id name isFavourite}}}statistics{anime{count meanScore standardDeviation minutesWatched episodesWatched chaptersRead volumesRead}manga{count meanScore standardDeviation minutesWatched episodesWatched chaptersRead volumesRead}}siteUrl}}""",
@ -1618,11 +1606,13 @@ Page(page:$page,perPage:50) {
suspend fun getNotifications(
id: Int,
page: Int = 1,
resetNotification: Boolean = true
resetNotification: Boolean = true,
type: Boolean? = null
): NotificationResponse? {
val type_in = "type_in:[AIRING,MEDIA_MERGE,MEDIA_DELETION,MEDIA_DATA_CHANGE]"
val reset = if (resetNotification) "true" else "false"
val res = executeQuery<NotificationResponse>(
"""{User(id:$id){unreadNotificationCount}Page(page:$page,perPage:$ITEMS_PER_PAGE){pageInfo{currentPage,hasNextPage}notifications(resetNotificationCount:$reset){__typename...on AiringNotification{id,type,animeId,episode,contexts,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}},}...on FollowingNotification{id,userId,type,context,createdAt,user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMessageNotification{id,userId,type,activityId,context,createdAt,message{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMentionNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplySubscribedNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentMentionNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentReplyNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentSubscribedNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentLikeNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadLikeNotification{id,userId,type,threadId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on RelatedMediaAdditionNotification{id,type,context,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDataChangeNotification{id,type,mediaId,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaMergeNotification{id,type,mediaId,deletedMediaTitles,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDeletionNotification{id,type,deletedMediaTitle,context,reason,createdAt,}}}}""",
"""{User(id:$id){unreadNotificationCount}Page(page:$page,perPage:$ITEMS_PER_PAGE){pageInfo{currentPage,hasNextPage}notifications(resetNotificationCount:$reset , ${if (type == true) type_in else ""}){__typename...on AiringNotification{id,type,animeId,episode,contexts,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}},}...on FollowingNotification{id,userId,type,context,createdAt,user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMessageNotification{id,userId,type,activityId,context,createdAt,message{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMentionNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplySubscribedNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentMentionNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentReplyNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentSubscribedNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentLikeNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadLikeNotification{id,userId,type,threadId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on RelatedMediaAdditionNotification{id,type,context,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDataChangeNotification{id,type,mediaId,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaMergeNotification{id,type,mediaId,deletedMediaTitles,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDeletionNotification{id,type,deletedMediaTitle,context,reason,createdAt,}}}}""",
force = true
)
if (res != null && resetNotification) {

View file

@ -74,7 +74,9 @@ class RepliesBottomDialog : BottomSheetDialogFragment() {
replies.map {
ActivityReplyItem(
it,
activityId,
requireActivity(),
adapter,
clickCallback = { int, _ ->
onClick(int)
}
@ -109,7 +111,6 @@ class RepliesBottomDialog : BottomSheetDialogFragment() {
super.onResume()
loading(true)
lifecycleScope.launch(Dispatchers.IO) {
delay(2000)
loadData()
}
}

View file

@ -422,14 +422,14 @@ class Stories @JvmOverloads constructor(
}
val likeColor = ContextCompat.getColor(context, R.color.yt_red)
val notLikeColor = ContextCompat.getColor(context, R.color.bg_opp)
binding.replyCount.text = story.replyCount.toString()
binding.activityReplies.setColorFilter(ContextCompat.getColor(context, R.color.bg_opp))
binding.activityRepliesContainer.setOnClickListener {
RepliesBottomDialog.newInstance(story.id)
.show(activity.supportFragmentManager, "replies")
}
binding.activityLike.setColorFilter(if (story.isLiked == true) likeColor else notLikeColor)
binding.replyCount.text = story.replyCount.toString()
binding.activityLikeCount.text = story.likeCount.toString()
binding.activityReplies.setColorFilter(ContextCompat.getColor(context, R.color.bg_opp))
binding.activityLikeContainer.setOnClickListener {
like()
}
@ -451,7 +451,7 @@ class Stories @JvmOverloads constructor(
val notLikeColor = ContextCompat.getColor(context, R.color.bg_opp)
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
scope.launch {
val res = Anilist.query.toggleLike(story.id, "ACTIVITY")
val res = Anilist.mutation.toggleLike(story.id, "ACTIVITY")
withContext(Dispatchers.Main) {
if (res != null) {
if (story.isLiked == true) {

View file

@ -136,7 +136,7 @@ class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListene
followButton.setOnClickListener {
lifecycleScope.launch(Dispatchers.IO) {
val res = Anilist.query.toggleFollow(user.id)
val res = Anilist.mutation.toggleFollow(user.id)
if (res?.data?.toggleFollow != null) {
withContext(Dispatchers.Main) {
snackString(R.string.success)
@ -325,7 +325,7 @@ class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListene
override fun getItemCount(): Int = 3
override fun createFragment(position: Int): Fragment = when (position) {
0 -> ProfileFragment.newInstance(user)
1 -> ActivityFragment(ActivityType.OTHER_USER, user.id)
1 -> ActivityFragment.newInstance(ActivityType.OTHER_USER, user.id)
2 -> StatsFragment.newInstance(user)
else -> ProfileFragment.newInstance(user)
}

View file

@ -21,13 +21,13 @@ import ani.dantotsu.navBarHeight
import ani.dantotsu.profile.ProfileActivity
import ani.dantotsu.setBaseline
import com.xwray.groupie.GroupieAdapter
import eu.kanade.tachiyomi.util.system.getSerializableCompat
import kotlinx.coroutines.launch
class ActivityFragment(
var type: ActivityType,
val userId: Int? = null,
var activityId: Int? = null,
) : Fragment() {
class ActivityFragment : Fragment() {
private lateinit var type: ActivityType
private var userId: Int? = null
private var activityId: Int? = null
private lateinit var binding: FragmentFeedBinding
private var adapter: GroupieAdapter = GroupieAdapter()
private var page: Int = 1
@ -43,15 +43,13 @@ class ActivityFragment(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val navBar = if (userId != null) {
(activity as ProfileActivity).navBar
} else {
(activity as FeedActivity).navBar
}
binding.listRecyclerView.setBaseline(navBar)
type = arguments?.getSerializableCompat<ActivityType>("type") as ActivityType
userId = arguments?.getInt("userId")
activityId = arguments?.getInt("activityId")
binding.listRecyclerView.adapter = adapter
binding.listRecyclerView.layoutManager = LinearLayoutManager(context)
binding.listProgressBar.isVisible = true
binding.feedRefresh.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = navBarHeight
}
@ -94,7 +92,7 @@ class ActivityFragment(
ActivityType.OTHER_USER -> getActivities(userId = userId)
ActivityType.ONE -> getActivities(activityId = activityId)
}
adapter.addAll(list.map { ActivityItem(it, ::onActivityClick, requireActivity()) })
adapter.addAll(list.map { ActivityItem(it, ::onActivityClick, adapter ,requireActivity()) })
}
private suspend fun getActivities(
@ -142,12 +140,7 @@ class ActivityFragment(
super.onResume()
if (this::binding.isInitialized) {
binding.root.requestLayout()
val navBar = if (userId != null) {
(activity as ProfileActivity).navBar
} else {
(activity as FeedActivity).navBar
}
binding.listRecyclerView.setBaseline(navBar)
}
}
@ -155,5 +148,15 @@ class ActivityFragment(
enum class ActivityType {
GLOBAL, USER, OTHER_USER, ONE
}
fun newInstance(type: ActivityType, userId: Int? = null, activityId: Int? = null): ActivityFragment {
return ActivityFragment().apply {
arguments = Bundle().apply {
putSerializable("type", type)
userId?.let { putInt("userId", it) }
activityId?.let { putInt("activityId", it) }
}
}
}
}
}

View file

@ -12,6 +12,7 @@ import ani.dantotsu.buildMarkwon
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.api.Activity
import ani.dantotsu.databinding.ItemActivityBinding
import ani.dantotsu.home.status.RepliesBottomDialog
import ani.dantotsu.loadImage
import ani.dantotsu.profile.User
import ani.dantotsu.profile.UsersDialogFragment
@ -30,22 +31,16 @@ import kotlinx.coroutines.withContext
class ActivityItem(
private val activity: Activity,
val clickCallback: (Int, type: String) -> Unit,
private val parentAdapter: GroupieAdapter,
private val fragActivity: FragmentActivity
) : BindableItem<ItemActivityBinding>() {
private lateinit var binding: ItemActivityBinding
private lateinit var repliesAdapter: GroupieAdapter
override fun bind(viewBinding: ItemActivityBinding, position: Int) {
binding = viewBinding
val context = binding.root.context
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
setAnimation(binding.root.context, binding.root)
repliesAdapter = GroupieAdapter()
binding.activityReplies.adapter = repliesAdapter
binding.activityReplies.layoutManager = LinearLayoutManager(
binding.root.context,
LinearLayoutManager.VERTICAL,
false
)
binding.activityUserName.text = activity.user?.name ?: activity.messenger?.name
binding.activityUserAvatar.loadImage(
activity.user?.avatar?.medium ?: activity.messenger?.avatar?.medium
@ -54,51 +49,16 @@ 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.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 {
ActivityReplyItem(it,fragActivity) { id, type ->
clickCallback(
id,
type
)
}
} ?: emptyList()
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
ContextCompat.startActivity(
context,
Intent(context, MarkdownCreatorActivity::class.java)
.putExtra("type", "replyActivity")
.putExtra("parentId", activity.id),
null
)
}
} else {
binding.commentReply.visibility = View.GONE
binding.dot.visibility = View.GONE
}
val userList = arrayListOf<User>()
activity.likes?.forEach { i ->
userList.add(User(i.id, i.name.toString(), i.avatar?.medium, i.bannerImage))
}
binding.activityRepliesContainer.setOnClickListener {
RepliesBottomDialog.newInstance(activity.id)
.show(fragActivity.supportFragmentManager, "replies")
}
binding.replyCount.text = activity.replyCount.toString()
binding.activityReplies.setColorFilter(ContextCompat.getColor(binding.root.context, R.color.bg_opp))
binding.activityLikeContainer.setOnLongClickListener {
UsersDialogFragment().apply {
userList(userList)
@ -108,9 +68,9 @@ class ActivityItem(
}
binding.activityLikeCount.text = (activity.likeCount ?: 0).toString()
binding.activityLikeContainer.setOnClickListener {
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
scope.launch {
val res = Anilist.query.toggleLike(activity.id, "ACTIVITY")
val res = Anilist.mutation.toggleLike(activity.id, "ACTIVITY")
withContext(Dispatchers.Main) {
if (res != null) {
@ -129,7 +89,20 @@ class ActivityItem(
}
}
}
val context = binding.root.context
binding.activityDelete.isVisible = activity.userId == Anilist.userid
binding.activityDelete.setOnClickListener {
scope.launch {
val res = Anilist.mutation.deleteActivity(activity.id)
withContext(Dispatchers.Main) {
if (res) {
snackString("Deleted activity")
parentAdapter.remove(this@ActivityItem)
} else {
snackString("Failed to delete activity")
}
}
}
}
when (activity.typename) {
"ListActivity" -> {
val cover = activity.media?.coverImage?.large
@ -156,6 +129,7 @@ class ActivityItem(
binding.activityMediaName.setOnClickListener {
clickCallback(activity.media?.id ?: -1, "MEDIA")
}
binding.activityEdit.isVisible = false
}
"TextActivity" -> {
@ -174,6 +148,17 @@ class ActivityItem(
binding.activityUserName.setOnClickListener {
clickCallback(activity.userId ?: -1, "USER")
}
binding.activityEdit.isVisible = activity.userId == Anilist.userid
binding.activityEdit.setOnClickListener {
ContextCompat.startActivity(
context,
Intent(context, MarkdownCreatorActivity::class.java)
.putExtra("type", "activity")
.putExtra("other", activity.text)
.putExtra("edit", activity.id),
null
)
}
}
"MessageActivity" -> {
@ -192,6 +177,7 @@ class ActivityItem(
binding.activityUserName.setOnClickListener {
clickCallback(activity.messengerId ?: -1, "USER")
}
binding.activityEdit.isVisible = false
}
}
}

View file

@ -1,7 +1,9 @@
package ani.dantotsu.profile.activity
import android.content.Intent
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentActivity
import ani.dantotsu.R
import ani.dantotsu.buildMarkwon
@ -13,6 +15,8 @@ import ani.dantotsu.profile.User
import ani.dantotsu.profile.UsersDialogFragment
import ani.dantotsu.snackString
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
import ani.dantotsu.util.MarkdownCreatorActivity
import com.xwray.groupie.GroupieAdapter
import com.xwray.groupie.viewbinding.BindableItem
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -22,23 +26,27 @@ import kotlinx.coroutines.withContext
class ActivityReplyItem(
private val reply: ActivityReply,
private val parentId : Int,
private val fragActivity: FragmentActivity,
private val parentAdapter: GroupieAdapter,
private val clickCallback: (Int, type: String) -> Unit,
) : BindableItem<ItemActivityReplyBinding>() {
private lateinit var binding: ItemActivityReplyBinding
override fun bind(viewBinding: ItemActivityReplyBinding, position: Int) {
binding = viewBinding
val context = binding.root.context
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
binding.activityUserAvatar.loadImage(reply.user.avatar?.medium)
binding.activityUserName.text = reply.user.name
binding.activityTime.text = ActivityItemBuilder.getDateTime(reply.createdAt)
binding.activityLikeCount.text = reply.likeCount.toString()
val likeColor = ContextCompat.getColor(binding.root.context, R.color.yt_red)
val notLikeColor = ContextCompat.getColor(binding.root.context, R.color.bg_opp)
val likeColor = ContextCompat.getColor(context, R.color.yt_red)
val notLikeColor = ContextCompat.getColor(context, R.color.bg_opp)
binding.activityLike.setColorFilter(if (reply.isLiked) likeColor else notLikeColor)
val markwon = buildMarkwon(binding.root.context)
val markwon = buildMarkwon(context)
markwon.setMarkdown(binding.activityContent, getBasicAniHTML(reply.text))
val userList = arrayListOf<User>()
reply.likes?.forEach { i ->
userList.add(User(i.id, i.name.toString(), i.avatar?.medium, i.bannerImage))
@ -51,9 +59,8 @@ class ActivityReplyItem(
true
}
binding.activityLikeContainer.setOnClickListener {
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
scope.launch {
val res = Anilist.query.toggleLike(reply.id, "ACTIVITY_REPLY")
val res = Anilist.mutation.toggleLike(reply.id, "ACTIVITY_REPLY")
withContext(Dispatchers.Main) {
if (res != null) {
if (reply.isLiked) {
@ -71,6 +78,42 @@ class ActivityReplyItem(
}
}
}
binding.activityReply.setOnClickListener {
ContextCompat.startActivity(
context,
Intent(context, MarkdownCreatorActivity::class.java)
.putExtra("type", "replyActivity")
.putExtra("parentId", parentId)
.putExtra("other", "@${reply.user.name} "),
null
)
}
binding.activityEdit.isVisible = reply.userId == Anilist.userid
binding.activityEdit.setOnClickListener {
ContextCompat.startActivity(
context,
Intent(context, MarkdownCreatorActivity::class.java)
.putExtra("type", "replyActivity")
.putExtra("parentId", parentId)
.putExtra("other", reply.text)
.putExtra("edit", reply.id),
null
)
}
binding.activityDelete.isVisible = reply.userId == Anilist.userid
binding.activityDelete.setOnClickListener {
scope.launch {
val res = Anilist.mutation.deleteActivityReply(reply.id)
withContext(Dispatchers.Main) {
if (res) {
snackString("Deleted")
parentAdapter.remove(this@ActivityReplyItem)
} else {
snackString("Failed to delete")
}
}
}
}
binding.activityAvatarContainer.setOnClickListener {
clickCallback(reply.userId, "USER")

View file

@ -47,6 +47,7 @@ class FeedActivity : AppCompatActivity() {
Pair(R.drawable.ic_globe_24, "Global"),
)
tabs.forEach { (icon, title) -> navBar.addTab(navBar.createTab(icon, title)) }
binding.notificationBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
val getOne = intent.getIntExtra("activityId", -1)
if (getOne != -1) { navBar.visibility = View.GONE }
@ -87,8 +88,8 @@ class FeedActivity : AppCompatActivity() {
override fun createFragment(position: Int): Fragment {
return when (position) {
0 -> ActivityFragment(if (activityId != -1) ActivityType.ONE else ActivityType.USER, activityId = activityId)
else -> ActivityFragment(ActivityType.GLOBAL)
0 -> ActivityFragment.newInstance(if (activityId != -1) ActivityType.ONE else ActivityType.USER, activityId = activityId)
else -> ActivityFragment.newInstance(ActivityType.GLOBAL)
}
}
}

View file

@ -84,11 +84,11 @@ class NotificationActivity : AppCompatActivity() {
override fun getItemCount(): Int = if (id != -1) 1 else 4
override fun createFragment(position: Int): Fragment = when (position) {
0 -> NotificationFragment(if (id != -1) NotificationType.ONE else NotificationType.MEDIA, id)
1 -> NotificationFragment(NotificationType.USER)
2 -> NotificationFragment(NotificationType.SUBSCRIPTION)
3 -> NotificationFragment(NotificationType.COMMENT)
else -> NotificationFragment(NotificationType.MEDIA)
0 -> NotificationFragment.newInstance(if (id != -1) NotificationType.ONE else NotificationType.MEDIA, id)
1 -> NotificationFragment.newInstance(NotificationType.USER)
2 -> NotificationFragment.newInstance(NotificationType.SUBSCRIPTION)
3 -> NotificationFragment.newInstance(NotificationType.COMMENT)
else -> NotificationFragment.newInstance(NotificationType.MEDIA)
}
}
}

View file

@ -7,18 +7,15 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.webkit.internal.ApiFeature.N
import ani.dantotsu.R
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.api.Notification
import ani.dantotsu.databinding.FragmentNotificationsBinding
import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.navBarHeight
import ani.dantotsu.notifications.comment.CommentStore
import ani.dantotsu.notifications.subscription.SubscriptionStore
import ani.dantotsu.profile.ProfileActivity
@ -27,13 +24,13 @@ import ani.dantotsu.setBaseline
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import com.xwray.groupie.GroupieAdapter
import eu.kanade.tachiyomi.util.system.getSerializableCompat
import kotlinx.coroutines.launch
class NotificationFragment(
val type: NotificationType,
val getID: Int = -1
) : Fragment() {
class NotificationFragment : Fragment() {
private lateinit var type : NotificationType
private var getID : Int = -1
private lateinit var binding: FragmentNotificationsBinding
private var adapter: GroupieAdapter = GroupieAdapter()
private var currentPage = 1
@ -49,14 +46,11 @@ class NotificationFragment(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val navbar = (activity as NotificationActivity).navBar
binding.notificationRecyclerView.setBaseline(navbar)
type = arguments?.getSerializableCompat<NotificationType>("type") as NotificationType
getID = arguments?.getInt("id") ?: -1
binding.notificationRecyclerView.adapter = adapter
binding.notificationRecyclerView.layoutManager = LinearLayoutManager(context)
binding.notificationProgressBar.isVisible = true
binding.notificationRefresh.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = navBarHeight
}
binding.emptyTextView.text = getString(R.string.no_notifications)
lifecycleScope.launch {
getList()
@ -92,7 +86,7 @@ class NotificationFragment(
private suspend fun getList() {
val list = when (type) {
NotificationType.ONE -> getNotificationsFiltered(false) { it.id == getID }
NotificationType.MEDIA -> getNotificationsFiltered { it.media != null }
NotificationType.MEDIA -> getNotificationsFiltered(type = true) { it.media != null }
NotificationType.USER -> getNotificationsFiltered { it.media == null }
NotificationType.SUBSCRIPTION -> getSubscriptions()
NotificationType.COMMENT -> getComments()
@ -102,11 +96,12 @@ class NotificationFragment(
private suspend fun getNotificationsFiltered(
reset: Boolean = true,
type: Boolean? = null,
filter: (Notification) -> Boolean
): List<Notification> {
val userId =
Anilist.userid ?: PrefManager.getVal<String>(PrefName.AnilistUserId).toIntOrNull() ?: 0
val res = Anilist.query.getNotifications(userId, currentPage, reset)?.data?.page
val res = Anilist.query.getNotifications(userId, currentPage, reset, type)?.data?.page
currentPage = res?.pageInfo?.currentPage?.plus(1) ?: 1
hasNextPage = res?.pageInfo?.hasNextPage ?: false
return res?.notifications?.filter(filter) ?: listOf()
@ -223,6 +218,15 @@ class NotificationFragment(
enum class NotificationType {
MEDIA, USER, SUBSCRIPTION, COMMENT, ONE
}
fun newInstance(type: NotificationType, id: Int = -1): NotificationFragment {
return NotificationFragment().apply {
arguments = Bundle().apply {
putSerializable("type", type)
putInt("id", id)
}
}
}
}
}

View file

@ -24,7 +24,9 @@ class MarkdownCreatorActivity : AppCompatActivity() {
private lateinit var binding: ActivityMarkdownCreatorBinding
private lateinit var type: String
private var text: String = ""
var ping: String? = null
private var parentId: Int = 0
@OptIn(DelicateCoroutinesApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -38,6 +40,7 @@ class MarkdownCreatorActivity : AppCompatActivity() {
bottomMargin += navBarHeight
}
setContentView(binding.root)
if (intent.hasExtra("type")) {
type = intent.getStringExtra("type")!!
} else {
@ -57,8 +60,11 @@ class MarkdownCreatorActivity : AppCompatActivity() {
}
getString(R.string.create_new_reply)
}
else -> ""
}
ping = intent.getStringExtra("other")
text = ping ?: ""
binding.editText.setText(text)
binding.editText.addTextChangedListener {
if (!binding.markdownCreatorPreviewCheckbox.isChecked) {
@ -86,15 +92,26 @@ class MarkdownCreatorActivity : AppCompatActivity() {
setMessage(R.string.post_to_anilist_warning)
setPosButton(R.string.ok) {
launchIO {
val editId = intent.getIntExtra("edit", -1)
val isEdit = editId != -1
val success = when (type) {
"activity" -> Anilist.mutation.postActivity(text)
"activity" -> if (isEdit) {
Anilist.mutation.postActivity(text, editId)
} else {
Anilist.mutation.postActivity(text)
}
//"review" -> Anilist.mutation.postReview(text)
"replyActivity" -> Anilist.mutation.postReply(parentId, text)
"replyActivity" -> if (isEdit) {
Anilist.mutation.postReply(parentId, text, editId)
} else {
Anilist.mutation.postReply(parentId, text)
}
else -> "Error: Unknown type"
}
toast(success)
finish()
}
onBackPressedDispatcher.onBackPressed()
}
setNeutralButton(R.string.open_rules) {
openLinkInBrowser("https://anilist.co/forum/thread/14")

View file

@ -58,7 +58,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="32dp"
android:visibility="gone" />
</LinearLayout>
</LinearLayout>

View file

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginTop="24dp"
android:background="?attr/colorSurface"
android:orientation="vertical">
@ -40,7 +40,6 @@
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:id="@+id/activityUserName"
android:layout_width="wrap_content"
@ -71,6 +70,33 @@
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/activityRepliesContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/activityReplies"
android:layout_width="18dp"
android:layout_height="18dp"
android:src="@drawable/ic_round_comment_24"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/replyCount"
android:layout_width="18dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="@font/poppins_semi_bold"
android:textAlignment="center"
android:textSize="12sp"
tools:text="12" />
</LinearLayout>
<LinearLayout
android:id="@+id/activityLikeContainer"
android:layout_width="wrap_content"
@ -81,18 +107,19 @@
<ImageView
android:id="@+id/activityLike"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="18dp"
android:layout_height="18dp"
android:src="@drawable/ic_round_favorite_24"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/activityLikeCount"
android:layout_width="wrap_content"
android:layout_width="18dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="@font/poppins_semi_bold"
android:textSize="15sp"
android:textAlignment="center"
android:textSize="12sp"
tools:text="12" />
</LinearLayout>
@ -107,13 +134,51 @@
android:fontFamily="@font/poppins_semi_bold"
android:text="@string/lorem_ipsum"
android:textSize="12sp" />
<LinearLayout
android:id="@+id/linearLayout6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="52dp"
android:orientation="horizontal">
<TextView
android:id="@+id/activityDelete"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_marginStart="12dp"
android:alpha="0.6"
android:fontFamily="@font/poppins_semi_bold"
android:gravity="center"
android:text="@string/delete"
android:textSize="12sp"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintStart_toEndOf="@+id/commentDownVote"
app:layout_constraintTop_toBottomOf="@+id/commentText"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/activityEdit"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_marginStart="12dp"
android:alpha="0.6"
android:fontFamily="@font/poppins_semi_bold"
android:gravity="center"
android:text="@string/edit"
android:textSize="12sp"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintBottom_toBottomOf="@+id/commentReply"
app:layout_constraintStart_toEndOf="@+id/commentReply"
tools:ignore="HardcodedText" />
</LinearLayout>
<FrameLayout
android:id="@+id/activityBannerContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:visibility="gone">
android:visibility="visible">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
@ -201,63 +266,4 @@
</LinearLayout>
</androidx.cardview.widget.CardView>
</FrameLayout>
<LinearLayout
android:id="@+id/commentRepliesContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="6dp"
android:orientation="horizontal">
<View
android:id="@+id/commentRepliesDivider"
android:layout_width="32dp"
android:layout_height="3dp"
android:layout_marginStart="4dp"
android:layout_marginTop="8dp"
android:background="@color/nav_tab" />
<TextView
android:id="@+id/commentTotalReplies"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:alpha="0.8"
android:fontFamily="@font/poppins_semi_bold"
android:text="View replies"
android:textSize="12sp"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/dot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:alpha="0.8"
android:fontFamily="@font/poppins_semi_bold"
android:text="•"
android:textSize="12sp"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/commentReply"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:alpha="0.8"
android:fontFamily="@font/poppins_semi_bold"
android:text="@string/reply"
android:textSize="12sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/activityReplies"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:nestedScrollingEnabled="false"
android:visibility="gone" />
</LinearLayout>

View file

@ -27,7 +27,6 @@
android:id="@+id/activityUserAvatar"
android:layout_width="42dp"
android:layout_height="42dp"
android:layout_gravity="center"
app:srcCompat="@drawable/ic_round_add_circle_24"
tools:ignore="ContentDescription,ImageContrastCheck"
tools:tint="@color/transparent" />
@ -41,7 +40,6 @@
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:id="@+id/activityUserName"
android:layout_width="wrap_content"
@ -73,8 +71,8 @@
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:id="@+id/activityLikeContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:orientation="vertical"
@ -82,18 +80,19 @@
<ImageView
android:id="@+id/activityLike"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="18dp"
android:layout_height="18dp"
android:src="@drawable/ic_round_favorite_24"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/activityLikeCount"
android:layout_width="wrap_content"
android:layout_width="18dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="@font/poppins_semi_bold"
android:textSize="15sp"
android:textAlignment="center"
android:textSize="12sp"
tools:text="12" />
</LinearLayout>
@ -107,4 +106,55 @@
android:fontFamily="@font/poppins_semi_bold"
android:text="@string/lorem_ipsum"
android:textSize="12sp" />
<LinearLayout
android:id="@+id/linearLayout6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="52dp"
android:visibility="gone"
tools:visibility="visible"
android:orientation="horizontal">
<TextView
android:id="@+id/activityReply"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_marginStart="12dp"
android:alpha="0.6"
android:fontFamily="@font/poppins_semi_bold"
android:gravity="center"
android:text="@string/reply"
android:textSize="12sp"
tools:visibility="visible"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/activityDelete"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_marginStart="12dp"
android:alpha="0.6"
android:fontFamily="@font/poppins_semi_bold"
android:gravity="center"
android:text="@string/delete"
android:textSize="12sp"
android:visibility="gone"
tools:visibility="visible"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/activityEdit"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_marginStart="12dp"
android:alpha="0.6"
android:fontFamily="@font/poppins_semi_bold"
android:gravity="center"
android:text="@string/edit"
android:textSize="12sp"
android:visibility="gone"
tools:visibility="visible"
tools:ignore="HardcodedText" />
</LinearLayout>
</LinearLayout>

View file

@ -224,7 +224,7 @@
android:alpha="0.6"
android:fontFamily="@font/poppins_semi_bold"
android:gravity="center"
android:text="Reply"
android:text="@string/reply"
android:textSize="12sp"
app:layout_constraintStart_toEndOf="@+id/commentDownVote"
app:layout_constraintTop_toBottomOf="@+id/commentText"
@ -238,7 +238,7 @@
android:alpha="0.6"
android:fontFamily="@font/poppins_semi_bold"
android:gravity="center"
android:text="Edit"
android:text="@string/edit"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/commentReply"
app:layout_constraintStart_toEndOf="@+id/commentReply"