mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-14 14:20:30 +05:30
Merge pull request #2464 from Bnyro/master
Add option to hide watched videos from the feed
This commit is contained in:
commit
7cc436950c
@ -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
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
10
app/src/main/res/drawable/ic_invisible.xml
Normal file
10
app/src/main/res/drawable/ic_invisible.xml
Normal 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>
|
@ -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>
|
||||||
|
@ -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">
|
||||||
|
Loading…
Reference in New Issue
Block a user