diff --git a/app/src/main/java/com/github/libretube/PipedApi.kt b/app/src/main/java/com/github/libretube/PipedApi.kt index bfd9a71cb..94c2a65b5 100644 --- a/app/src/main/java/com/github/libretube/PipedApi.kt +++ b/app/src/main/java/com/github/libretube/PipedApi.kt @@ -10,6 +10,12 @@ interface PipedApi { @GET("streams/{videoId}") suspend fun getStreams(@Path("videoId") videoId: String): Streams + @GET("comments/{videoId}") + suspend fun getComments(@Path("videoId") videoId: String): CommentsPage + + @GET("nextpage/comments/{videoId}") + suspend fun getCommentsNextPage(@Path("videoId") videoId: String, @Query("nextpage") nextPage: String): CommentsPage + @GET("search") suspend fun getSearchResults( @Query("q") searchQuery: String, diff --git a/app/src/main/java/com/github/libretube/PlayerFragment.kt b/app/src/main/java/com/github/libretube/PlayerFragment.kt index c08ac332f..fa6c60caf 100644 --- a/app/src/main/java/com/github/libretube/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/PlayerFragment.kt @@ -31,7 +31,9 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.preference.PreferenceManager import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.github.libretube.adapters.CommentsAdapter import com.github.libretube.adapters.TrendingAdapter import com.github.libretube.obj.PipedStream import com.github.libretube.obj.Subscribe @@ -75,6 +77,10 @@ class PlayerFragment : Fragment() { var isSubscribed: Boolean = false private lateinit var relatedRecView: RecyclerView + private lateinit var commentsRecView: RecyclerView + private var commentsAdapter: CommentsAdapter? = null + private var nextPage: String? = null + private var isLoading = true private lateinit var exoPlayerView: StyledPlayerView private lateinit var motionLayout: MotionLayout private lateinit var exoPlayer: ExoPlayer @@ -192,10 +198,15 @@ class PlayerFragment : Fragment() { } view.findViewById(R.id.player_title_layout).setOnClickListener { - var visible = playerDescription.isVisible - - playerDescription.visibility = if (visible) View.GONE else View.VISIBLE + playerDescription.visibility = + if (playerDescription.isVisible) View.GONE else View.VISIBLE } + + view.findViewById(R.id.comments_toggle).setOnClickListener { + commentsRecView.visibility = if (commentsRecView.isVisible) View.GONE else View.VISIBLE + relatedRecView.visibility = if (relatedRecView.isVisible) View.GONE else View.VISIBLE + } + // FullScreen button trigger view.findViewById(R.id.fullscreen).setOnClickListener { // remember to hide everything when new thing added @@ -221,6 +232,25 @@ class PlayerFragment : Fragment() { isFullScreen = false } } + + val scrollView = view.findViewById(R.id.player_scrollView) + scrollView.viewTreeObserver + .addOnScrollChangedListener { + if (scrollView.getChildAt(0).bottom + == (scrollView.height + scrollView.scrollY) + ) { + fetchNextComments() + } + + } + + commentsRecView = view.findViewById(R.id.comments_recView) + commentsRecView.layoutManager = LinearLayoutManager(view.context) + + commentsRecView.setItemViewCacheSize(20) + commentsRecView.setDrawingCacheEnabled(true) + commentsRecView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH) + relatedRecView = view.findViewById(R.id.player_recView) relatedRecView.layoutManager = GridLayoutManager(view.context, resources.getInteger(R.integer.grid_items)) @@ -253,6 +283,19 @@ class PlayerFragment : Fragment() { Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show() return@launchWhenCreated } + val commentsResponse = try { + RetrofitInstance.api.getComments(videoId!!) + } catch (e: IOException) { + println(e) + Log.e(TAG, "IOException, you might not have internet connection") + Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show() + return@launchWhenCreated + } catch (e: HttpException) { + Log.e(TAG, "HttpException, unexpected response") + Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show() + return@launchWhenCreated + } + isLoading = false var videosNameArray: Array = arrayOf() videosNameArray += "HLS" for (vid in response.videoStreams!!) { @@ -476,7 +519,11 @@ class PlayerFragment : Fragment() { } } }) + commentsAdapter = CommentsAdapter(commentsResponse.comments) + commentsRecView.adapter = commentsAdapter + nextPage = commentsResponse.nextpage relatedRecView.adapter = TrendingAdapter(response.relatedStreams!!) + view.findViewById(R.id.player_description).text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { Html.fromHtml(response.description, Html.FROM_HTML_MODE_COMPACT) @@ -736,4 +783,25 @@ class PlayerFragment : Fragment() { override fun onResume() { super.onResume() } + + private fun fetchNextComments(){ + lifecycleScope.launchWhenCreated { + if (!isLoading) { + isLoading = true + val response = try { + RetrofitInstance.api.getCommentsNextPage(videoId!!, nextPage!!) + } catch (e: IOException) { + println(e) + Log.e(TAG, "IOException, you might not have internet connection") + return@launchWhenCreated + } catch (e: HttpException) { + Log.e(TAG, "HttpException, unexpected response," + e.response()) + return@launchWhenCreated + } + nextPage = response.nextpage + commentsAdapter?.updateItems(response.comments!!) + isLoading = false + } + } + } } diff --git a/app/src/main/java/com/github/libretube/adapters/CommentsAdapter.kt b/app/src/main/java/com/github/libretube/adapters/CommentsAdapter.kt new file mode 100644 index 000000000..bdd0f0811 --- /dev/null +++ b/app/src/main/java/com/github/libretube/adapters/CommentsAdapter.kt @@ -0,0 +1,53 @@ +package com.github.libretube.adapters + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.github.libretube.R +import com.github.libretube.formatShort +import com.github.libretube.obj.Comment +import com.squareup.picasso.Picasso + +class CommentsAdapter(private val comments: MutableList): RecyclerView.Adapter(){ + + fun updateItems(newItems: List){ + var commentsSize = comments.size + comments.addAll(newItems) + notifyItemRangeInserted(commentsSize, newItems.size) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + var commentsView = LayoutInflater.from(parent.context).inflate(R.layout.comments_row, parent, false) + return ViewHolder(commentsView) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.v.findViewById(R.id.comment_infos).text = comments[position].author.toString() + " • " + comments[position].commentedTime.toString() + holder.v.findViewById(R.id.comment_text).text = comments[position].commentText.toString() + val thumbnailImage = holder.v.findViewById(R.id.commentor_image) + Picasso.get().load(comments[position].thumbnail).fit().centerCrop().into(thumbnailImage) + holder.v.findViewById(R.id.likes_textView).text = comments[position].likeCount?.toLong().formatShort() + if (comments[position].verified == true) { + holder.v.findViewById(R.id.verified_imageView).visibility = View.VISIBLE + } + if (comments[position].pinned == true) { + holder.v.findViewById(R.id.pinned_imageView).visibility = View.VISIBLE + } + if (comments[position].hearted == true) { + holder.v.findViewById(R.id.hearted_imageView).visibility = View.VISIBLE + } + } + + override fun getItemCount(): Int { + return comments.size + } + +} + +class ViewHolder(val v: View): RecyclerView.ViewHolder(v){ + init { + } +} diff --git a/app/src/main/java/com/github/libretube/obj/Comment.java b/app/src/main/java/com/github/libretube/obj/Comment.java deleted file mode 100644 index 953bb7bdf..000000000 --- a/app/src/main/java/com/github/libretube/obj/Comment.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.github.libretube.obj; - -public class Comment { - public String author, thumbnail, commentId, commentText, commentedTime, commentorUrl, repliesPage; - public int likeCount; - public boolean hearted, pinned, verified; - - public Comment(String author, String thumbnail, String commentId, String commentText, String commentedTime, - String commentorUrl, String repliesPage, int likeCount, boolean hearted, boolean pinned, boolean verified) { - this.author = author; - this.thumbnail = thumbnail; - this.commentId = commentId; - this.commentText = commentText; - this.commentedTime = commentedTime; - this.commentorUrl = commentorUrl; - this.repliesPage = repliesPage; - this.likeCount = likeCount; - this.hearted = hearted; - this.pinned = pinned; - this.verified = verified; - } -} diff --git a/app/src/main/java/com/github/libretube/obj/Comment.kt b/app/src/main/java/com/github/libretube/obj/Comment.kt new file mode 100644 index 000000000..2e015acc8 --- /dev/null +++ b/app/src/main/java/com/github/libretube/obj/Comment.kt @@ -0,0 +1,20 @@ +package com.github.libretube.obj + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class Comment( + val author: String?, + val commentId: String?, + val commentText: String?, + val commentedTime: String?, + val commentorUrl: String?, + val hearted: Boolean?, + val likeCount: Int?, + val pinned: Boolean?, + val thumbnail: String?, + val verified: Boolean? +){ + constructor(): this("", "","","","",null,0,null,"",null) +} + diff --git a/app/src/main/java/com/github/libretube/obj/CommentsPage.java b/app/src/main/java/com/github/libretube/obj/CommentsPage.java deleted file mode 100644 index a8fb24b20..000000000 --- a/app/src/main/java/com/github/libretube/obj/CommentsPage.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.github.libretube.obj; - -import java.util.List; - -public class CommentsPage { - - public List comments; - public String nextpage; - public boolean disabled; - - public CommentsPage(List comments, String nextpage, boolean disabled) { - this.comments = comments; - this.nextpage = nextpage; - this.disabled = disabled; - } -} diff --git a/app/src/main/java/com/github/libretube/obj/CommentsPage.kt b/app/src/main/java/com/github/libretube/obj/CommentsPage.kt new file mode 100644 index 000000000..54b5519d0 --- /dev/null +++ b/app/src/main/java/com/github/libretube/obj/CommentsPage.kt @@ -0,0 +1,12 @@ +package com.github.libretube.obj + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class CommentsPage( + val comments: MutableList = arrayListOf(), + val disabled: Boolean? = null, + val nextpage: String? = "", +){ + constructor(): this(arrayListOf(),null,"") +} diff --git a/app/src/main/res/drawable/ic_hearted.xml b/app/src/main/res/drawable/ic_hearted.xml new file mode 100644 index 000000000..f690e38fd --- /dev/null +++ b/app/src/main/res/drawable/ic_hearted.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_pinned.xml b/app/src/main/res/drawable/ic_pinned.xml new file mode 100644 index 000000000..f1e14a868 --- /dev/null +++ b/app/src/main/res/drawable/ic_pinned.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_thumb_up.xml b/app/src/main/res/drawable/ic_thumb_up.xml new file mode 100644 index 000000000..6a39a3934 --- /dev/null +++ b/app/src/main/res/drawable/ic_thumb_up.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_verified.xml b/app/src/main/res/drawable/ic_verified.xml new file mode 100644 index 000000000..bbb482627 --- /dev/null +++ b/app/src/main/res/drawable/ic_verified.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/comments_row.xml b/app/src/main/res/layout/comments_row.xml new file mode 100644 index 000000000..878a2841e --- /dev/null +++ b/app/src/main/res/layout/comments_row.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_player.xml b/app/src/main/res/layout/fragment_player.xml index d3057fba0..e92513b53 100644 --- a/app/src/main/res/layout/fragment_player.xml +++ b/app/src/main/res/layout/fragment_player.xml @@ -9,7 +9,7 @@ tools:context=".PlayerFragment"> - + + + + + + + + + android:layout_marginTop="20dp" + android:layout_marginLeft="20dp" + android:layout_marginRight="20dp" + android:layout_below="@id/comments_toggle" + android:nestedScrollingEnabled="false" + android:visibility="gone" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 936811986..0dcb5ae6f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -64,4 +64,5 @@ Dark Theme %1$s subscribers %1$s videos + Comments