diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt b/app/src/main/java/org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt index ce74678ca77..a6c5fa68628 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt +++ b/app/src/main/java/org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt @@ -9,13 +9,14 @@ package org.schabi.newpipe.database.stream import androidx.room.ColumnInfo import androidx.room.Embedded import androidx.room.Ignore -import java.time.OffsetDateTime import org.schabi.newpipe.database.LocalItem import org.schabi.newpipe.database.history.model.StreamHistoryEntity import org.schabi.newpipe.database.stream.model.StreamEntity +import org.schabi.newpipe.database.stream.model.StreamStateEntity.Companion.PLAYBACK_FINISHED_END_MILLISECONDS import org.schabi.newpipe.database.stream.model.StreamStateEntity.Companion.STREAM_PROGRESS_MILLIS import org.schabi.newpipe.extractor.stream.StreamInfoItem import org.schabi.newpipe.util.image.ImageStrategy +import java.time.OffsetDateTime data class StreamStatisticsEntry( @Embedded @@ -52,6 +53,20 @@ data class StreamStatisticsEntry( } } + /** + * The video will be considered as finished, if the time left is less than + * [PLAYBACK_FINISHED_END_MILLISECONDS] and the progress is at least 3/4 of the video length. + * The state will be saved anyway, so that it can be shown under stream info items, but the + * player will not resume if a state is considered as finished. Finished streams are also the + * ones that can be filtered out in the feed fragment. + * @return whether the stream is finished or not + */ + fun isFinished(): Boolean { + val durationInSeconds = streamEntity.duration + return progressMillis >= durationInSeconds * 1000 - PLAYBACK_FINISHED_END_MILLISECONDS && + progressMillis >= durationInSeconds * 1000 * 3 / 4 + } + companion object { const val STREAM_LATEST_DATE = "latestAccess" const val STREAM_WATCH_COUNT = "watchCount" diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index 43b7f1c0db2..89b623cd974 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -57,6 +57,7 @@ public class StatisticsPlaylistFragment @State Parcelable itemsListState; private StatisticSortMode sortMode = StatisticSortMode.LAST_PLAYED; + private boolean includeFullyWatched = true; private StatisticPlaylistControlBinding headerBinding; private PlaylistControlBinding playlistControlBinding; @@ -78,6 +79,14 @@ private List processResult(final List !e.isFinished()) + .toList(); + } + return results; } @@ -277,6 +286,8 @@ public void handleResult(@NonNull final List result) { PlayButtonHelper.initPlaylistControlClickListener(activity, playlistControlBinding, this); headerBinding.sortButton.setOnClickListener(view -> toggleSortMode()); + headerBinding.fullyWatchedFilterButtonCheckBox + .setOnClickListener(view -> toggleIncludeFullyWatched()); hideLoading(); } @@ -313,6 +324,11 @@ private void toggleSortMode() { startLoading(true); } + private void toggleIncludeFullyWatched() { + includeFullyWatched = !includeFullyWatched; + startLoading(true); + } + private PlayQueue getPlayQueueStartingAt(final StreamStatisticsEntry infoItem) { return getPlayQueue(Math.max(itemListAdapter.getItemsList().indexOf(infoItem), 0)); } diff --git a/app/src/main/res/layout/statistic_playlist_control.xml b/app/src/main/res/layout/statistic_playlist_control.xml index 36540d32e91..f4be9557d05 100644 --- a/app/src/main/res/layout/statistic_playlist_control.xml +++ b/app/src/main/res/layout/statistic_playlist_control.xml @@ -5,37 +5,74 @@ android:layout_height="wrap_content" android:orientation="vertical"> - - - - - - + android:baselineAligned="false" + android:orientation="horizontal"> + + + + + + + + + + + + + + + + HTTP error 403 received from server while playing, likely caused by an IP ban or streaming URL deobfuscation issues %1$s refused to provide data, asking for a login to confirm the requester is not a bot.\n\nYour IP might have been temporarily banned by %1$s, you can wait some time or switch to a different IP (for example by turning on/off a VPN, or by switching from WiFi to mobile data). This content is not available for the currently selected content country.\n\nChange your selection from \"Settings > Content > Default content country\". + Hide Watched