diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ef57b17aa2..930cdf195e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -198,6 +198,12 @@
+
+
diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistMutations.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistMutations.kt
index c2b8eb2418..e1e3b1d573 100644
--- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistMutations.kt
+++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistMutations.kt
@@ -2,6 +2,7 @@ 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 kotlinx.serialization.json.JsonObject
class AnilistMutations {
@@ -69,4 +70,10 @@ class AnilistMutations {
val variables = """{"id":"$listId"}"""
executeQuery(query, variables)
}
+
+
+ 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}}}}"
+ return executeQuery(query)
+ }
}
\ No newline at end of file
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 3c4a898ab1..bd779e00e3 100644
--- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt
+++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt
@@ -1504,6 +1504,13 @@ Page(page:$page,perPage:50) {
return author
}
+ suspend fun getReviews(mediaId: Int, page: Int = 1, sort: String = "UPDATED_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
+ )
+ }
+
suspend fun toggleFollow(id: Int): Query.ToggleFollow? {
return executeQuery(
"""mutation{ToggleFollow(userId:$id){id, isFollowing, isFollower}}"""
diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/api/Data.kt b/app/src/main/java/ani/dantotsu/connections/anilist/api/Data.kt
index bb6ee79209..e6635b9a77 100644
--- a/app/src/main/java/ani/dantotsu/connections/anilist/api/Data.kt
+++ b/app/src/main/java/ani/dantotsu/connections/anilist/api/Data.kt
@@ -299,6 +299,70 @@ class Query {
val following: List?
) : java.io.Serializable
+ @Serializable
+ data class ReviewsResponse(
+ @SerialName("data")
+ val data: Data
+ ) : java.io.Serializable {
+ @Serializable
+ data class Data(
+ @SerialName("Page")
+ val page: ReviewPage?
+ ) : java.io.Serializable
+ }
+
+ @Serializable
+ data class ReviewPage(
+ @SerialName("pageInfo")
+ val pageInfo: PageInfo,
+ @SerialName("reviews")
+ val reviews: List?
+ ) : java.io.Serializable
+
+ @Serializable
+ data class RateReviewResponse(
+ @SerialName("data")
+ val data: Data
+ ) : java.io.Serializable {
+ @Serializable
+ data class Data(
+ @SerialName("RateReview")
+ val rateReview: Review
+ ) : java.io.Serializable
+ }
+
+ @Serializable
+ data class Review(
+ @SerialName("id")
+ val id: Int,
+ @SerialName("mediaId")
+ val mediaId: Int,
+ @SerialName("mediaType")
+ val mediaType: String,
+ @SerialName("summary")
+ val summary: String,
+ @SerialName("body")
+ val body: String,
+ @SerialName("rating")
+ var rating: Int,
+ @SerialName("ratingAmount")
+ var ratingAmount: Int,
+ @SerialName("userRating")
+ var userRating: String,
+ @SerialName("score")
+ val score: Int,
+ @SerialName("private")
+ val private: Boolean,
+ @SerialName("siteUrl")
+ val siteUrl: String,
+ @SerialName("createdAt")
+ val createdAt: Int,
+ @SerialName("updatedAt")
+ val updatedAt: Int?,
+ @SerialName("user")
+ val user: ani.dantotsu.connections.anilist.api.User?,
+ ) : java.io.Serializable
+
@Serializable
data class UserProfile(
@SerialName("id")
diff --git a/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt b/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt
index 1ad28a6e62..0c0e1fdd71 100644
--- a/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt
+++ b/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt
@@ -226,7 +226,7 @@ class AnimeDownloaderService : Service() {
task.episode
) ?: throw Exception("Failed to create output directory")
- outputDir.findFile("${task.getTaskName()}.mp4")?.delete()
+ outputDir.findFile("${task.getTaskName()}.mkv")?.delete()
val outputFile = outputDir.createFile("video/x-matroska", "${task.getTaskName()}.mkv")
?: throw Exception("Failed to create output file")
@@ -245,7 +245,7 @@ class AnimeDownloaderService : Service() {
.append(defaultHeaders["User-Agent"]).append("\"\'\r\n\'")
}
val probeRequest =
- "-headers $headersStringBuilder -i ${task.video.file.url} -show_entries format=duration -v quiet -of csv=\"p=0\""
+ "-headers $headersStringBuilder -i \"${task.video.file.url}\" -show_entries format=duration -v quiet -of csv=\"p=0\""
ffExtension.executeFFProbe(
probeRequest
) {
@@ -256,7 +256,7 @@ class AnimeDownloaderService : Service() {
val headers = headersStringBuilder.toString()
var request = "-headers $headers "
- request += "-i ${task.video.file.url} -c copy -map 0:v -map 0:a -map 0:s?" +
+ request += "-i \"${task.video.file.url}\" -c copy -map 0:v -map 0:a -map 0:s?" +
" -f matroska -timeout 600 -reconnect 1" +
" -reconnect_streamed 1 -allowed_extensions ALL " +
"-tls_verify 0 $path -v trace"
diff --git a/app/src/main/java/ani/dantotsu/media/MediaInfoFragment.kt b/app/src/main/java/ani/dantotsu/media/MediaInfoFragment.kt
index 3863db98af..671c96cebb 100644
--- a/app/src/main/java/ani/dantotsu/media/MediaInfoFragment.kt
+++ b/app/src/main/java/ani/dantotsu/media/MediaInfoFragment.kt
@@ -517,26 +517,24 @@ class MediaInfoFragment : Fragment() {
}
parent.addView(root)
}
+ }
- ItemTitleSearchBinding.inflate(
- LayoutInflater.from(context),
- parent,
- false
- ).apply {
-
- titleSearchImage.loadImage(media.banner ?: media.cover)
- titleSearchText.text =
- getString(R.string.search_title, media.mainName())
- titleSearchCard.setSafeOnClickListener {
- val query = Intent(requireContext(), SearchActivity::class.java)
- .putExtra("type", "ANIME")
- .putExtra("query", media.mainName())
- .putExtra("search", true)
- ContextCompat.startActivity(requireContext(), query, null)
- }
+ ItemTitleSearchBinding.inflate(
+ LayoutInflater.from(context),
+ parent,
+ false
+ ).apply {
- parent.addView(root)
+ titleSearchImage.loadImage(media.banner ?: media.cover)
+ titleSearchText.text =
+ getString(R.string.reviews)
+ titleSearchCard.setSafeOnClickListener {
+ val query = Intent(requireContext(), ReviewActivity::class.java)
+ .putExtra("mediaId", media.id)
+ ContextCompat.startActivity(requireContext(), query, null)
}
+
+ parent.addView(root)
}
ItemTitleRecyclerBinding.inflate(
diff --git a/app/src/main/java/ani/dantotsu/media/ReviewActivity.kt b/app/src/main/java/ani/dantotsu/media/ReviewActivity.kt
new file mode 100644
index 0000000000..453617787d
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/media/ReviewActivity.kt
@@ -0,0 +1,149 @@
+package ani.dantotsu.media
+
+import android.annotation.SuppressLint
+import android.content.Intent
+import android.os.Bundle
+import android.text.SpannableString
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.isVisible
+import androidx.core.view.updateLayoutParams
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.LinearLayoutManager
+import ani.dantotsu.R
+import ani.dantotsu.connections.anilist.Anilist
+import ani.dantotsu.connections.anilist.api.Query
+import ani.dantotsu.databinding.ActivityFollowBinding
+import ani.dantotsu.initActivity
+import ani.dantotsu.navBarHeight
+import ani.dantotsu.profile.FollowerItem
+import ani.dantotsu.statusBarHeight
+import ani.dantotsu.themes.ThemeManager
+import com.xwray.groupie.GroupieAdapter
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class ReviewActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityFollowBinding
+ val adapter = GroupieAdapter()
+ private val reviews = mutableListOf()
+ var mediaId = 0
+ private var currentPage: Int = 1
+ private var hasNextPage: Boolean = true
+
+ @SuppressLint("ClickableViewAccessibility")
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ ThemeManager(this).applyTheme()
+ initActivity(this)
+ binding = ActivityFollowBinding.inflate(layoutInflater)
+ binding.listToolbar.updateLayoutParams {
+ topMargin = statusBarHeight
+ }
+ binding.listFrameLayout.updateLayoutParams {
+ bottomMargin = navBarHeight
+ }
+ setContentView(binding.root)
+ mediaId = intent.getIntExtra("mediaId", -1)
+ if (mediaId == -1) {
+ finish()
+ return
+ }
+ binding.followerGrid.visibility = View.GONE
+ binding.followerList.visibility = View.GONE
+ binding.followFilterButton.visibility = View.GONE
+ binding.listTitle.text = getString(R.string.reviews)
+ binding.listRecyclerView.adapter = adapter
+ binding.listRecyclerView.layoutManager = LinearLayoutManager(
+ this,
+ LinearLayoutManager.VERTICAL,
+ false
+ )
+ binding.listProgressBar.visibility = View.VISIBLE
+ binding.listBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
+
+ lifecycleScope.launch(Dispatchers.IO) {
+ val response = Anilist.query.getReviews(mediaId)
+ withContext(Dispatchers.Main) {
+ binding.listProgressBar.visibility = View.GONE
+ binding.listRecyclerView.setOnTouchListener { _, event ->
+ if (event?.action == MotionEvent.ACTION_UP) {
+ if (hasNextPage && !binding.listRecyclerView.canScrollVertically(1) && !binding.followRefresh.isVisible
+ && binding.listRecyclerView.adapter!!.itemCount != 0 &&
+ (binding.listRecyclerView.layoutManager as LinearLayoutManager).findLastVisibleItemPosition() == (binding.listRecyclerView.adapter!!.itemCount - 1)
+ ) {
+ binding.followRefresh.visibility = ViewGroup.VISIBLE
+ loadPage(++currentPage) {
+ binding.followRefresh.visibility = ViewGroup.GONE
+ }
+ }
+ }
+ false
+ }
+ currentPage = response?.data?.page?.pageInfo?.currentPage ?: 1
+ hasNextPage = response?.data?.page?.pageInfo?.hasNextPage ?: false
+ response?.data?.page?.reviews?.let {
+ reviews.addAll(it)
+ fillList()
+ }
+ }
+ }
+ }
+
+ private fun loadPage(page: Int, callback: () -> Unit) {
+ lifecycleScope.launch(Dispatchers.IO) {
+ val response = Anilist.query.getReviews(mediaId, page)
+ currentPage = response?.data?.page?.pageInfo?.currentPage ?: 1
+ hasNextPage = response?.data?.page?.pageInfo?.hasNextPage ?: false
+ withContext(Dispatchers.Main) {
+ response?.data?.page?.reviews?.let {
+ reviews.addAll(it)
+ fillList()
+ }
+ callback()
+ }
+ }
+ }
+
+ 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,
+ this::onUserClick
+ )
+ )
+ }
+ }
+
+ private fun onUserClick(userId: Int) {
+ val review = reviews.find { it.id == userId }
+ if (review != null) {
+ startActivity(Intent(this, ReviewViewActivity::class.java).putExtra("review", review))
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/media/ReviewViewActivity.kt b/app/src/main/java/ani/dantotsu/media/ReviewViewActivity.kt
new file mode 100644
index 0000000000..7d33481b2e
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/media/ReviewViewActivity.kt
@@ -0,0 +1,178 @@
+package ani.dantotsu.media
+
+import android.os.Bundle
+import android.view.View
+import android.view.ViewGroup
+import android.webkit.WebResourceRequest
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import androidx.core.view.updateLayoutParams
+import androidx.lifecycle.lifecycleScope
+import ani.dantotsu.R
+import ani.dantotsu.connections.anilist.Anilist
+import ani.dantotsu.connections.anilist.api.Query
+import ani.dantotsu.databinding.ActivityReviewViewBinding
+import ani.dantotsu.getThemeColor
+import ani.dantotsu.initActivity
+import ani.dantotsu.loadImage
+import ani.dantotsu.navBarHeight
+import ani.dantotsu.profile.activity.ActivityItemBuilder
+import ani.dantotsu.statusBarHeight
+import ani.dantotsu.themes.ThemeManager
+import ani.dantotsu.toast
+import ani.dantotsu.util.AniMarkdown
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class ReviewViewActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityReviewViewBinding
+ private lateinit var review: Query.Review
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ ThemeManager(this).applyTheme()
+ initActivity(this)
+ binding = ActivityReviewViewBinding.inflate(layoutInflater)
+ binding.userContainer.updateLayoutParams {
+ topMargin = statusBarHeight
+ }
+ binding.reviewContent.updateLayoutParams {
+ bottomMargin += navBarHeight
+ }
+ setContentView(binding.root)
+ review = intent.getSerializableExtra("review") as Query.Review
+ binding.userName.text = review.user?.name
+ binding.userAvatar.loadImage(review.user?.avatar?.medium)
+ binding.userTime.text = ActivityItemBuilder.getDateTime(review.createdAt)
+ binding.profileUserBio.settings.loadWithOverviewMode = true
+ binding.profileUserBio.settings.useWideViewPort = true
+ binding.profileUserBio.setInitialScale(1)
+ val styledHtml = AniMarkdown.getFullAniHTML(
+ review.body,
+ ContextCompat.getColor(this, R.color.bg_opp)
+ )
+ binding.profileUserBio.loadDataWithBaseURL(
+ null,
+ styledHtml,
+ "text/html",
+ "utf-8",
+ null
+ )
+ binding.profileUserBio.setBackgroundColor(
+ ContextCompat.getColor(
+ this,
+ android.R.color.transparent
+ )
+ )
+ binding.profileUserBio.setLayerType(View.LAYER_TYPE_HARDWARE, null)
+ binding.profileUserBio.webViewClient = object : WebViewClient() {
+ override fun onPageFinished(view: WebView?, url: String?) {
+ super.onPageFinished(view, url)
+ binding.profileUserBio.setBackgroundColor(
+ ContextCompat.getColor(
+ this@ReviewViewActivity,
+ android.R.color.transparent
+ )
+ )
+ }
+
+ override fun shouldOverrideUrlLoading(
+ view: WebView?,
+ request: WebResourceRequest?
+ ): Boolean {
+ return true
+ }
+ }
+ userVote(review.userRating)
+ enableVote()
+ binding.voteCount.text = review.rating.toString()
+ binding.voteText.text = getString(
+ R.string.vote_out_of_total,
+ review.rating.toString(),
+ review.ratingAmount.toString()
+ )
+ }
+
+ private fun userVote(type: String) {
+ val selectedColor = getThemeColor(com.google.android.material.R.attr.colorPrimary)
+ val unselectedColor = getThemeColor(androidx.appcompat.R.attr.colorControlNormal)
+ when (type) {
+ "NO_VOTE" -> {
+ binding.upvote.setColorFilter(unselectedColor)
+ binding.downvote.setColorFilter(unselectedColor)
+ }
+
+ "UP_VOTE" -> {
+ binding.upvote.setColorFilter(selectedColor)
+ binding.downvote.setColorFilter(unselectedColor)
+ }
+
+ "DOWN_VOTE" -> {
+ binding.upvote.setColorFilter(unselectedColor)
+ binding.downvote.setColorFilter(selectedColor)
+ }
+ }
+ }
+
+ private fun rateReview(rating: String) {
+ disableVote()
+ 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.voteCount.text = review.rating.toString()
+ binding.voteText.text = getString(
+ R.string.vote_out_of_total,
+ review.rating.toString(),
+ review.ratingAmount.toString()
+ )
+ userVote(review.userRating)
+ enableVote()
+ }
+ } else {
+ withContext(Dispatchers.Main) {
+ toast(
+ getString(R.string.error_message, "response is null")
+ )
+ enableVote()
+ }
+ }
+ }
+ }
+
+ private fun disableVote() {
+ binding.upvote.setOnClickListener(null)
+ binding.downvote.setOnClickListener(null)
+ binding.upvote.isEnabled = false
+ binding.downvote.isEnabled = false
+ }
+
+ private fun enableVote() {
+ binding.upvote.setOnClickListener {
+ if (review.userRating == "UP_VOTE") {
+ rateReview("NO_VOTE")
+ } else {
+ rateReview("UP_VOTE")
+ }
+ disableVote()
+ }
+ binding.downvote.setOnClickListener {
+ if (review.userRating == "DOWN_VOTE") {
+ rateReview("NO_VOTE")
+ } else {
+ rateReview("DOWN_VOTE")
+ }
+ disableVote()
+ }
+ binding.upvote.isEnabled = true
+ binding.downvote.isEnabled = true
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/profile/FollowActivity.kt b/app/src/main/java/ani/dantotsu/profile/FollowActivity.kt
index c5c606d1e8..6e2a92fcb6 100644
--- a/app/src/main/java/ani/dantotsu/profile/FollowActivity.kt
+++ b/app/src/main/java/ani/dantotsu/profile/FollowActivity.kt
@@ -2,6 +2,7 @@ package ani.dantotsu.profile
import android.content.Intent
import android.os.Bundle
+import android.text.SpannableString
import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import android.widget.ImageButton
@@ -54,7 +55,7 @@ class FollowActivity : AppCompatActivity() {
)
binding.listRecyclerView.adapter = adapter
binding.listProgressBar.visibility = View.VISIBLE
- binding.listBack.setOnClickListener { finish() }
+ binding.listBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
val title = intent.getStringExtra("title")
val userID = intent.getIntExtra("userId", 0)
@@ -97,10 +98,11 @@ class FollowActivity : AppCompatActivity() {
}
users?.forEach { user ->
if (getLayoutType(selected) == 0) {
+ val username = SpannableString(user.name ?: "Unknown")
adapter.add(
FollowerItem(
user.id,
- user.name ?: "Unknown",
+ username,
user.avatar?.medium,
user.bannerImage ?: user.avatar?.medium
) { onUserClick(it) })
diff --git a/app/src/main/java/ani/dantotsu/profile/FollowerItem.kt b/app/src/main/java/ani/dantotsu/profile/FollowerItem.kt
index 9513c29e46..18c05a8951 100644
--- a/app/src/main/java/ani/dantotsu/profile/FollowerItem.kt
+++ b/app/src/main/java/ani/dantotsu/profile/FollowerItem.kt
@@ -1,6 +1,7 @@
package ani.dantotsu.profile
+import android.text.SpannableString
import android.view.View
import ani.dantotsu.R
import ani.dantotsu.blurImage
@@ -10,9 +11,10 @@ import com.xwray.groupie.viewbinding.BindableItem
class FollowerItem(
private val id: Int,
- private val name: String,
+ private val name: SpannableString,
private val avatar: String?,
private val banner: String?,
+ private val altText: String? = null,
val clickCallback: (Int) -> Unit
) : BindableItem() {
private lateinit var binding: ItemFollowerBinding
@@ -21,6 +23,10 @@ class FollowerItem(
binding = viewBinding
binding.profileUserName.text = name
avatar?.let { binding.profileUserAvatar.loadImage(it) }
+ altText?.let {
+ binding.altText.visibility = View.VISIBLE
+ binding.altText.text = it
+ }
blurImage(binding.profileBannerImage, banner ?: avatar)
binding.root.setOnClickListener { clickCallback(id) }
}
diff --git a/app/src/main/res/drawable/ic_thumbs.xml b/app/src/main/res/drawable/ic_thumbs.xml
new file mode 100644
index 0000000000..8c5dd3cc8e
--- /dev/null
+++ b/app/src/main/res/drawable/ic_thumbs.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/surface_rounded_bg.xml b/app/src/main/res/drawable/surface_rounded_bg.xml
new file mode 100644
index 0000000000..59ad61753d
--- /dev/null
+++ b/app/src/main/res/drawable/surface_rounded_bg.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_review_view.xml b/app/src/main/res/layout/activity_review_view.xml
new file mode 100644
index 0000000000..6732d8f936
--- /dev/null
+++ b/app/src/main/res/layout/activity_review_view.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_follower.xml b/app/src/main/res/layout/item_follower.xml
index 2339b8ce74..675e5451b2 100644
--- a/app/src/main/res/layout/item_follower.xml
+++ b/app/src/main/res/layout/item_follower.xml
@@ -52,14 +52,34 @@
-
+ android:layout_marginStart="100dp"
+ android:gravity="center_vertical"
+ android:orientation="vertical">
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_title_search.xml b/app/src/main/res/layout/item_title_search.xml
index 8f1c8f0e93..b1232b928d 100644
--- a/app/src/main/res/layout/item_title_search.xml
+++ b/app/src/main/res/layout/item_title_search.xml
@@ -50,7 +50,7 @@
android:gravity="center"
android:maxLines="2"
android:padding="4dp"
- android:text="@string/search"
+ android:text="@string/reviews"
android:textAllCaps="true"
android:textColor="@color/bg_white"
android:textSize="14sp" />
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0c769dcbfa..3b030a0ac6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -430,7 +430,7 @@
Error: %1$s
Step: %1$s
Review
-
+ Reviews
Display only the first button
Display dantotsu in the second button
Display your AniList profile instead
@@ -850,8 +850,6 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
Do it!
Password
- Search %1$s
-
Track progress directly from your home screen
Anime\nWatched
Manga\nRead
@@ -981,4 +979,5 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
Download Subtitle
No video selected
No subtitles available
+ (%1$s out of %2$s liked this review)