Implemented the feature and fixed some small issues

This commit is contained in:
Jared Fantaye 2023-02-01 23:10:31 +01:00
parent 3d36eb5baf
commit 9c82441c19
8 changed files with 82 additions and 50 deletions

View File

@ -71,8 +71,8 @@ abstract class FeedDAO {
:includePartiallyPlayed :includePartiallyPlayed
OR sh.stream_id IS NULL OR sh.stream_id IS NULL
OR sst.stream_id IS NULL OR sst.stream_id IS NULL
OR (sst.progress_time < ${StreamStateEntity.PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS} OR (sst.progress_time <= ${StreamStateEntity.PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS}
AND sst.progress_time < s.duration * 1000 / 4) AND sst.progress_time <= s.duration * 1000 / 4)
) )
AND ( AND (
:uploadDateBefore IS NULL :uploadDateBefore IS NULL

View File

@ -100,9 +100,13 @@ class FeedFragment : BaseStateFragment<FeedState>() {
private var oldestSubscriptionUpdate: OffsetDateTime? = null private var oldestSubscriptionUpdate: OffsetDateTime? = null
private lateinit var groupAdapter: GroupieAdapter private lateinit var groupAdapter: GroupieAdapter
@State @JvmField var showPlayedItems: ShowItems = ShowItems.DEFAULT @State @JvmField var feedVisibilityStatus: StreamVisibilityStatus = StreamVisibilityStatus.DEFAULT
@State @JvmField var showFutureItems: Boolean = true @State @JvmField var showFutureItems: Boolean = true
private lateinit var showAllMenuItem: MenuItem
private lateinit var hideWatchedMenuItem: MenuItem
private lateinit var hidePartiallyWatchedMenuItem: MenuItem
private var onSettingsChangeListener: SharedPreferences.OnSharedPreferenceChangeListener? = null private var onSettingsChangeListener: SharedPreferences.OnSharedPreferenceChangeListener? = null
private var updateListViewModeOnResume = false private var updateListViewModeOnResume = false
private var isRefreshing = false private var isRefreshing = false
@ -140,7 +144,7 @@ class FeedFragment : BaseStateFragment<FeedState>() {
val factory = FeedViewModel.getFactory(requireContext(), groupId) val factory = FeedViewModel.getFactory(requireContext(), groupId)
viewModel = ViewModelProvider(this, factory)[FeedViewModel::class.java] viewModel = ViewModelProvider(this, factory)[FeedViewModel::class.java]
showPlayedItems = viewModel.getItemsVisibilityFromPreferences() feedVisibilityStatus = viewModel.getItemsVisibilityFromPreferences()
showFutureItems = viewModel.getShowFutureItemsFromPreferences() showFutureItems = viewModel.getShowFutureItemsFromPreferences()
viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(::handleResult) } viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(::handleResult) }
@ -216,7 +220,15 @@ class FeedFragment : BaseStateFragment<FeedState>() {
activity.supportActionBar?.subtitle = groupName activity.supportActionBar?.subtitle = groupName
inflater.inflate(R.menu.menu_feed_fragment, menu) inflater.inflate(R.menu.menu_feed_fragment, menu)
updateTogglePlayedItemsButton(menu.findItem(R.id.menu_item_feed_toggle_played_items))
val itemVisibilityMenu = menu.findItem(R.id.menu_item_feed_toggle_played_items).subMenu
if (itemVisibilityMenu != null) {
showAllMenuItem = itemVisibilityMenu.findItem(R.id.menu_item_feed_toggle_show_all_items)
hideWatchedMenuItem = itemVisibilityMenu.findItem(R.id.menu_item_feed_toggle_show_played_items)
hidePartiallyWatchedMenuItem = itemVisibilityMenu.findItem(R.id.menu_item_feed_toggle_partially_played_items)
}
updateItemVisibilityMenu(menu.findItem(R.id.menu_item_feed_toggle_played_items))
updateToggleFutureItemsButton(menu.findItem(R.id.menu_item_feed_toggle_future_items)) updateToggleFutureItemsButton(menu.findItem(R.id.menu_item_feed_toggle_future_items))
} }
@ -243,11 +255,11 @@ class FeedFragment : BaseStateFragment<FeedState>() {
.show() .show()
return true return true
} else if (item.itemId == R.id.menu_item_feed_toggle_show_all_items) { } else if (item.itemId == R.id.menu_item_feed_toggle_show_all_items) {
setShowPlayedItemsMethod(item, ShowItems.DEFAULT) changeItemsVisibilityStatus(item, StreamVisibilityStatus.DEFAULT)
} else if (item.itemId == R.id.menu_item_feed_toggle_show_played_items) { } else if (item.itemId == R.id.menu_item_feed_toggle_show_played_items) {
setShowPlayedItemsMethod(item, ShowItems.WATCHED) changeItemsVisibilityStatus(item, StreamVisibilityStatus.HIDE_WATCHED)
} else if (item.itemId == R.id.menu_item_feed_toggle_partially_played_items) { } else if (item.itemId == R.id.menu_item_feed_toggle_partially_played_items) {
setShowPlayedItemsMethod(item, ShowItems.PARTIALLY_WATCHED) changeItemsVisibilityStatus(item, StreamVisibilityStatus.HIDE_PARTIALLY_WATCHED)
} else if (item.itemId == R.id.menu_item_feed_toggle_future_items) { } else if (item.itemId == R.id.menu_item_feed_toggle_future_items) {
showFutureItems = !item.isChecked showFutureItems = !item.isChecked
updateToggleFutureItemsButton(item) updateToggleFutureItemsButton(item)
@ -258,11 +270,11 @@ class FeedFragment : BaseStateFragment<FeedState>() {
return super.onOptionsItemSelected(item) return super.onOptionsItemSelected(item)
} }
private fun setShowPlayedItemsMethod(item: MenuItem, showItems: ShowItems) { private fun changeItemsVisibilityStatus(item: MenuItem, streamVisibilityStatus: StreamVisibilityStatus) {
showPlayedItems = showItems feedVisibilityStatus = streamVisibilityStatus
viewModel.togglePlayedItems(showPlayedItems) viewModel.changeVisibilityState(feedVisibilityStatus)
updateTogglePlayedItemsButton(item) updateItemVisibilityMenu(item)
viewModel.saveShowPlayedItemsToPreferences(showPlayedItems) viewModel.saveStreamVisibilityStateToPreferences(feedVisibilityStatus)
} }
override fun onDestroyOptionsMenu() { override fun onDestroyOptionsMenu() {
@ -291,10 +303,28 @@ class FeedFragment : BaseStateFragment<FeedState>() {
super.onDestroyView() super.onDestroyView()
} }
private fun updateTogglePlayedItemsButton(menuItem: MenuItem) { private fun updateItemVisibilityMenu(menuItem: MenuItem) {
when (feedVisibilityStatus) {
StreamVisibilityStatus.DEFAULT -> {
showAllMenuItem.isVisible = false
hideWatchedMenuItem.isVisible = true
hidePartiallyWatchedMenuItem.isVisible = true
}
StreamVisibilityStatus.HIDE_WATCHED -> {
showAllMenuItem.isVisible = true
hideWatchedMenuItem.isVisible = false
hidePartiallyWatchedMenuItem.isVisible = true
}
else -> {
showAllMenuItem.isVisible = true
hideWatchedMenuItem.isVisible = true
hidePartiallyWatchedMenuItem.isVisible = false
}
}
MenuItemCompat.setTooltipText( MenuItemCompat.setTooltipText(
menuItem, menuItem,
getString(R.string.feed_toggle_show_hide_played_items) getString(R.string.feed_change_stream_visibility_state)
) )
} }

View File

@ -28,20 +28,17 @@ import org.schabi.newpipe.util.DEFAULT_THROTTLE_TIMEOUT
import java.time.OffsetDateTime import java.time.OffsetDateTime
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
enum class ShowItems {
WATCHED, PARTIALLY_WATCHED, DEFAULT
}
class FeedViewModel( class FeedViewModel(
private val application: Application, private val application: Application,
groupId: Long = FeedGroupEntity.GROUP_ALL_ID, groupId: Long = FeedGroupEntity.GROUP_ALL_ID,
initialShowPlayedItems: ShowItems = ShowItems.DEFAULT, initialStreamVisibility: StreamVisibilityStatus = StreamVisibilityStatus.DEFAULT,
initialShowFutureItems: Boolean = true initialShowFutureItems: Boolean = true
) : ViewModel() { ) : ViewModel() {
private val feedDatabaseManager = FeedDatabaseManager(application) private val feedDatabaseManager = FeedDatabaseManager(application)
private val toggleShowPlayedItems = BehaviorProcessor.create<ShowItems>() private val streamVisibilityState = BehaviorProcessor.create<StreamVisibilityStatus>()
private val toggleShowPlayedItemsFlowable = toggleShowPlayedItems private val streamVisibilityStateFlowable = streamVisibilityState
.startWithItem(initialShowPlayedItems) .startWithItem(initialStreamVisibility)
.distinctUntilChanged() .distinctUntilChanged()
private val toggleShowFutureItems = BehaviorProcessor.create<Boolean>() private val toggleShowFutureItems = BehaviorProcessor.create<Boolean>()
@ -55,12 +52,12 @@ class FeedViewModel(
private var combineDisposable = Flowable private var combineDisposable = Flowable
.combineLatest( .combineLatest(
FeedEventManager.events(), FeedEventManager.events(),
toggleShowPlayedItemsFlowable, streamVisibilityStateFlowable,
toggleShowFutureItemsFlowable, toggleShowFutureItemsFlowable,
feedDatabaseManager.notLoadedCount(groupId), feedDatabaseManager.notLoadedCount(groupId),
feedDatabaseManager.oldestSubscriptionUpdate(groupId), feedDatabaseManager.oldestSubscriptionUpdate(groupId),
Function5 { t1: FeedEventManager.Event, t2: ShowItems, t3: Boolean, Function5 { t1: FeedEventManager.Event, t2: StreamVisibilityStatus, t3: Boolean,
t4: Long, t5: List<OffsetDateTime> -> t4: Long, t5: List<OffsetDateTime> ->
return@Function5 CombineResultEventHolder(t1, t2, t3, t4, t5.firstOrNull()) return@Function5 CombineResultEventHolder(t1, t2, t3, t4, t5.firstOrNull())
} }
@ -74,10 +71,10 @@ class FeedViewModel(
.getStreams( .getStreams(
groupId, groupId,
!( !(
showPlayedItems == ShowItems.WATCHED || showPlayedItems == StreamVisibilityStatus.HIDE_WATCHED ||
showPlayedItems == ShowItems.PARTIALLY_WATCHED showPlayedItems == StreamVisibilityStatus.HIDE_PARTIALLY_WATCHED
), ),
showPlayedItems != ShowItems.PARTIALLY_WATCHED, showPlayedItems != StreamVisibilityStatus.HIDE_PARTIALLY_WATCHED,
showFutureItems showFutureItems
) )
.blockingGet(arrayListOf()) .blockingGet(arrayListOf())
@ -110,7 +107,7 @@ class FeedViewModel(
private data class CombineResultEventHolder( private data class CombineResultEventHolder(
val t1: FeedEventManager.Event, val t1: FeedEventManager.Event,
val t2: ShowItems, val t2: StreamVisibilityStatus,
val t3: Boolean, val t3: Boolean,
val t4: Long, val t4: Long,
val t5: OffsetDateTime? val t5: OffsetDateTime?
@ -123,20 +120,20 @@ class FeedViewModel(
val t4: OffsetDateTime? val t4: OffsetDateTime?
) )
fun togglePlayedItems(showItems: ShowItems) { fun changeVisibilityState(streamVisibilityStatus: StreamVisibilityStatus) {
toggleShowPlayedItems.onNext(showItems) streamVisibilityState.onNext(streamVisibilityStatus)
} }
fun saveShowPlayedItemsToPreferences(showItems: ShowItems) = fun saveStreamVisibilityStateToPreferences(streamVisibilityStatus: StreamVisibilityStatus) =
PreferenceManager.getDefaultSharedPreferences(application).edit { PreferenceManager.getDefaultSharedPreferences(application).edit {
this.putString( this.putString(
application.getString(R.string.feed_show_played_items_key), application.getString(R.string.feed_stream_visibility_state_key),
showItems.toString() streamVisibilityStatus.toString()
) )
this.apply() this.apply()
} }
fun getItemsVisibilityFromPreferences() = getItemsVisibilityFromPreferences(application) fun getItemsVisibilityFromPreferences() = getStreamVisibilityStateFromPreferences(application)
fun toggleFutureItems(showFutureItems: Boolean) { fun toggleFutureItems(showFutureItems: Boolean) {
toggleShowFutureItems.onNext(showFutureItems) toggleShowFutureItems.onNext(showFutureItems)
@ -152,13 +149,13 @@ class FeedViewModel(
companion object { companion object {
private fun getItemsVisibilityFromPreferences(context: Context): ShowItems { private fun getStreamVisibilityStateFromPreferences(context: Context): StreamVisibilityStatus {
val s = PreferenceManager.getDefaultSharedPreferences(context) val s = PreferenceManager.getDefaultSharedPreferences(context)
.getString( .getString(
context.getString(R.string.feed_show_played_items_key), context.getString(R.string.feed_stream_visibility_state_key),
ShowItems.DEFAULT.toString() StreamVisibilityStatus.DEFAULT.toString()
) ?: ShowItems.DEFAULT.toString() ) ?: StreamVisibilityStatus.DEFAULT.toString()
return ShowItems.valueOf(s) return StreamVisibilityStatus.valueOf(s)
} }
private fun getShowFutureItemsFromPreferences(context: Context) = private fun getShowFutureItemsFromPreferences(context: Context) =
@ -170,7 +167,7 @@ class FeedViewModel(
App.getApp(), App.getApp(),
groupId, groupId,
// Read initial value from preferences // Read initial value from preferences
getItemsVisibilityFromPreferences(context.applicationContext), getStreamVisibilityStateFromPreferences(context.applicationContext),
getShowFutureItemsFromPreferences(context.applicationContext) getShowFutureItemsFromPreferences(context.applicationContext)
) )
} }

View File

@ -0,0 +1,5 @@
package org.schabi.newpipe.local.feed
enum class StreamVisibilityStatus {
DEFAULT, HIDE_WATCHED, HIDE_PARTIALLY_WATCHED
}

View File

@ -87,7 +87,7 @@ public class HistoryRecordManager {
* Marks a stream item as watched such that it is hidden from the feed if watched videos are * Marks a stream item as watched such that it is hidden from the feed if watched videos are
* hidden. Adds a history entry and updates the stream progress to 100%. * hidden. Adds a history entry and updates the stream progress to 100%.
* *
* @see FeedViewModel#togglePlayedItems * @see FeedViewModel#changeVisibilityState
* @param info the item to mark as watched * @param info the item to mark as watched
* @return a Maybe containing the ID of the item if successful * @return a Maybe containing the ID of the item if successful
*/ */

View File

@ -7,18 +7,18 @@
android:checkable="false" android:checkable="false"
android:checked="false" android:checked="false"
android:icon="@drawable/ic_visibility_on" android:icon="@drawable/ic_visibility_on"
android:title="@string/feed_toggle_show_hide_played_items" android:title="@string/feed_change_stream_visibility_state"
app:showAsAction="ifRoom"> app:showAsAction="ifRoom">
<menu> <menu>
<item <item
android:id="@+id/menu_item_feed_toggle_show_all_items" android:id="@+id/menu_item_feed_toggle_show_all_items"
android:title="@string/feed_toggle_show_items"/> android:title="@string/feed_stream_visibility_show_all"/>
<item <item
android:id="@+id/menu_item_feed_toggle_show_played_items" android:id="@+id/menu_item_feed_toggle_show_played_items"
android:title="@string/feed_toggle_show_watched_items"/> android:title="@string/feed_stream_visibility_hide_watched"/>
<item <item
android:id="@+id/menu_item_feed_toggle_partially_played_items" android:id="@+id/menu_item_feed_toggle_partially_played_items"
android:title="@string/feed_toggle_show_partially_watched_items"/> android:title="@string/feed_stream_visibility_hide_partially_watched"/>
</menu> </menu>
</item> </item>

View File

@ -283,7 +283,7 @@
<string name="feed_update_threshold_key">feed_update_threshold_key</string> <string name="feed_update_threshold_key">feed_update_threshold_key</string>
<string name="feed_update_threshold_default_value">300</string> <string name="feed_update_threshold_default_value">300</string>
<string name="feed_show_played_items_key">feed_show_items</string> <string name="feed_stream_visibility_state_key">feed_stream_visibility_state</string>
<string name="feed_show_future_items_key">feed_show_future_items</string> <string name="feed_show_future_items_key">feed_show_future_items</string>
<string name="show_thumbnail_key">show_thumbnail_key</string> <string name="show_thumbnail_key">show_thumbnail_key</string>

View File

@ -691,7 +691,7 @@
\nYouTube is an example of a service that offers this fast method with its RSS feed. \nYouTube is an example of a service that offers this fast method with its RSS feed.
\n \n
\nSo the choice boils down to what you prefer: speed or precise information.</string> \nSo the choice boils down to what you prefer: speed or precise information.</string>
<string name="feed_toggle_show_hide_played_items">Show/hide watched items</string> <string name="feed_change_stream_visibility_state">Show/hide watched streams</string>
<string name="content_not_supported">This content is not yet supported by NewPipe.\n\nIt will hopefully be supported in a future version.</string> <string name="content_not_supported">This content is not yet supported by NewPipe.\n\nIt will hopefully be supported in a future version.</string>
<string name="detail_sub_channel_thumbnail_view_description">Channel\'s avatar thumbnail</string> <string name="detail_sub_channel_thumbnail_view_description">Channel\'s avatar thumbnail</string>
<string name="channel_created_by">Created by %s</string> <string name="channel_created_by">Created by %s</string>
@ -759,8 +759,8 @@
<string name="unknown_quality">Unknown quality</string> <string name="unknown_quality">Unknown quality</string>
<string name="feed_toggle_show_future_items">Show future items</string> <string name="feed_toggle_show_future_items">Show future items</string>
<string name="feed_toggle_hide_future_items">Hide future items</string> <string name="feed_toggle_hide_future_items">Hide future items</string>
<string name="feed_toggle_show_partially_watched_items">Hide Watched and Partially Watched </string> <string name="feed_stream_visibility_hide_partially_watched">Hide Watched </string>
<string name="feed_toggle_show_watched_items">Hide Watched</string> <string name="feed_stream_visibility_hide_watched">Hide Fully Watched</string>
<string name="feed_toggle_show_items">Show All</string> <string name="feed_stream_visibility_show_all">Show All</string>
<string name="sort">Sort</string> <string name="sort">Sort</string>
</resources> </resources>