From d414c2789a80d40f38b178bb3c9748f8a8c3a61f Mon Sep 17 00:00:00 2001 From: mertalev <101130780+mertalev@users.noreply.github.com> Date: Sun, 1 Dec 2024 02:30:04 -0500 Subject: [PATCH] fix looping --- .../common/native_video_viewer.page.dart | 91 +++++++++---------- .../video_player_controls_provider.dart | 3 + .../custom_video_player_controls.dart | 4 +- mobile/pubspec.lock | 4 +- mobile/pubspec.yaml | 2 +- 5 files changed, 52 insertions(+), 52 deletions(-) diff --git a/mobile/lib/pages/common/native_video_viewer.page.dart b/mobile/lib/pages/common/native_video_viewer.page.dart index 2a072dd35a..c8696dc22c 100644 --- a/mobile/lib/pages/common/native_video_viewer.page.dart +++ b/mobile/lib/pages/common/native_video_viewer.page.dart @@ -37,11 +37,6 @@ class NativeVideoViewerPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final loopVideo = ref.watch( - appSettingsServiceProvider.select( - (settings) => settings.getSetting(AppSettingsEnum.loopVideo), - ), - ); final controller = useState(null); final lastVideoPosition = useRef(-1); final isBuffering = useRef(false); @@ -186,28 +181,7 @@ class NativeVideoViewerPage extends HookConsumerWidget { interval: const Duration(milliseconds: 100), maxWaitTime: const Duration(milliseconds: 200), ); - ref.listen(videoPlayerControlsProvider.select((value) => value.position), - (_, position) async { - final playerController = controller.value; - if (playerController == null) { - return; - } - - final playbackInfo = playerController.playbackInfo; - if (playbackInfo == null) { - return; - } - - // Find the position to seek to - final seek = position ~/ 1; - if (seek != playbackInfo.position) { - seekDebouncer.run(() => playerController.seekTo(seek)); - } - }); - - // // When the custom video controls pause or play - ref.listen(videoPlayerControlsProvider.select((value) => value.pause), - (_, pause) async { + Future onPlayerControlsPlayChange(bool? _, bool pause) async { final videoController = controller.value; if (videoController == null || !context.mounted) { return; @@ -228,8 +202,39 @@ class NativeVideoViewerPage extends HookConsumerWidget { } catch (error) { log.severe('Error pausing or playing video: $error'); } + } + + ref.listen(videoPlayerControlsProvider.select((value) => value.position), + (_, position) { + final playerController = controller.value; + if (playerController == null) { + return; + } + + final playbackInfo = playerController.playbackInfo; + if (playbackInfo == null) { + return; + } + + // Find the position to seek to + final seek = position ~/ 1; + if (seek != playbackInfo.position) { + seekDebouncer.run(() => playerController.seekTo(seek)); + } + + if (Platform.isIOS && + seek == 0 && + !ref.read(videoPlayerControlsProvider.notifier).paused) { + onPlayerControlsPlayChange(null, false); + } }); + // // When the custom video controls pause or play + ref.listen( + videoPlayerControlsProvider.select((value) => value.pause), + onPlayerControlsPlayChange, + ); + void onPlaybackReady() async { final videoController = controller.value; if (videoController == null || !isCurrent || !context.mounted) { @@ -258,12 +263,6 @@ class NativeVideoViewerPage extends HookConsumerWidget { final videoPlayback = VideoPlaybackValue.fromNativeController(videoController); - // No need to update the UI when it's about to loop - if (videoPlayback.state == VideoPlaybackState.completed && loopVideo) { - return; - } - ref.read(videoPlaybackValueProvider.notifier).status = - videoPlayback.state; if (videoPlayback.state == VideoPlaybackState.playing) { // Sync with the controls playing WakelockPlus.enable(); @@ -271,6 +270,9 @@ class NativeVideoViewerPage extends HookConsumerWidget { // Sync with the controls pause WakelockPlus.disable(); } + + ref.read(videoPlaybackValueProvider.notifier).status = + videoPlayback.state; } void onPlaybackPositionChanged() { @@ -302,28 +304,16 @@ class NativeVideoViewerPage extends HookConsumerWidget { } } - void onPlaybackEnded() { - final videoController = controller.value; - if (videoController == null || !context.mounted) { - return; - } - - if (!loopVideo) { - WakelockPlus.disable(); - } - } - void removeListeners(NativeVideoPlayerController controller) { controller.onPlaybackPositionChanged .removeListener(onPlaybackPositionChanged); controller.onPlaybackStatusChanged .removeListener(onPlaybackStatusChanged); controller.onPlaybackReady.removeListener(onPlaybackReady); - controller.onPlaybackEnded.removeListener(onPlaybackEnded); } void initController(NativeVideoPlayerController nc) async { - if (controller.value != null) { + if (controller.value != null || !context.mounted) { return; } ref.read(videoPlayerControlsProvider.notifier).reset(); @@ -337,10 +327,15 @@ class NativeVideoViewerPage extends HookConsumerWidget { nc.onPlaybackPositionChanged.addListener(onPlaybackPositionChanged); nc.onPlaybackStatusChanged.addListener(onPlaybackStatusChanged); nc.onPlaybackReady.addListener(onPlaybackReady); - nc.onPlaybackEnded.addListener(onPlaybackEnded); + nc.loadVideoSource(source).catchError((error) { + log.severe('Error loading video source: $error'); + }); + final loopVideo = ref + .read(appSettingsServiceProvider) + .getSetting(AppSettingsEnum.loopVideo); nc.setLoop(loopVideo); - nc.loadVideoSource(source); + controller.value = nc; Timer(const Duration(milliseconds: 200), checkIfBuffering); } diff --git a/mobile/lib/providers/asset_viewer/video_player_controls_provider.dart b/mobile/lib/providers/asset_viewer/video_player_controls_provider.dart index 20f8fd7d2e..24ca9cb18e 100644 --- a/mobile/lib/providers/asset_viewer/video_player_controls_provider.dart +++ b/mobile/lib/providers/asset_viewer/video_player_controls_provider.dart @@ -1,4 +1,5 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart'; class VideoPlaybackControls { const VideoPlaybackControls({ @@ -40,6 +41,7 @@ class VideoPlayerControls extends StateNotifier { double get position => state.position; bool get mute => state.mute; + bool get paused => state.pause; set position(double value) { if (state.position == value) { @@ -111,5 +113,6 @@ class VideoPlayerControls extends StateNotifier { mute: state.mute, pause: false, ); + ref.read(videoPlaybackValueProvider.notifier).position = Duration.zero; } } diff --git a/mobile/lib/widgets/asset_viewer/custom_video_player_controls.dart b/mobile/lib/widgets/asset_viewer/custom_video_player_controls.dart index 3960ce2d67..a04936ae3d 100644 --- a/mobile/lib/widgets/asset_viewer/custom_video_player_controls.dart +++ b/mobile/lib/widgets/asset_viewer/custom_video_player_controls.dart @@ -34,7 +34,9 @@ class CustomVideoPlayerControls extends HookConsumerWidget { } // Do not hide on paused - if (state != VideoPlaybackState.paused && assetIsVideo) { + if (state != VideoPlaybackState.paused && + state != VideoPlaybackState.completed && + assetIsVideo) { ref.read(showControlsProvider.notifier).show = false; } }, diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index b5fe94c6b8..5062a3766f 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -1028,8 +1028,8 @@ packages: dependency: "direct main" description: path: "." - ref: "feat/exoplayer" - resolved-ref: "2139230b334b22b87de1dba47cc5632e5d172840" + ref: "68ea203" + resolved-ref: "68ea2030ba7aceb1bc44b683ff0b742fd1a52d2f" url: "https://github.com/immich-app/native_video_player" source: git version: "1.3.1" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 744260df07..07d5e4a7f5 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -67,7 +67,7 @@ dependencies: native_video_player: git: url: https://github.com/immich-app/native_video_player - ref: feat/exoplayer + ref: 68ea203 #image editing packages crop_image: ^1.0.13