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 e98966e6..c77cf105 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt @@ -1505,7 +1505,7 @@ Page(page:$page,perPage:50) { return author } - suspend fun getReviews(mediaId: Int, page: Int = 1, sort: String = "UPDATED_AT_DESC"): Query.ReviewsResponse? { + suspend fun getReviews(mediaId: Int, page: Int = 1, sort: String = "CREATED_AT_DESC"): Query.ReviewsResponse? { return executeQuery( """{Page(page:$page,perPage:10){pageInfo{currentPage,hasNextPage,total}reviews(mediaId:$mediaId,sort:$sort){id,mediaId,mediaType,summary,body(asHtml:true)rating,ratingAmount,userRating,score,private,siteUrl,createdAt,updatedAt,user{id,name,bannerImage avatar{medium,large}}}}}""", force = true diff --git a/app/src/main/java/ani/dantotsu/connections/github/Contributors.kt b/app/src/main/java/ani/dantotsu/connections/github/Contributors.kt index b8863310..337e4c49 100644 --- a/app/src/main/java/ani/dantotsu/connections/github/Contributors.kt +++ b/app/src/main/java/ani/dantotsu/connections/github/Contributors.kt @@ -84,15 +84,15 @@ class Contributors { "https://anilist.co/user/6244220" ), Developer( - "Zaidsenior", + "Ziadsenior", "https://s4.anilist.co/file/anilistcdn/user/avatar/large/b6049773-8cjYeUOFUguv.jpg", - "Comment Moderator", + "Comment Moderator and Arabic Translator", "https://anilist.co/user/6049773" ), Developer( "hastsu", "https://cdn.discordapp.com/avatars/602422545077108749/20b4a6efa4314550e4ed51cdbe4fef3d.webp?size=160", - "Comment Moderator", + "Comment Moderator and Arabic Translator", "https://anilist.co/user/6183359" ), ) diff --git a/app/src/main/java/ani/dantotsu/home/status/CircleView.kt b/app/src/main/java/ani/dantotsu/home/status/CircleView.kt index 2a7c02d9..63986d83 100644 --- a/app/src/main/java/ani/dantotsu/home/status/CircleView.kt +++ b/app/src/main/java/ani/dantotsu/home/status/CircleView.kt @@ -12,13 +12,14 @@ import ani.dantotsu.getThemeColor class CircleView(context: Context, attrs: AttributeSet?) : View(context, attrs) { private var parts: Int = 3 - private var gapAngle: Float = 9f + private var gapAngle: Float = 12f private val path = Path() private var isUser = false private var booleanList = listOf() private val paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.STROKE strokeWidth = 6f + strokeCap = Paint.Cap.ROUND } @SuppressLint("DrawAllocation") diff --git a/app/src/main/java/ani/dantotsu/home/status/Stories.kt b/app/src/main/java/ani/dantotsu/home/status/Stories.kt index f0d3cf2b..7f2c60ec 100644 --- a/app/src/main/java/ani/dantotsu/home/status/Stories.kt +++ b/app/src/main/java/ani/dantotsu/home/status/Stories.kt @@ -42,6 +42,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.util.Calendar import java.util.Locale +import kotlin.math.abs class Stories @JvmOverloads constructor( @@ -264,29 +265,44 @@ class Stories @JvmOverloads constructor( private var startClickTime = 0L + private var startX = 0f + private var startY = 0f + private var isLongPress = false + private val swipeThreshold = 100 override fun onTouch(view: View?, event: MotionEvent?): Boolean { val maxClickDuration = 200 when (event?.action) { MotionEvent.ACTION_DOWN -> { + startX = event.x + startY = event.y startClickTime = Calendar.getInstance().timeInMillis pause() + isLongPress = false + } + + MotionEvent.ACTION_MOVE -> { + val deltaX = event.x - startX + val deltaY = event.y - startY + if (!isLongPress && (abs(deltaX) > swipeThreshold || abs(deltaY) > swipeThreshold)) { + isLongPress = true + } } MotionEvent.ACTION_UP -> { val clickDuration = Calendar.getInstance().timeInMillis - startClickTime - if (clickDuration < maxClickDuration) { - //click occurred - view?.let { - if (it.id == R.id.leftTouchPanel) { - leftPanelTouch() - } else if (it.id == R.id.rightTouchPanel) { - rightPanelTouch() - } + if (clickDuration < maxClickDuration && !isLongPress) { + when (view?.id) { + R.id.leftTouchPanel -> leftPanelTouch() + R.id.rightTouchPanel -> rightPanelTouch() } } else { - //hold click occurred resume() } + val deltaX = event.x - startX + if (abs(deltaX) > swipeThreshold) { + if (deltaX > 0) onStoriesPrevious() + else onStoriesCompleted() + } } } return true @@ -359,16 +375,14 @@ class Stories @JvmOverloads constructor( ) } fun visible(isList: Boolean) { - val visible = if (isList) View.VISIBLE else View.GONE - val gone = if (isList) View.GONE else View.VISIBLE - binding.textActivity.visibility = gone - binding.textActivityContainer.visibility = gone - binding.infoText.visibility = visible - binding.coverImage.visibility = visible + binding.textActivity.isVisible = !isList + binding.textActivityContainer.isVisible = !isList + binding.infoText.isVisible = isList + binding.coverImage.isVisible = isList binding.infoText.visibility = if (isList) View.VISIBLE else View.INVISIBLE binding.infoText.text = "" - binding.contentImageViewKen.visibility = visible - binding.contentImageView.visibility = visible + binding.contentImageViewKen.isVisible = isList + binding.contentImageView.isVisible = isList } when (story.typename) { @@ -383,16 +397,15 @@ class Stories @JvmOverloads constructor( } } } ${story.progress ?: story.media?.title?.userPreferred} " + - if ( - story.status?.contains("completed") == false && - !story.status.contains("plans") && - !story.status.contains("repeating") - ) - { - "of ${story.media?.title?.userPreferred}" - } else { - "" - } + if ( + story.status?.contains("completed") == false && + !story.status.contains("plans") && + !story.status.contains("repeating") + ) { + "of ${story.media?.title?.userPreferred}" + } else { + "" + } binding.infoText.text = text val bannerAnimations: Boolean = PrefManager.getVal(PrefName.BannerAnimations) blurImage( @@ -404,18 +417,16 @@ class Stories @JvmOverloads constructor( ContextCompat.startActivity( context, Intent(context, MediaDetailsActivity::class.java).putExtra( - "mediaId", - story.media?.id - ), + "mediaId", + story.media?.id + ), ActivityOptionsCompat.makeSceneTransitionAnimation( activity, binding.coverImage, ViewCompat.getTransitionName(binding.coverImage)!! ).toBundle() ) - } - } "TextActivity" -> { @@ -445,11 +456,13 @@ class Stories @JvmOverloads constructor( val likeColor = ContextCompat.getColor(context, R.color.yt_red) val notLikeColor = ContextCompat.getColor(context, R.color.bg_opp) binding.activityRepliesContainer.setOnClickListener { - RepliesBottomDialog.newInstance(story.id).show(activity.supportFragmentManager, "replies") + 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.activityLike.setColorFilter(if (story.isLiked == true) likeColor else notLikeColor) + binding.activityReplies.setColorFilter(ContextCompat.getColor(context, R.color.bg_opp)) binding.activityLikeContainer.setOnClickListener { like() } diff --git a/app/src/main/java/ani/dantotsu/media/ReviewActivity.kt b/app/src/main/java/ani/dantotsu/media/ReviewActivity.kt index b4631db4..8f3c3b12 100644 --- a/app/src/main/java/ani/dantotsu/media/ReviewActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/ReviewActivity.kt @@ -77,7 +77,7 @@ class ReviewActivity : AppCompatActivity() { binding.listBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() } lifecycleScope.launch(Dispatchers.IO) { - val response = Anilist.query.getReviews(mediaId) + val response = Anilist.query.getReviews(mediaId)?.data?.page withContext(Dispatchers.Main) { binding.listProgressBar.visibility = View.GONE binding.listRecyclerView.setOnTouchListener { _, event -> @@ -94,9 +94,9 @@ class ReviewActivity : AppCompatActivity() { } false } - currentPage = response?.data?.page?.pageInfo?.currentPage ?: 1 - hasNextPage = response?.data?.page?.pageInfo?.hasNextPage ?: false - response?.data?.page?.reviews?.let { + currentPage = response?.pageInfo?.currentPage ?: 1 + hasNextPage = response?.pageInfo?.hasNextPage ?: false + response?.reviews?.let { reviews.addAll(it) fillList() } @@ -122,29 +122,10 @@ class ReviewActivity : AppCompatActivity() { private fun fillList() { adapter.clear() reviews.forEach { - val username = it.user?.name ?: "Unknown" - val name = SpannableString(username + " - " + it.score) - //change the size of the score - name.setSpan( - android.text.style.RelativeSizeSpan(0.9f), - 0, - name.length, - android.text.Spannable.SPAN_EXCLUSIVE_EXCLUSIVE - ) - //give the text an underline - name.setSpan( - android.text.style.UnderlineSpan(), - username.length + 3, - name.length, - android.text.Spannable.SPAN_EXCLUSIVE_EXCLUSIVE - ) adapter.add( - FollowerItem( - it.id, - name, - it.user?.avatar?.medium, - it.user?.bannerImage, - it.summary, + ReviewAdapter( + it, + this, this::onUserClick ) ) diff --git a/app/src/main/java/ani/dantotsu/media/ReviewAdapter.kt b/app/src/main/java/ani/dantotsu/media/ReviewAdapter.kt new file mode 100644 index 00000000..1f8034d3 --- /dev/null +++ b/app/src/main/java/ani/dantotsu/media/ReviewAdapter.kt @@ -0,0 +1,129 @@ +package ani.dantotsu.media + + +import android.content.Context +import android.text.SpannableString +import android.view.View +import androidx.lifecycle.lifecycleScope +import ani.dantotsu.R +import ani.dantotsu.blurImage +import ani.dantotsu.connections.anilist.Anilist +import ani.dantotsu.connections.anilist.api.Query +import ani.dantotsu.databinding.ItemFollowerBinding +import ani.dantotsu.databinding.ItemReviewsBinding +import ani.dantotsu.getThemeColor +import ani.dantotsu.loadImage +import ani.dantotsu.profile.activity.ActivityItemBuilder +import ani.dantotsu.toast +import com.xwray.groupie.viewbinding.BindableItem +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +class ReviewAdapter( + private var review: Query.Review, + val context: ReviewActivity, + val clickCallback: (Int) -> Unit + +) : BindableItem() { + private lateinit var binding: ItemReviewsBinding + + override fun bind(viewBinding: ItemReviewsBinding, position: Int) { + binding = viewBinding + binding.reviewUserName.text = review.user?.name + binding.reviewUserAvatar.loadImage(review.user?.avatar?.medium) + binding.reviewText.text = review.summary + binding.reviewPostTime.text = ActivityItemBuilder.getDateTime(review.createdAt) + binding.reviewTag.text = "[${review.score}]" + binding.root.setOnClickListener { clickCallback(review.id) } + userVote(review.userRating) + enableVote() + binding.reviewTotalVotes.text = review.rating.toString() + } + + override fun getLayout(): Int { + return R.layout.item_reviews + } + + override fun initializeViewBinding(view: View): ItemReviewsBinding { + return ItemReviewsBinding.bind(view) + } + private fun userVote(type: String) { + when (type) { + "NO_VOTE" -> { + binding.reviewUpVote.setImageResource(R.drawable.ic_round_upvote_inactive_24) + binding.reviewDownVote.setImageResource(R.drawable.ic_round_upvote_inactive_24) + binding.reviewUpVote.alpha = 0.6f + binding.reviewDownVote.alpha = 0.6f + } + + "UP_VOTE" -> { + binding.reviewUpVote.setImageResource(R.drawable.ic_round_upvote_active_24) + binding.reviewDownVote.setImageResource(R.drawable.ic_round_upvote_inactive_24) + binding.reviewUpVote.alpha = 1f + binding.reviewDownVote.alpha = 0.6f + } + + "DOWN_VOTE" -> { + binding.reviewUpVote.setImageResource(R.drawable.ic_round_upvote_inactive_24) + binding.reviewDownVote.setImageResource(R.drawable.ic_round_upvote_active_24) + binding.reviewDownVote.alpha = 1f + binding.reviewUpVote.alpha = 0.6f + } + } + } + + private fun rateReview(rating: String) { + disableVote() + context.lifecycleScope.launch { + val result = Anilist.mutation.rateReview(review.id, rating) + if (result != null) { + withContext(Dispatchers.Main) { + val res = result.data.rateReview + review.rating = res.rating + review.ratingAmount = res.ratingAmount + review.userRating = res.userRating + userVote(review.userRating) + binding.reviewTotalVotes.text = review.rating.toString() + userVote(review.userRating) + enableVote() + } + } else { + withContext(Dispatchers.Main) { + toast( + context.getString(R.string.error_message, "response is null") + ) + enableVote() + } + } + } + } + + private fun disableVote() { + binding.reviewUpVote.setOnClickListener(null) + binding.reviewDownVote.setOnClickListener(null) + binding.reviewUpVote.isEnabled = false + binding.reviewDownVote.isEnabled = false + } + + private fun enableVote() { + binding.reviewUpVote.setOnClickListener { + if (review.userRating == "UP_VOTE") { + rateReview("NO_VOTE") + } else { + rateReview("UP_VOTE") + } + disableVote() + } + binding.reviewDownVote.setOnClickListener { + if (review.userRating == "DOWN_VOTE") { + rateReview("NO_VOTE") + } else { + rateReview("DOWN_VOTE") + } + disableVote() + } + binding.reviewUpVote.isEnabled = true + binding.reviewDownVote.isEnabled = true + } +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/SubscriptionItem.kt b/app/src/main/java/ani/dantotsu/settings/SubscriptionItem.kt index 6c6cf941..bb8c0396 100644 --- a/app/src/main/java/ani/dantotsu/settings/SubscriptionItem.kt +++ b/app/src/main/java/ani/dantotsu/settings/SubscriptionItem.kt @@ -5,6 +5,7 @@ import android.view.View import androidx.core.content.ContextCompat import ani.dantotsu.R import ani.dantotsu.databinding.ItemSubscriptionBinding +import ani.dantotsu.loadImage import ani.dantotsu.media.MediaDetailsActivity import ani.dantotsu.notifications.subscription.SubscriptionHelper import com.xwray.groupie.GroupieAdapter @@ -25,7 +26,7 @@ class SubscriptionItem( else SubscriptionHelper.getMangaParser(media.id).name val mediaName = media.name - val showName = "$mediaName - $parserName" + val showName = "$mediaName ($parserName)" binding.subscriptionName.text = showName binding.root.setOnClickListener { ContextCompat.startActivity( @@ -36,6 +37,7 @@ class SubscriptionItem( null ) } + binding.subscriptionCover.loadImage(media.image) binding.deleteSubscription.setOnClickListener { SubscriptionHelper.deleteSubscription(id, true) adapter.remove(this) diff --git a/app/src/main/res/layout/activity_review_view.xml b/app/src/main/res/layout/activity_review_view.xml index 6732d8f9..8ae33dc4 100644 --- a/app/src/main/res/layout/activity_review_view.xml +++ b/app/src/main/res/layout/activity_review_view.xml @@ -2,6 +2,7 @@ diff --git a/app/src/main/res/layout/item_developer.xml b/app/src/main/res/layout/item_developer.xml index c4c87d7b..d695edec 100644 --- a/app/src/main/res/layout/item_developer.xml +++ b/app/src/main/res/layout/item_developer.xml @@ -28,7 +28,7 @@ + android:text="@string/lorem_ipsum" + android:maxLines="2" + android:fontFamily="@font/poppins_semi_bold" /> diff --git a/app/src/main/res/layout/item_follower.xml b/app/src/main/res/layout/item_follower.xml index 675e5451..6c236619 100644 --- a/app/src/main/res/layout/item_follower.xml +++ b/app/src/main/res/layout/item_follower.xml @@ -74,11 +74,12 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="start|center_vertical" - android:ellipsize="end" android:fontFamily="@font/poppins_semi_bold" + android:ellipsize="end" + android:alpha="0.75" android:maxLines="2" android:text="@string/lorem_ipsum" - android:textSize="14sp" + android:textSize="12sp" android:visibility="gone" /> diff --git a/app/src/main/res/layout/item_reviews.xml b/app/src/main/res/layout/item_reviews.xml new file mode 100644 index 00000000..0d2d5832 --- /dev/null +++ b/app/src/main/res/layout/item_reviews.xml @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_search_history.xml b/app/src/main/res/layout/item_search_history.xml index 82155f90..237ecbef 100644 --- a/app/src/main/res/layout/item_search_history.xml +++ b/app/src/main/res/layout/item_search_history.xml @@ -30,7 +30,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:src="@drawable/ic_circle_cancel" + android:src="@drawable/ic_round_close_24" android:textSize="14sp" app:tint="?attr/colorOnBackground" tools:ignore="ContentDescription" /> diff --git a/app/src/main/res/layout/item_subscription.xml b/app/src/main/res/layout/item_subscription.xml index be8dd588..d6609cd6 100644 --- a/app/src/main/res/layout/item_subscription.xml +++ b/app/src/main/res/layout/item_subscription.xml @@ -8,14 +8,35 @@ android:layout_marginHorizontal="8dp" android:orientation="horizontal" tools:ignore="UseCompoundDrawables"> + + + + @@ -26,7 +47,7 @@ android:layout_gravity="center_vertical" android:layout_marginEnd="8dp" android:contentDescription="@string/delete" - android:src="@drawable/ic_circle_cancel" + android:src="@drawable/ic_round_close_24" app:tint="?attr/colorOnBackground" /> \ No newline at end of file