mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-30 06:43:00 +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:
		| @@ -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' | ||||
|         ) | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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()); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Stypox
					Stypox