From 374001a1632aa06ce3ba877d96e51049969c8628 Mon Sep 17 00:00:00 2001 From: nixos script Date: Sun, 29 Oct 2023 09:58:34 +0800 Subject: [PATCH 1/3] remove picture availability for cached dearrow videos to improve performance remove private videos from video feeds make the player stop in case a video can't be retrieved to avoid crashing the whole app --- lib/player/states/player.dart | 80 +++++++++++++++------------- lib/utils/video_post_processing.dart | 4 +- lib/videos/models/dearrow.dart | 13 +++-- 3 files changed, 52 insertions(+), 45 deletions(-) diff --git a/lib/player/states/player.dart b/lib/player/states/player.dart index 7c3a0d49..c6c48f37 100644 --- a/lib/player/states/player.dart +++ b/lib/player/states/player.dart @@ -416,55 +416,61 @@ class PlayerCubit extends Cubit { } _switchToVideo(IdedVideo video, {Duration? startAt}) async { - // we move the existing video to the stack of played video + try { + // we move the existing video to the stack of played video - bool isOffline = video is DownloadedVideo; - // we want to switch to audio mode as soon as we can to prevent problems when switching from audio to video or the other way - if (isOffline) { - setAudio(video.audioOnly); - } + bool isOffline = video is DownloadedVideo; + // we want to switch to audio mode as soon as we can to prevent problems when switching from audio to video or the other way + if (isOffline) { + setAudio(video.audioOnly); + } - var state = this.state.copyWith(); + var state = this.state.copyWith(); - state.mediaEvent = MediaEvent(state: MediaState.loading); + state.mediaEvent = MediaEvent(state: MediaState.loading); - if (isOffline) { - state.videos = []; - state.currentlyPlaying = null; - } else { - state.offlineVideos = []; - state.offlineCurrentlyPlaying = null; - } + if (isOffline) { + state.videos = []; + state.currentlyPlaying = null; + } else { + state.offlineVideos = []; + state.offlineCurrentlyPlaying = null; + } - List toCheck = isOffline ? state.offlineVideos : state.videos; + List toCheck = isOffline ? state.offlineVideos : state.videos; - emit(state); - state = this.state.copyWith(); + emit(state); + state = this.state.copyWith(); - if (!isOffline) { - late Video v; - if (video is Video) { - v = video; + if (!isOffline) { + late Video v; + if (video is Video) { + v = video; + } else { + v = await service.getVideo(video.videoId); + } + state.currentlyPlaying = v; + state.mediaCommand = MediaCommand(MediaCommandType.switchVideo, value: SwitchVideoValue(video: v, startAt: startAt)); } else { - v = await service.getVideo(video.videoId); + state.offlineCurrentlyPlaying = video; + state.mediaCommand = MediaCommand(MediaCommandType.switchToOfflineVideo, value: video); } - state.currentlyPlaying = v; - state.mediaCommand = MediaCommand(MediaCommandType.switchVideo, value: SwitchVideoValue(video: v, startAt: startAt)); - } else { - state.offlineCurrentlyPlaying = video; - state.mediaCommand = MediaCommand(MediaCommandType.switchToOfflineVideo, value: video); - } - state.position = Duration.zero; - state.forwardStep = defaultStep; - state.rewindStep = defaultStep; + state.position = Duration.zero; + state.forwardStep = defaultStep; + state.rewindStep = defaultStep; - emit(state); + emit(state); - setSponsorBlock(); + setSponsorBlock(); - if (!isTv) { - mediaHandler.skipToQueueItem(currentIndex); + if (!isTv) { + mediaHandler.skipToQueueItem(currentIndex); + } + } catch (err) { + // if we can't get video details, we need to stop everything + log.severe("Couldn't play video '${video.videoId}', stopping player to avoid app crash"); + hide(); } } @@ -560,7 +566,7 @@ class PlayerCubit extends Cubit { var movedItem = listToUpdate.removeAt(oldItemIndex); listToUpdate.insert(newItemIndex, movedItem); log.fine('Reordered list: $oldItemIndex new index: ${listToUpdate.indexOf(movedItem)}'); - if(newItemIndex <= currentIndex){ + if (newItemIndex <= currentIndex) { state.playedVideos.add(listToUpdate[newItemIndex].videoId); } /* diff --git a/lib/utils/video_post_processing.dart b/lib/utils/video_post_processing.dart index d0fc60ff..f7045ca1 100644 --- a/lib/utils/video_post_processing.dart +++ b/lib/utils/video_post_processing.dart @@ -6,11 +6,13 @@ import 'package:logging/logging.dart'; import '../videos/models/base_video.dart'; var log = Logger('Video post process'); +const privateVideoString = "[Private video]"; Future> postProcessVideos(List toProcess) async { try { int start = DateTime.now().millisecondsSinceEpoch; - List videos = toProcess ?? []; + List videos = toProcess.where((element) => element.title != privateVideoString).toList() ?? []; + videos = await VideoFilter.filterVideos(videos); videos = await DeArrow.processVideos(videos); diff --git a/lib/videos/models/dearrow.dart b/lib/videos/models/dearrow.dart index 84feb493..12df2726 100644 --- a/lib/videos/models/dearrow.dart +++ b/lib/videos/models/dearrow.dart @@ -50,13 +50,12 @@ class DeArrow { if (!doThumbnails) return; if (cache.url != null) { - - bool isThumbnailAvailable = await service.testDeArrowThumbnail(cache.url); - if (isThumbnailAvailable) { - video.deArrowThumbnailUrl = cache.url; - // if we've set both things from cache, we stop otherwise we go through normal process - return; - } + // bool isThumbnailAvailable = await service.testDeArrowThumbnail(cache.url); + // if (isThumbnailAvailable) { + video.deArrowThumbnailUrl = cache.url; + // if we've set both things from cache, we stop otherwise we go through normal process + return; + // } } } From a72be481fe297cd9a68b34fe05b040b8ff25ccfa Mon Sep 17 00:00:00 2001 From: nixos script Date: Sun, 29 Oct 2023 11:56:13 +0800 Subject: [PATCH 2/3] fix #346 issue when sponsorblock is enabled, videos would not skip the next one in a playlist fix #348 issue where manually selecting a video in video queue and playing next would not skip to the next one but to what should have been next before manually selecting the video --- lib/player/states/player.dart | 119 ++++++++++++------- lib/player/views/components/video_queue.dart | 4 +- 2 files changed, 77 insertions(+), 46 deletions(-) diff --git a/lib/player/states/player.dart b/lib/player/states/player.dart index c6c48f37..b21770c8 100644 --- a/lib/player/states/player.dart +++ b/lib/player/states/player.dart @@ -317,38 +317,40 @@ class PlayerCubit extends Cubit { } } - playNext() { - EasyThrottle.throttle(skipToVideoThrottleName, const Duration(seconds: 1), () async { - if (settings.state.playerRepeatMode == PlayerRepeat.repeatOne) { - seek(Duration.zero); - play(); - } else if (state.videos.isNotEmpty || state.offlineVideos.isNotEmpty) { - //moving current video to played list - String? currentVideoId = state.currentlyPlaying?.videoId ?? state.offlineCurrentlyPlaying?.videoId; - if (currentVideoId != null) { - // state.playedVideos.remove(currentVideoId); - state.playedVideos.add(currentVideoId); - } + _playNextNow() async { + if (settings.state.playerRepeatMode == PlayerRepeat.repeatOne) { + seek(Duration.zero); + play(); + } else if (state.videos.isNotEmpty || state.offlineVideos.isNotEmpty) { + //moving current video to played list + String? currentVideoId = state.currentlyPlaying?.videoId ?? state.offlineCurrentlyPlaying?.videoId; + if (currentVideoId != null) { + // state.playedVideos.remove(currentVideoId); + state.playedVideos.add(currentVideoId); + } - if (state.playQueue.isNotEmpty) { - String toPlay = state.playQueue.removeFirst(); - if (state.videos.isNotEmpty) { - await switchToVideo(state.videos.firstWhere((element) => element.videoId == toPlay)); - } else { - await switchToOfflineVideo(state.offlineVideos.firstWhere((element) => element.videoId == toPlay)); - } - } else if (settings.state.playerRepeatMode == PlayerRepeat.repeatAll) { - state.playedVideos = []; - state.playQueue = ListQueue.from([]); - if (state.videos.isNotEmpty) { - await switchToVideo(state.videos[0]); - } else { - await switchToOfflineVideo(state.offlineVideos[0]); - } - generatePlayQueue(); + if (state.playQueue.isNotEmpty) { + String toPlay = state.playQueue.removeFirst(); + if (state.videos.isNotEmpty) { + await switchToVideo(state.videos.firstWhere((element) => element.videoId == toPlay)); + } else { + await switchToOfflineVideo(state.offlineVideos.firstWhere((element) => element.videoId == toPlay)); + } + } else if (settings.state.playerRepeatMode == PlayerRepeat.repeatAll) { + state.playedVideos = []; + state.playQueue = ListQueue.from([]); + if (state.videos.isNotEmpty) { + await switchToVideo(state.videos[0]); + } else { + await switchToOfflineVideo(state.offlineVideos[0]); } + generatePlayQueue(); } - }); + } + } + + playNext() { + EasyThrottle.throttle(skipToVideoThrottleName, const Duration(seconds: 1), _playNextNow); } playPrevious() { @@ -415,7 +417,33 @@ class PlayerCubit extends Cubit { } } + /// skip to queue video of index + /// if we're not shuffling, we also rebuild the playnext and played previously queue + skipToVideo(int index) { + if (index < 0 || index >= state.videos.length) { + return; + } + + if (settings.state.playerShuffleMode) { + } else { + List played = []; + List playNext = []; + for (int i = 0; i < state.videos.length; i++) { + var v = state.videos[i]; + if (i < index) { + played.add(v.videoId); + } else if (i > index) { + playNext.add(v.videoId); + } + } + emit(state.copyWith(playedVideos: played, playQueue: ListQueue.from(playNext))); + } + switchToVideo(state.videos[index]); + } + + /// Switches to a video without changing the queue _switchToVideo(IdedVideo video, {Duration? startAt}) async { + var state = this.state.copyWith(); try { // we move the existing video to the stack of played video @@ -425,7 +453,6 @@ class PlayerCubit extends Cubit { setAudio(video.audioOnly); } - var state = this.state.copyWith(); state.mediaEvent = MediaEvent(state: MediaState.loading); @@ -462,15 +489,24 @@ class PlayerCubit extends Cubit { emit(state); - setSponsorBlock(); + await setSponsorBlock(); if (!isTv) { mediaHandler.skipToQueueItem(currentIndex); } } catch (err) { - // if we can't get video details, we need to stop everything - log.severe("Couldn't play video '${video.videoId}', stopping player to avoid app crash"); - hide(); + emit(state); + if(state.videos.length == 1) { + // if we can't get video details, we need to stop everything + log.severe("Couldn't play video '${video.videoId}', stopping player to avoid app crash"); + hide(); + }else{ + // if we have more than 1 video + log.severe("Couldn't play video '${video.videoId}', removing it from the queue"); + + removeVideoFromQueue(video.videoId); + _playNextNow(); + } } } @@ -595,7 +631,7 @@ class PlayerCubit extends Cubit { } setSponsorBlock() async { - var state = this.state.copyWith(); + List> newSegments = []; if (state.currentlyPlaying != null) { List types = SponsorSegmentType.values.where((e) => db.getSettings(e.settingsName())?.value == 'true').toList(); @@ -608,15 +644,11 @@ class PlayerCubit extends Cubit { return segment; })); - state.sponsorSegments = segments; + newSegments = segments; log.fine('we found ${segments.length} segments to skip'); - } else { - state.sponsorSegments = []; } - } else { - state.sponsorSegments = []; } - emit(state); + emit(state.copyWith(sponsorSegments: newSegments)); } seek(Duration duration) { @@ -755,9 +787,8 @@ class PlayerCubit extends Cubit { videos.shuffle(); } - state.playQueue = ListQueue.from(videos); - - // set up the queue + ListQueue playQueue = ListQueue.from(videos); + emit(state.copyWith(playQueue: playQueue)); } } diff --git a/lib/player/views/components/video_queue.dart b/lib/player/views/components/video_queue.dart index c4fb712a..967efff2 100644 --- a/lib/player/views/components/video_queue.dart +++ b/lib/player/views/components/video_queue.dart @@ -34,7 +34,7 @@ class VideoQueue extends StatelessWidget { )) ], child: CompactVideo( - onTap: isPlaying ? () {} : () => controller.switchToVideo(video), + onTap: isPlaying ? () {} : () => controller.skipToVideo(index), video: video, highlighted: isPlaying, ), @@ -65,7 +65,7 @@ class VideoQueue extends StatelessWidget { )) ], child: CompactVideo( - onTap: isPlaying ? () {} : () => controller.switchToOfflineVideo(v), + onTap: isPlaying ? () {} : () => controller.skipToVideo(index), offlineVideo: v, highlighted: isPlaying, trailing: [ From fa67214d3f6bc9e51966f9ed311e83d0891e8096 Mon Sep 17 00:00:00 2001 From: nixos script Date: Sun, 29 Oct 2023 12:10:38 +0800 Subject: [PATCH 3/3] update version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index a07d94b8..865f605f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.17.0+4034 +version: 1.17.1+4035 environment: sdk: '>=3.0.0 <4.0.0'