1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2024-12-23 08:30:44 +00:00

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>> 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( @Query(
""" """
SELECT s.*, sst.progress_time SELECT s.*, sst.progress_time
@ -93,6 +99,13 @@ abstract class FeedDAO {
) )
abstract fun getLiveOrNotPlayedStreams(): Flowable<List<StreamWithState>> 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( @Query(
""" """
SELECT s.*, sst.progress_time SELECT s.*, sst.progress_time
@ -113,6 +126,9 @@ abstract class FeedDAO {
WHERE fgs.group_id = :groupId WHERE fgs.group_id = :groupId
AND ( AND (
sh.stream_id IS NULL 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 = 'LIVE_STREAM'
OR s.stream_type = 'AUDIO_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.Entity;
import androidx.room.ForeignKey; import androidx.room.ForeignKey;
import java.util.Objects;
import static androidx.room.ForeignKey.CASCADE; 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.JOIN_STREAM_ID;
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE; 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"; 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 #isFinished(long)
* @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreams() * @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) @ColumnInfo(name = JOIN_STREAM_ID)
private long streamUid; 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 * 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 * @return whether this stream state entity should be saved or not
*/ */
public boolean isValid() { public boolean isValid(final long durationInSeconds) {
return progressMillis > PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS; 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 * 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 * 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. * 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 * @param durationInSeconds the duration of the stream connected with this state, in seconds
* @return whether the stream is finished or not * @return whether the stream is finished or not
*/ */
@ -95,4 +104,9 @@ public class StreamStateEntity {
return false; 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) { public Maybe<StreamStateEntity> loadStreamState(final PlayQueueItem queueItem) {
return queueItem.getStream() return queueItem.getStream()
.map((info) -> streamTable.upsert(new StreamEntity(info))) .map(info -> streamTable.upsert(new StreamEntity(info)))
.flatMapPublisher(streamStateTable::getState) .flatMapPublisher(streamStateTable::getState)
.firstElement() .firstElement()
.flatMap(list -> list.isEmpty() ? Maybe.empty() : Maybe.just(list.get(0))) .flatMap(list -> list.isEmpty() ? Maybe.empty() : Maybe.just(list.get(0)))
.filter(StreamStateEntity::isValid) .filter(state -> state.isValid(queueItem.getDuration()))
.subscribeOn(Schedulers.io()); .subscribeOn(Schedulers.io());
} }
@ -224,7 +224,7 @@ public class HistoryRecordManager {
.flatMapPublisher(streamStateTable::getState) .flatMapPublisher(streamStateTable::getState)
.firstElement() .firstElement()
.flatMap(list -> list.isEmpty() ? Maybe.empty() : Maybe.just(list.get(0))) .flatMap(list -> list.isEmpty() ? Maybe.empty() : Maybe.just(list.get(0)))
.filter(StreamStateEntity::isValid) .filter(state -> state.isValid(info.getDuration()))
.subscribeOn(Schedulers.io()); .subscribeOn(Schedulers.io());
} }
@ -232,7 +232,7 @@ public class HistoryRecordManager {
return Completable.fromAction(() -> database.runInTransaction(() -> { return Completable.fromAction(() -> database.runInTransaction(() -> {
final long streamId = streamTable.upsert(new StreamEntity(info)); final long streamId = streamTable.upsert(new StreamEntity(info));
final StreamStateEntity state = new StreamStateEntity(streamId, progressMillis); final StreamStateEntity state = new StreamStateEntity(streamId, progressMillis);
if (state.isValid()) { if (state.isValid(info.getDuration())) {
streamStateTable.upsert(state); streamStateTable.upsert(state);
} }
})).subscribeOn(Schedulers.io()); })).subscribeOn(Schedulers.io());