Skip to content

Commit 2142f05

Browse files
committed
Fix hiding finished streams in groups; new stream state validity condition
Consider stream state valid also if >1/4 of video was watched
1 parent 0113ad5 commit 2142f05

3 files changed

Lines changed: 40 additions & 10 deletions

File tree

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ abstract class FeedDAO {
6464
)
6565
abstract fun getAllStreamsForGroup(groupId: Long): Flowable<List<StreamWithState>>
6666

67+
/**
68+
* @see StreamStateEntity.isFinished()
69+
* @see StreamStateEntity.PLAYBACK_FINISHED_END_MILLISECONDS
70+
* @return all of the non-live, never-played and non-finished streams in the feed
71+
* (all of the cited conditions must hold for a stream to be in the returned list)
72+
*/
6773
@Query(
6874
"""
6975
SELECT s.*, sst.progress_time
@@ -93,6 +99,13 @@ abstract class FeedDAO {
9399
)
94100
abstract fun getLiveOrNotPlayedStreams(): Flowable<List<StreamWithState>>
95101

102+
/**
103+
* @see StreamStateEntity.isFinished()
104+
* @see StreamStateEntity.PLAYBACK_FINISHED_END_MILLISECONDS
105+
* @param groupId the group id to get streams of
106+
* @return all of the non-live, never-played and non-finished streams for the given feed group
107+
* (all of the cited conditions must hold for a stream to be in the returned list)
108+
*/
96109
@Query(
97110
"""
98111
SELECT s.*, sst.progress_time
@@ -113,6 +126,9 @@ abstract class FeedDAO {
113126
WHERE fgs.group_id = :groupId
114127
AND (
115128
sh.stream_id IS NULL
129+
OR sst.stream_id IS NULL
130+
OR sst.progress_time < s.duration * 1000 - ${StreamStateEntity.PLAYBACK_FINISHED_END_MILLISECONDS}
131+
OR sst.progress_time < s.duration * 1000 * 3 / 4
116132
OR s.stream_type = 'LIVE_STREAM'
117133
OR s.stream_type = 'AUDIO_LIVE_STREAM'
118134
)

app/src/main/java/org/schabi/newpipe/database/stream/model/StreamStateEntity.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import androidx.room.Entity;
66
import androidx.room.ForeignKey;
77

8+
import java.util.Objects;
9+
810
import static androidx.room.ForeignKey.CASCADE;
911
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID;
1012
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE;
@@ -26,15 +28,18 @@ public class StreamStateEntity {
2628
public static final String STREAM_PROGRESS_MILLIS = "progress_time";
2729

2830
/**
29-
* Playback state will not be saved, if playback time is less than this threshold.
31+
* Playback state will not be saved, if playback time is less than this threshold (5000ms = 5s).
3032
*/
31-
private static final long PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS = 5000; // 5000ms = 5s
33+
private static final long PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS = 5000;
3234

3335
/**
36+
* Stream will be considered finished if the playback time left exceeds this threshold
37+
* (60000ms = 60s).
3438
* @see #isFinished(long)
3539
* @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreams()
40+
* @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreamsForGroup(long)
3641
*/
37-
public static final long PLAYBACK_FINISHED_END_MILLISECONDS = 60000; // 60000ms = 60s
42+
public static final long PLAYBACK_FINISHED_END_MILLISECONDS = 60000;
3843

3944
@ColumnInfo(name = JOIN_STREAM_ID)
4045
private long streamUid;
@@ -65,11 +70,13 @@ public void setProgressMillis(final long progressMillis) {
6570

6671
/**
6772
* The state will be considered valid, and thus be saved, if the progress is more than {@link
68-
* #PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS}.
73+
* #PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS} or at least 1/4 of the video length.
74+
* @param durationInSeconds the duration of the stream connected with this state, in seconds
6975
* @return whether this stream state entity should be saved or not
7076
*/
71-
public boolean isValid() {
72-
return progressMillis > PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS;
77+
public boolean isValid(final long durationInSeconds) {
78+
return progressMillis > PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS
79+
|| progressMillis > durationInSeconds * 1000 / 4;
7380
}
7481

7582
/**
@@ -78,6 +85,8 @@ public boolean isValid() {
7885
* The state will be saved anyway, so that it can be shown under stream info items, but the
7986
* player will not resume if a state is considered as finished. Finished streams are also the
8087
* ones that can be filtered out in the feed fragment.
88+
* @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreams()
89+
* @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreamsForGroup(long)
8190
* @param durationInSeconds the duration of the stream connected with this state, in seconds
8291
* @return whether the stream is finished or not
8392
*/
@@ -95,4 +104,9 @@ public boolean equals(@Nullable final Object obj) {
95104
return false;
96105
}
97106
}
107+
108+
@Override
109+
public int hashCode() {
110+
return Objects.hash(streamUid, progressMillis);
111+
}
98112
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,11 @@ public Maybe<StreamHistoryEntity> getStreamHistory(final StreamInfo info) {
211211

212212
public Maybe<StreamStateEntity> loadStreamState(final PlayQueueItem queueItem) {
213213
return queueItem.getStream()
214-
.map((info) -> streamTable.upsert(new StreamEntity(info)))
214+
.map(info -> streamTable.upsert(new StreamEntity(info)))
215215
.flatMapPublisher(streamStateTable::getState)
216216
.firstElement()
217217
.flatMap(list -> list.isEmpty() ? Maybe.empty() : Maybe.just(list.get(0)))
218-
.filter(StreamStateEntity::isValid)
218+
.filter(state -> state.isValid(queueItem.getDuration()))
219219
.subscribeOn(Schedulers.io());
220220
}
221221

@@ -224,15 +224,15 @@ public Maybe<StreamStateEntity> loadStreamState(final StreamInfo info) {
224224
.flatMapPublisher(streamStateTable::getState)
225225
.firstElement()
226226
.flatMap(list -> list.isEmpty() ? Maybe.empty() : Maybe.just(list.get(0)))
227-
.filter(StreamStateEntity::isValid)
227+
.filter(state -> state.isValid(info.getDuration()))
228228
.subscribeOn(Schedulers.io());
229229
}
230230

231231
public Completable saveStreamState(@NonNull final StreamInfo info, final long progressMillis) {
232232
return Completable.fromAction(() -> database.runInTransaction(() -> {
233233
final long streamId = streamTable.upsert(new StreamEntity(info));
234234
final StreamStateEntity state = new StreamStateEntity(streamId, progressMillis);
235-
if (state.isValid()) {
235+
if (state.isValid(info.getDuration())) {
236236
streamStateTable.upsert(state);
237237
}
238238
})).subscribeOn(Schedulers.io());

0 commit comments

Comments
 (0)