Skip to content

Commit cd8d570

Browse files
committed
Implemented the feature using multiple checkboxes
1 parent 9c82441 commit cd8d570

8 files changed

Lines changed: 107 additions & 158 deletions

File tree

app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ abstract class FeedDAO {
7373
OR sst.stream_id IS NULL
7474
OR (sst.progress_time <= ${StreamStateEntity.PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS}
7575
AND sst.progress_time <= s.duration * 1000 / 4)
76+
OR (sst.progress_time >= s.duration * 1000 - ${StreamStateEntity.PLAYBACK_FINISHED_END_MILLISECONDS}
77+
OR sst.progress_time >= s.duration * 1000 * 3 / 4)
7678
)
7779
AND (
7880
:uploadDateBefore IS NULL

app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt

Lines changed: 41 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import android.view.View
3737
import android.view.ViewGroup
3838
import android.widget.Button
3939
import androidx.appcompat.app.AlertDialog
40-
import androidx.appcompat.content.res.AppCompatResources
4140
import androidx.core.content.edit
4241
import androidx.core.math.MathUtils
4342
import androidx.core.os.bundleOf
@@ -100,13 +99,10 @@ class FeedFragment : BaseStateFragment<FeedState>() {
10099
private var oldestSubscriptionUpdate: OffsetDateTime? = null
101100

102101
private lateinit var groupAdapter: GroupieAdapter
103-
@State @JvmField var feedVisibilityStatus: StreamVisibilityStatus = StreamVisibilityStatus.DEFAULT
102+
@State @JvmField var showPlayedItems: Boolean = true
103+
@State @JvmField var showPartiallyPlayedItems: Boolean = true
104104
@State @JvmField var showFutureItems: Boolean = true
105105

106-
private lateinit var showAllMenuItem: MenuItem
107-
private lateinit var hideWatchedMenuItem: MenuItem
108-
private lateinit var hidePartiallyWatchedMenuItem: MenuItem
109-
110106
private var onSettingsChangeListener: SharedPreferences.OnSharedPreferenceChangeListener? = null
111107
private var updateListViewModeOnResume = false
112108
private var isRefreshing = false
@@ -144,7 +140,8 @@ class FeedFragment : BaseStateFragment<FeedState>() {
144140

145141
val factory = FeedViewModel.getFactory(requireContext(), groupId)
146142
viewModel = ViewModelProvider(this, factory)[FeedViewModel::class.java]
147-
feedVisibilityStatus = viewModel.getItemsVisibilityFromPreferences()
143+
showPlayedItems = viewModel.getShowPlayedItemsFromPreferences()
144+
showPartiallyPlayedItems = viewModel.getShowPartiallyPlayedItemsFromPreferences()
148145
showFutureItems = viewModel.getShowFutureItemsFromPreferences()
149146
viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(::handleResult) }
150147

@@ -220,16 +217,10 @@ class FeedFragment : BaseStateFragment<FeedState>() {
220217
activity.supportActionBar?.subtitle = groupName
221218

222219
inflater.inflate(R.menu.menu_feed_fragment, menu)
223-
224-
val itemVisibilityMenu = menu.findItem(R.id.menu_item_feed_toggle_played_items).subMenu
225-
if (itemVisibilityMenu != null) {
226-
showAllMenuItem = itemVisibilityMenu.findItem(R.id.menu_item_feed_toggle_show_all_items)
227-
hideWatchedMenuItem = itemVisibilityMenu.findItem(R.id.menu_item_feed_toggle_show_played_items)
228-
hidePartiallyWatchedMenuItem = itemVisibilityMenu.findItem(R.id.menu_item_feed_toggle_partially_played_items)
229-
}
230-
231-
updateItemVisibilityMenu(menu.findItem(R.id.menu_item_feed_toggle_played_items))
232-
updateToggleFutureItemsButton(menu.findItem(R.id.menu_item_feed_toggle_future_items))
220+
MenuItemCompat.setTooltipText(
221+
menu.findItem(R.id.menu_item_feed_toggle_played_items),
222+
getString(R.string.feed_show_hide_streams)
223+
)
233224
}
234225

235226
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@@ -254,27 +245,44 @@ class FeedFragment : BaseStateFragment<FeedState>() {
254245
.create()
255246
.show()
256247
return true
257-
} else if (item.itemId == R.id.menu_item_feed_toggle_show_all_items) {
258-
changeItemsVisibilityStatus(item, StreamVisibilityStatus.DEFAULT)
259-
} else if (item.itemId == R.id.menu_item_feed_toggle_show_played_items) {
260-
changeItemsVisibilityStatus(item, StreamVisibilityStatus.HIDE_WATCHED)
261-
} else if (item.itemId == R.id.menu_item_feed_toggle_partially_played_items) {
262-
changeItemsVisibilityStatus(item, StreamVisibilityStatus.HIDE_PARTIALLY_WATCHED)
263-
} else if (item.itemId == R.id.menu_item_feed_toggle_future_items) {
264-
showFutureItems = !item.isChecked
265-
updateToggleFutureItemsButton(item)
266-
viewModel.toggleFutureItems(showFutureItems)
267-
viewModel.saveShowFutureItemsToPreferences(showFutureItems)
248+
} else if (item.itemId == R.id.menu_item_feed_toggle_played_items) {
249+
showStreamVisibilityDialog()
268250
}
269251

270252
return super.onOptionsItemSelected(item)
271253
}
272254

273-
private fun changeItemsVisibilityStatus(item: MenuItem, streamVisibilityStatus: StreamVisibilityStatus) {
274-
feedVisibilityStatus = streamVisibilityStatus
275-
viewModel.changeVisibilityState(feedVisibilityStatus)
276-
updateItemVisibilityMenu(item)
277-
viewModel.saveStreamVisibilityStateToPreferences(feedVisibilityStatus)
255+
private fun showStreamVisibilityDialog() {
256+
val dialogItems = arrayOf(
257+
getString(R.string.feed_show_watched),
258+
getString(R.string.feed_show_partially_watched),
259+
getString(R.string.feed_show_upcoming)
260+
)
261+
262+
val checkedDialogItems = booleanArrayOf(!showPlayedItems, !showPartiallyPlayedItems, !showFutureItems)
263+
264+
val builder = AlertDialog.Builder(context!!)
265+
builder.setTitle(R.string.feed_hide_streams_title)
266+
builder.setMultiChoiceItems(dialogItems, checkedDialogItems) { _, which, isChecked ->
267+
checkedDialogItems[which] = isChecked
268+
}
269+
270+
builder.setPositiveButton(R.string.ok) { _, _ ->
271+
showPlayedItems = !checkedDialogItems[0]
272+
viewModel.setShowPlayedItems(showPlayedItems)
273+
viewModel.saveShowPlayedItemsToPreferences(showPlayedItems)
274+
275+
showPartiallyPlayedItems = !checkedDialogItems[1]
276+
viewModel.setShowPartiallyPlayedItems(showPartiallyPlayedItems)
277+
viewModel.saveShowPartiallyPlayedItemsToPreferences(showPartiallyPlayedItems)
278+
279+
showFutureItems = !checkedDialogItems[2]
280+
viewModel.setShowFutureItems(showFutureItems)
281+
viewModel.saveShowFutureItemsToPreferences(showFutureItems)
282+
}
283+
builder.setNegativeButton(R.string.cancel, null)
284+
285+
builder.create().show()
278286
}
279287

280288
override fun onDestroyOptionsMenu() {
@@ -303,48 +311,6 @@ class FeedFragment : BaseStateFragment<FeedState>() {
303311
super.onDestroyView()
304312
}
305313

306-
private fun updateItemVisibilityMenu(menuItem: MenuItem) {
307-
when (feedVisibilityStatus) {
308-
StreamVisibilityStatus.DEFAULT -> {
309-
showAllMenuItem.isVisible = false
310-
hideWatchedMenuItem.isVisible = true
311-
hidePartiallyWatchedMenuItem.isVisible = true
312-
}
313-
StreamVisibilityStatus.HIDE_WATCHED -> {
314-
showAllMenuItem.isVisible = true
315-
hideWatchedMenuItem.isVisible = false
316-
hidePartiallyWatchedMenuItem.isVisible = true
317-
}
318-
else -> {
319-
showAllMenuItem.isVisible = true
320-
hideWatchedMenuItem.isVisible = true
321-
hidePartiallyWatchedMenuItem.isVisible = false
322-
}
323-
}
324-
325-
MenuItemCompat.setTooltipText(
326-
menuItem,
327-
getString(R.string.feed_change_stream_visibility_state)
328-
)
329-
}
330-
331-
private fun updateToggleFutureItemsButton(menuItem: MenuItem) {
332-
menuItem.isChecked = showFutureItems
333-
menuItem.icon = AppCompatResources.getDrawable(
334-
requireContext(),
335-
if (showFutureItems) R.drawable.ic_history_future else R.drawable.ic_history
336-
)
337-
MenuItemCompat.setTooltipText(
338-
menuItem,
339-
getString(
340-
if (showFutureItems)
341-
R.string.feed_toggle_hide_future_items
342-
else
343-
R.string.feed_toggle_show_future_items
344-
)
345-
)
346-
}
347-
348314
// //////////////////////////////////////////////////////////////////////////
349315
// Handling
350316
// //////////////////////////////////////////////////////////////////////////

app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt

Lines changed: 54 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import androidx.lifecycle.viewmodel.viewModelFactory
1111
import androidx.preference.PreferenceManager
1212
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
1313
import io.reactivex.rxjava3.core.Flowable
14-
import io.reactivex.rxjava3.functions.Function5
14+
import io.reactivex.rxjava3.functions.Function6
1515
import io.reactivex.rxjava3.processors.BehaviorProcessor
1616
import io.reactivex.rxjava3.schedulers.Schedulers
1717
import org.schabi.newpipe.App
@@ -31,18 +31,24 @@ import java.util.concurrent.TimeUnit
3131
class FeedViewModel(
3232
private val application: Application,
3333
groupId: Long = FeedGroupEntity.GROUP_ALL_ID,
34-
initialStreamVisibility: StreamVisibilityStatus = StreamVisibilityStatus.DEFAULT,
34+
initialShowPlayedItems: Boolean = true,
35+
initialShowPartiallyPlayedItems: Boolean = true,
3536
initialShowFutureItems: Boolean = true
3637
) : ViewModel() {
3738
private val feedDatabaseManager = FeedDatabaseManager(application)
3839

39-
private val streamVisibilityState = BehaviorProcessor.create<StreamVisibilityStatus>()
40-
private val streamVisibilityStateFlowable = streamVisibilityState
41-
.startWithItem(initialStreamVisibility)
40+
private val showPlayedItems = BehaviorProcessor.create<Boolean>()
41+
private val showPlayedItemsFlowable = showPlayedItems
42+
.startWithItem(initialShowPlayedItems)
4243
.distinctUntilChanged()
4344

44-
private val toggleShowFutureItems = BehaviorProcessor.create<Boolean>()
45-
private val toggleShowFutureItemsFlowable = toggleShowFutureItems
45+
private val showPartiallyPlayedItems = BehaviorProcessor.create<Boolean>()
46+
private val showPartiallyPlayedItemsFlowable = showPartiallyPlayedItems
47+
.startWithItem(initialShowPartiallyPlayedItems)
48+
.distinctUntilChanged()
49+
50+
private val showFutureItems = BehaviorProcessor.create<Boolean>()
51+
private val showFutureItemsFlowable = showFutureItems
4652
.startWithItem(initialShowFutureItems)
4753
.distinctUntilChanged()
4854

@@ -52,35 +58,27 @@ class FeedViewModel(
5258
private var combineDisposable = Flowable
5359
.combineLatest(
5460
FeedEventManager.events(),
55-
streamVisibilityStateFlowable,
56-
toggleShowFutureItemsFlowable,
61+
showPlayedItemsFlowable,
62+
showPartiallyPlayedItemsFlowable,
63+
showFutureItemsFlowable,
5764
feedDatabaseManager.notLoadedCount(groupId),
5865
feedDatabaseManager.oldestSubscriptionUpdate(groupId),
5966

60-
Function5 { t1: FeedEventManager.Event, t2: StreamVisibilityStatus, t3: Boolean,
61-
t4: Long, t5: List<OffsetDateTime> ->
62-
return@Function5 CombineResultEventHolder(t1, t2, t3, t4, t5.firstOrNull())
67+
Function6 { t1: FeedEventManager.Event, t2: Boolean, t3: Boolean, t4: Boolean,
68+
t5: Long, t6: List<OffsetDateTime> ->
69+
return@Function6 CombineResultEventHolder(t1, t2, t3, t4, t5, t6.firstOrNull())
6370
}
6471
)
6572
.throttleLatest(DEFAULT_THROTTLE_TIMEOUT, TimeUnit.MILLISECONDS)
6673
.subscribeOn(Schedulers.io())
6774
.observeOn(Schedulers.io())
68-
.map { (event, showPlayedItems, showFutureItems, notLoadedCount, oldestUpdate) ->
69-
val streamItems = if (event is SuccessResultEvent || event is IdleEvent) {
75+
.map { (event, showPlayedItems, showPartiallyPlayedItems, showFutureItems, notLoadedCount, oldestUpdate) ->
76+
val streamItems = if (event is SuccessResultEvent || event is IdleEvent)
7077
feedDatabaseManager
71-
.getStreams(
72-
groupId,
73-
!(
74-
showPlayedItems == StreamVisibilityStatus.HIDE_WATCHED ||
75-
showPlayedItems == StreamVisibilityStatus.HIDE_PARTIALLY_WATCHED
76-
),
77-
showPlayedItems != StreamVisibilityStatus.HIDE_PARTIALLY_WATCHED,
78-
showFutureItems
79-
)
78+
.getStreams(groupId, showPlayedItems, showPartiallyPlayedItems, showFutureItems)
8079
.blockingGet(arrayListOf())
81-
} else {
80+
else
8281
arrayListOf()
83-
}
8482

8583
CombineResultDataHolder(event, streamItems, notLoadedCount, oldestUpdate)
8684
}
@@ -107,10 +105,11 @@ class FeedViewModel(
107105

108106
private data class CombineResultEventHolder(
109107
val t1: FeedEventManager.Event,
110-
val t2: StreamVisibilityStatus,
108+
val t2: Boolean,
111109
val t3: Boolean,
112-
val t4: Long,
113-
val t5: OffsetDateTime?
110+
val t4: Boolean,
111+
val t5: Long,
112+
val t6: OffsetDateTime?
114113
)
115114

116115
private data class CombineResultDataHolder(
@@ -120,23 +119,32 @@ class FeedViewModel(
120119
val t4: OffsetDateTime?
121120
)
122121

123-
fun changeVisibilityState(streamVisibilityStatus: StreamVisibilityStatus) {
124-
streamVisibilityState.onNext(streamVisibilityStatus)
122+
fun setShowPlayedItems(showPlayedItems: Boolean) {
123+
this.showPlayedItems.onNext(showPlayedItems)
125124
}
126125

127-
fun saveStreamVisibilityStateToPreferences(streamVisibilityStatus: StreamVisibilityStatus) =
126+
fun saveShowPlayedItemsToPreferences(showPlayedItems: Boolean) =
128127
PreferenceManager.getDefaultSharedPreferences(application).edit {
129-
this.putString(
130-
application.getString(R.string.feed_stream_visibility_state_key),
131-
streamVisibilityStatus.toString()
132-
)
128+
this.putBoolean(application.getString(R.string.feed_show_watched_items_key), showPlayedItems)
133129
this.apply()
134130
}
135131

136-
fun getItemsVisibilityFromPreferences() = getStreamVisibilityStateFromPreferences(application)
132+
fun getShowPlayedItemsFromPreferences() = getShowPlayedItemsFromPreferences(application)
137133

138-
fun toggleFutureItems(showFutureItems: Boolean) {
139-
toggleShowFutureItems.onNext(showFutureItems)
134+
fun setShowPartiallyPlayedItems(showPartiallyPlayedItems: Boolean) {
135+
this.showPartiallyPlayedItems.onNext(showPartiallyPlayedItems)
136+
}
137+
138+
fun saveShowPartiallyPlayedItemsToPreferences(showPartiallyPlayedItems: Boolean) =
139+
PreferenceManager.getDefaultSharedPreferences(application).edit {
140+
this.putBoolean(application.getString(R.string.feed_show_partially_watched_items_key), showPartiallyPlayedItems)
141+
this.apply()
142+
}
143+
144+
fun getShowPartiallyPlayedItemsFromPreferences() = getShowPartiallyPlayedItemsFromPreferences(application)
145+
146+
fun setShowFutureItems(showFutureItems: Boolean) {
147+
this.showFutureItems.onNext(showFutureItems)
140148
}
141149

142150
fun saveShowFutureItemsToPreferences(showFutureItems: Boolean) =
@@ -148,16 +156,13 @@ class FeedViewModel(
148156
fun getShowFutureItemsFromPreferences() = getShowFutureItemsFromPreferences(application)
149157

150158
companion object {
159+
private fun getShowPlayedItemsFromPreferences(context: Context) =
160+
PreferenceManager.getDefaultSharedPreferences(context)
161+
.getBoolean(context.getString(R.string.feed_show_watched_items_key), true)
151162

152-
private fun getStreamVisibilityStateFromPreferences(context: Context): StreamVisibilityStatus {
153-
val s = PreferenceManager.getDefaultSharedPreferences(context)
154-
.getString(
155-
context.getString(R.string.feed_stream_visibility_state_key),
156-
StreamVisibilityStatus.DEFAULT.toString()
157-
) ?: StreamVisibilityStatus.DEFAULT.toString()
158-
return StreamVisibilityStatus.valueOf(s)
159-
}
160-
163+
private fun getShowPartiallyPlayedItemsFromPreferences(context: Context) =
164+
PreferenceManager.getDefaultSharedPreferences(context)
165+
.getBoolean(context.getString(R.string.feed_show_partially_watched_items_key), true)
161166
private fun getShowFutureItemsFromPreferences(context: Context) =
162167
PreferenceManager.getDefaultSharedPreferences(context)
163168
.getBoolean(context.getString(R.string.feed_show_future_items_key), true)
@@ -167,7 +172,8 @@ class FeedViewModel(
167172
App.getApp(),
168173
groupId,
169174
// Read initial value from preferences
170-
getStreamVisibilityStateFromPreferences(context.applicationContext),
175+
getShowPlayedItemsFromPreferences(context.applicationContext),
176+
getShowPartiallyPlayedItemsFromPreferences(context.applicationContext),
171177
getShowFutureItemsFromPreferences(context.applicationContext)
172178
)
173179
}

app/src/main/java/org/schabi/newpipe/local/feed/StreamVisibilityStatus.kt

Lines changed: 0 additions & 5 deletions
This file was deleted.

app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public HistoryRecordManager(final Context context) {
8787
* Marks a stream item as watched such that it is hidden from the feed if watched videos are
8888
* hidden. Adds a history entry and updates the stream progress to 100%.
8989
*
90-
* @see FeedViewModel#changeVisibilityState
90+
* @see FeedViewModel#setShowPlayedItems
9191
* @param info the item to mark as watched
9292
* @return a Maybe containing the ID of the item if successful
9393
*/

app/src/main/res/menu/menu_feed_fragment.xml

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,9 @@
44

55
<item
66
android:id="@+id/menu_item_feed_toggle_played_items"
7-
android:checkable="false"
8-
android:checked="false"
7+
android:orderInCategory="2"
98
android:icon="@drawable/ic_visibility_on"
10-
android:title="@string/feed_change_stream_visibility_state"
11-
app:showAsAction="ifRoom">
12-
<menu>
13-
<item
14-
android:id="@+id/menu_item_feed_toggle_show_all_items"
15-
android:title="@string/feed_stream_visibility_show_all"/>
16-
<item
17-
android:id="@+id/menu_item_feed_toggle_show_played_items"
18-
android:title="@string/feed_stream_visibility_hide_watched"/>
19-
<item
20-
android:id="@+id/menu_item_feed_toggle_partially_played_items"
21-
android:title="@string/feed_stream_visibility_hide_partially_watched"/>
22-
</menu>
23-
</item>
24-
25-
<item
26-
android:id="@+id/menu_item_feed_toggle_future_items"
27-
android:orderInCategory="3"
28-
android:checkable="true"
29-
android:checked="true"
30-
android:icon="@drawable/ic_history_future"
31-
android:title="@string/feed_toggle_show_future_items"
9+
android:title="@string/feed_show_hide_streams"
3210
app:showAsAction="ifRoom" />
3311

3412
<item

0 commit comments

Comments
 (0)