Fix hiding finished streams in groups; new stream state validity condition

Consider stream state valid also if >1/4 of video was watched
This commit is contained in:
Stypox 2021-06-07 09:43:08 +02:00
parent 0113ad5e14
commit 2142f05a88
No known key found for this signature in database
GPG Key ID: 4BDF1B40A49FDD23
3 changed files with 40 additions and 10 deletions

View File

@ -64,6 +64,12 @@ abstract class FeedDAO {
)
abstract fun getAllStreamsForGroup(groupId: Long): Flowable<List<StreamWithState>>
/**
* @see StreamStateEntity.isFinished()
* @see StreamStateEntity.PLAYBACK_FINISHED_END_MILLISECONDS
* @return all of the non-live, never-played and non-finished streams in the feed
* (all of the cited conditions must hold for a stream to be in the returned list)
*/
@Query(
"""
SELECT s.*, sst.progress_time
@ -93,6 +99,13 @@ abstract class FeedDAO {
)
abstract fun getLiveOrNotPlayedStreams(): Flowable<List<StreamWithState>>
/**
* @see StreamStateEntity.isFinished()
* @see StreamStateEntity.PLAYBACK_FINISHED_END_MILLISECONDS
* @param groupId the group id to get streams of
* @return all of the non-live, never-played and non-finished streams for the given feed group
* (all of the cited conditions must hold for a stream to be in the returned list)
*/
@Query(
"""
SELECT s.*, sst.progress_time
@ -113,6 +126,9 @@ abstract class FeedDAO {
WHERE fgs.group_id = :groupId
AND (
sh.stream_id IS NULL
OR sst.stream_id IS NULL
OR sst.progress_time < s.duration * 1000 - ${StreamStateEntity.PLAYBACK_FINISHED_END_MILLISECONDS}
OR sst.progress_time < s.duration * 1000 * 3 / 4
OR s.stream_type = 'LIVE_STREAM'
OR s.stream_type = 'AUDIO_LIVE_STREAM'
)

View File

@ -5,6 +5,8 @@ import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.ForeignKey;
import java.util.Objects;
import static androidx.room.ForeignKey.CASCADE;
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID;
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE;
@ -26,15 +28,18 @@ public class StreamStateEntity {
public static final String STREAM_PROGRESS_MILLIS = "progress_time";
/**
* Playback state will not be saved, if playback time is less than this threshold.
* Playback state will not be saved, if playback time is less than this threshold (5000ms = 5s).
*/
private static final long PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS = 5000; // 5000ms = 5s
private static final long PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS = 5000;
/**
* Stream will be considered finished if the playback time left exceeds this threshold
* (60000ms = 60s).
* @see #isFinished(long)
* @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreams()
* @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreamsForGroup(long)
*/
public static final long PLAYBACK_FINISHED_END_MILLISECONDS = 60000; // 60000ms = 60s
public static final long PLAYBACK_FINISHED_END_MILLISECONDS = 60000;
@ColumnInfo(name = JOIN_STREAM_ID)
private long streamUid;
@ -65,11 +70,13 @@ public class StreamStateEntity {
/**
* The state will be considered valid, and thus be saved, if the progress is more than {@link
* #PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS}.
* #PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS} or at least 1/4 of the video length.
* @param durationInSeconds the duration of the stream connected with this state, in seconds
* @return whether this stream state entity should be saved or not
*/
public boolean isValid() {
return progressMillis > PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS;
public boolean isValid(final long durationInSeconds) {
return progressMillis > PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS
|| progressMillis > durationInSeconds * 1000 / 4;
}
/**
@ -78,6 +85,8 @@ public class StreamStateEntity {
* 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.
* @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreams()
* @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreamsForGroup(long)
* @param durationInSeconds the duration of the stream connected with this state, in seconds
* @return whether the stream is finished or not
*/
@ -95,4 +104,9 @@ public class StreamStateEntity {
return false;
}
}
@Override
public int hashCode() {
return Objects.hash(streamUid, progressMillis);
}
}

View File

@ -211,11 +211,11 @@ public class HistoryRecordManager {
public Maybe<StreamStateEntity> loadStreamState(final PlayQueueItem queueItem) {
return queueItem.getStream()
.map((info) -> streamTable.upsert(new StreamEntity(info)))
.map(info -> streamTable.upsert(new StreamEntity(info)))
.flatMapPublisher(streamStateTable::getState)
.firstElement()
.flatMap(list -> list.isEmpty() ? Maybe.empty() : Maybe.just(list.get(0)))
.filter(StreamStateEntity::isValid)
.filter(state -> state.isValid(queueItem.getDuration()))
.subscribeOn(Schedulers.io());
}
@ -224,7 +224,7 @@ public class HistoryRecordManager {
.flatMapPublisher(streamStateTable::getState)
.firstElement()
.flatMap(list -> list.isEmpty() ? Maybe.empty() : Maybe.just(list.get(0)))
.filter(StreamStateEntity::isValid)
.filter(state -> state.isValid(info.getDuration()))
.subscribeOn(Schedulers.io());
}
@ -232,7 +232,7 @@ public class HistoryRecordManager {
return Completable.fromAction(() -> database.runInTransaction(() -> {
final long streamId = streamTable.upsert(new StreamEntity(info));
final StreamStateEntity state = new StreamStateEntity(streamId, progressMillis);
if (state.isValid()) {
if (state.isValid(info.getDuration())) {
streamStateTable.upsert(state);
}
})).subscribeOn(Schedulers.io());