Add option to hide watched videos from the feed

This commit is contained in:
Bnyro 2022-12-21 12:00:58 +01:00
parent 947077acdc
commit 0ecd9fbf28
7 changed files with 57 additions and 25 deletions

View File

@ -109,6 +109,7 @@ object PreferenceKeys {
*/ */
const val LAST_STREAM_VIDEO_ID = "last_stream_video_id" const val LAST_STREAM_VIDEO_ID = "last_stream_video_id"
const val LAST_WATCHED_FEED_TIME = "last_watched_feed_time" const val LAST_WATCHED_FEED_TIME = "last_watched_feed_time"
const val HIDE_WATCHED_FROM_FEED = "hide_watched_from_feed"
/** /**
* Advanced * Advanced

View File

@ -32,7 +32,8 @@ import com.github.libretube.util.TextUtils
class VideosAdapter( class VideosAdapter(
private val streamItems: MutableList<StreamItem>, private val streamItems: MutableList<StreamItem>,
private val showAllAtOnce: Boolean = true, private val showAllAtOnce: Boolean = true,
private val forceMode: ForceMode = ForceMode.NONE private val forceMode: ForceMode = ForceMode.NONE,
private val hideWatched: Boolean = false
) : RecyclerView.Adapter<VideosViewHolder>() { ) : RecyclerView.Adapter<VideosViewHolder>() {
var index = 10 var index = 10
@ -81,17 +82,33 @@ class VideosAdapter(
} }
} }
private fun hideItemView(holder: VideosViewHolder) {
holder.itemView.visibility = View.GONE
holder.itemView.layoutParams = RecyclerView.LayoutParams(0, 0)
}
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: VideosViewHolder, position: Int) { override fun onBindViewHolder(holder: VideosViewHolder, position: Int) {
val video = streamItems[position] val video = streamItems[position]
val videoId = video.url?.toID()
val videoName = video.title
// hide the item if there was an extractor error // hide the item if there was an extractor error
if (video.title == null && video.type != "caught") { if (video.title == null && video.type != "caught") {
holder.itemView.visibility = View.GONE hideItemView(holder)
holder.itemView.layoutParams = RecyclerView.LayoutParams(0, 0)
return return
} }
videoId?.let {
val shouldHide = (holder.trendingRowBinding?.watchProgress ?: holder.videoRowBinding!!.watchProgress)
.setWatchProgressLength(it, video.duration ?: 0L)
if (hideWatched && shouldHide) {
hideItemView(holder)
return
}
}
// Trending layout // Trending layout
holder.trendingRowBinding?.apply { holder.trendingRowBinding?.apply {
// set a fixed width for better visuals // set a fixed width for better visuals
@ -120,8 +137,6 @@ class VideosAdapter(
root.setOnClickListener { root.setOnClickListener {
NavigationHelper.navigateVideo(root.context, video.url) NavigationHelper.navigateVideo(root.context, video.url)
} }
val videoId = video.url?.toID()
val videoName = video.title
root.setOnLongClickListener { root.setOnLongClickListener {
if (videoId == null || videoName == null) return@setOnLongClickListener true if (videoId == null || videoName == null) return@setOnLongClickListener true
@ -133,9 +148,6 @@ class VideosAdapter(
true true
} }
if (videoId != null) {
watchProgress.setWatchProgressLength(videoId, video.duration ?: 0L)
}
} }
// Normal videos row layout // Normal videos row layout
@ -167,8 +179,6 @@ class VideosAdapter(
NavigationHelper.navigateVideo(root.context, video.url) NavigationHelper.navigateVideo(root.context, video.url)
} }
val videoId = video.url?.toID()
val videoName = video.title
root.setOnLongClickListener { root.setOnLongClickListener {
if (videoId == null || videoName == null) return@setOnLongClickListener true if (videoId == null || videoName == null) return@setOnLongClickListener true
VideoOptionsBottomSheet(videoId, videoName) VideoOptionsBottomSheet(videoId, videoName)
@ -176,13 +186,8 @@ class VideosAdapter(
(root.context as BaseActivity).supportFragmentManager, (root.context as BaseActivity).supportFragmentManager,
VideoOptionsBottomSheet::class.java.name VideoOptionsBottomSheet::class.java.name
) )
true true
} }
if (videoId != null) {
watchProgress.setWatchProgressLength(videoId, video.duration ?: 0L)
}
} }
} }

View File

@ -7,9 +7,12 @@ import com.github.libretube.db.DatabaseHolder.Companion.Database
import com.github.libretube.extensions.awaitQuery import com.github.libretube.extensions.awaitQuery
/** /**
* shows the already watched time under the video * Shows the already watched time under the video
* @param videoId The id of the video to inspect
* @param duration The duration of the video in seconds
* @return Whether the video is already watched more than 90%
*/ */
fun View?.setWatchProgressLength(videoId: String, duration: Long) { fun View?.setWatchProgressLength(videoId: String, duration: Long): Boolean {
val view = this!! val view = this!!
val progress = try { val progress = try {
@ -17,23 +20,27 @@ fun View?.setWatchProgressLength(videoId: String, duration: Long) {
Database.watchPositionDao().findById(videoId)?.position Database.watchPositionDao().findById(videoId)?.position
} }
} catch (e: Exception) { } catch (e: Exception) {
return return false
} // divide by 1000 to convert ms to seconds
?.toFloat()?.div(1000)
if (progress == null || duration == 0L) {
view.visibility = View.GONE
return false
} }
view.viewTreeObserver view.viewTreeObserver
.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { .addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() { override fun onGlobalLayout() {
this@setWatchProgressLength.viewTreeObserver.removeOnGlobalLayoutListener(this) this@setWatchProgressLength.viewTreeObserver.removeOnGlobalLayoutListener(this)
if (progress == null || duration == 0L) {
view.visibility = View.GONE
return
}
val fullWidth = (parent as LinearLayout).width val fullWidth = (parent as LinearLayout).width
val newWidth = (fullWidth * (progress / duration)) / 1000 val newWidth = fullWidth * (progress / duration.toFloat())
val lp = view.layoutParams val lp = view.layoutParams
lp.width = newWidth.toInt() lp.width = newWidth.toInt()
view.layoutParams = lp view.layoutParams = lp
view.visibility = View.VISIBLE view.visibility = View.VISIBLE
} }
}) })
return (progress ?: 0f) / duration.toFloat() > 0.9
} }

View File

@ -167,7 +167,8 @@ class SubscriptionsFragment : BaseFragment() {
binding.subProgress.visibility = View.GONE binding.subProgress.visibility = View.GONE
subscriptionAdapter = VideosAdapter( subscriptionAdapter = VideosAdapter(
sortedFeed.toMutableList(), sortedFeed.toMutableList(),
showAllAtOnce = false showAllAtOnce = false,
hideWatched = PreferenceHelper.getBoolean(PreferenceKeys.HIDE_WATCHED_FROM_FEED, false)
) )
binding.subFeed.adapter = subscriptionAdapter binding.subFeed.adapter = subscriptionAdapter

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,7c2.76,0 5,2.24 5,5 0,0.65 -0.13,1.26 -0.36,1.83l2.92,2.92c1.51,-1.26 2.7,-2.89 3.43,-4.75 -1.73,-4.39 -6,-7.5 -11,-7.5 -1.4,0 -2.74,0.25 -3.98,0.7l2.16,2.16C10.74,7.13 11.35,7 12,7zM2,4.27l2.28,2.28 0.46,0.46C3.08,8.3 1.78,10.02 1,12c1.73,4.39 6,7.5 11,7.5 1.55,0 3.03,-0.3 4.38,-0.84l0.42,0.42L19.73,22 21,20.73 3.27,3 2,4.27zM7.53,9.8l1.55,1.55c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.66 1.34,3 3,3 0.22,0 0.44,-0.03 0.65,-0.08l1.55,1.55c-0.67,0.33 -1.41,0.53 -2.2,0.53 -2.76,0 -5,-2.24 -5,-5 0,-0.79 0.2,-1.53 0.53,-2.2zM11.84,9.02l3.15,3.15 0.02,-0.16c0,-1.66 -1.34,-3 -3,-3l-0.17,0.01z" />
</vector>

View File

@ -418,6 +418,8 @@
<string name="nothing_selected">Nothing selected!</string> <string name="nothing_selected">Nothing selected!</string>
<string name="color_violet">Versatile Violet</string> <string name="color_violet">Versatile Violet</string>
<string name="failed_fetching_instances">Failed to fetch available instances.</string> <string name="failed_fetching_instances">Failed to fetch available instances.</string>
<string name="hide_watched_from_feed">Hide watched videos from feed</string>
<string name="hide_watched_from_feed_summary">Don\'t show videos being watched more than 90% in the subscriptions tab.</string>
<!-- Notification channel strings --> <!-- Notification channel strings -->
<string name="download_channel_name">Download Service</string> <string name="download_channel_name">Download Service</string>

View File

@ -37,6 +37,12 @@
app:key="confirm_unsubscribing" app:key="confirm_unsubscribing"
app:title="@string/confirm_unsubscribing" /> app:title="@string/confirm_unsubscribing" />
<SwitchPreferenceCompat
android:icon="@drawable/ic_invisible"
android:summary="@string/hide_watched_from_feed_summary"
android:title="@string/hide_watched_from_feed"
app:key="hide_watched_from_feed" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory app:title="@string/misc"> <PreferenceCategory app:title="@string/misc">