diff --git a/mobile/lib/pages/common/native_video_loader.dart b/mobile/lib/pages/common/native_video_loader.dart index 91927ac530..d6c857a5d2 100644 --- a/mobile/lib/pages/common/native_video_loader.dart +++ b/mobile/lib/pages/common/native_video_loader.dart @@ -33,25 +33,28 @@ class NativeVideoLoader extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final log = Logger('NativeVideoLoader'); + log.info('Building NativeVideoLoader'); // fast path for aspect ratio - final initAspectRatio = useMemoized( - () { - if (asset.exifInfo == null) { - return null; - } + // final initAspectRatio = useMemoized( + // () { + // if (asset.exifInfo == null) { + // return null; + // } - final width = asset.orientatedWidth?.toDouble(); - final height = asset.orientatedHeight?.toDouble(); - return width != null && height != null && width > 0 && height > 0 - ? width / height - : null; - }, - ); + // final width = asset.orientatedWidth?.toDouble(); + // final height = asset.orientatedHeight?.toDouble(); + // return width != null && height != null && width > 0 && height > 0 + // ? width / height + // : null; + // }, + // ); final localEntity = useMemoized( - () => asset.localId != null ? AssetEntity.fromId(asset.localId!) : null, + () => asset.isLocal ? AssetEntity.fromId(asset.localId!) : null, ); Future calculateAspectRatio() async { + log.info('Calculating aspect ratio'); late final double? orientatedWidth; late final double? orientatedHeight; @@ -68,6 +71,7 @@ class NativeVideoLoader extends HookConsumerWidget { orientatedHeight = entity.orientatedHeight?.toDouble(); } + log.info('Calculated aspect ratio'); if (orientatedWidth != null && orientatedHeight != null && orientatedWidth > 0 && @@ -78,12 +82,7 @@ class NativeVideoLoader extends HookConsumerWidget { return 1.0; } - final aspectRatioFuture = useMemoized( - () => initAspectRatio == null ? calculateAspectRatio() : null, - ); - - final log = Logger('NativeVideoLoader'); - log.info('Building NativeVideoLoader'); + final aspectRatioFuture = useMemoized(() => calculateAspectRatio()); Future createLocalSource() async { log.info('Loading video from local storage'); @@ -97,10 +96,12 @@ class NativeVideoLoader extends HookConsumerWidget { throw Exception('No file found for the video'); } - return await VideoSource.init( + final source = await VideoSource.init( path: file.path, type: VideoSourceType.file, ); + log.info('Loaded video from local storage'); + return source; } Future createRemoteSource() async { @@ -112,14 +113,16 @@ class NativeVideoLoader extends HookConsumerWidget { ? '$serverEndpoint/assets/${asset.livePhotoVideoId}/video/playback' : '$serverEndpoint/assets/${asset.remoteId}/video/playback'; - return await VideoSource.init( + final source = await VideoSource.init( path: videoUrl, type: VideoSourceType.network, headers: ApiService.getRequestHeaders(), ); + log.info('Loaded video from server'); + return source; } - Future createSource(Asset asset) async { + Future createSource() { if (asset.isLocal && asset.livePhotoVideoId == null) { return createLocalSource(); } @@ -127,6 +130,16 @@ class NativeVideoLoader extends HookConsumerWidget { return createRemoteSource(); } + final createSourceFuture = useMemoized(() => createSource()); + + final combinedFuture = useMemoized( + () async { + final aspectRatio = await aspectRatioFuture; + final source = await createSourceFuture; + return (source, aspectRatio); + }, + ); + final size = MediaQuery.sizeOf(context); return SizedBox( @@ -143,18 +156,17 @@ class NativeVideoLoader extends HookConsumerWidget { width: size.width, child: FutureBuilder( key: ValueKey(asset.id), - future: aspectRatioFuture, - initialData: initAspectRatio, + future: combinedFuture, + // initialData: initAspectRatio, builder: (context, snapshot) { if (!snapshot.hasData) { return placeholder; } return NativeVideoViewerPage( - key: ValueKey(asset.id), - videoSource: createSource(asset), + videoSource: snapshot.data!.$1, duration: asset.duration, - aspectRatio: snapshot.data as double, + aspectRatio: snapshot.data!.$2, isMotionVideo: isMotionVideo, hideControlsTimer: hideControlsTimer, loopVideo: loopVideo, diff --git a/mobile/lib/pages/common/native_video_viewer.page.dart b/mobile/lib/pages/common/native_video_viewer.page.dart index 478f084040..d3eefcde6a 100644 --- a/mobile/lib/pages/common/native_video_viewer.page.dart +++ b/mobile/lib/pages/common/native_video_viewer.page.dart @@ -30,7 +30,7 @@ import 'package:wakelock_plus/wakelock_plus.dart'; // } class NativeVideoViewerPage extends HookConsumerWidget { - final Future videoSource; + final VideoSource videoSource; final double aspectRatio; final Duration duration; final bool isMotionVideo; @@ -75,7 +75,7 @@ class NativeVideoViewerPage extends HookConsumerWidget { } // timer to mark videos as buffering if the position does not change - useInterval(const Duration(seconds: 5), checkIfBuffering); + // useInterval(const Duration(seconds: 5), checkIfBuffering); // When the volume changes, set the volume ref.listen(videoPlayerControlsProvider.select((value) => value.mute), @@ -186,12 +186,12 @@ class NativeVideoViewerPage extends HookConsumerWidget { if (state == VideoPlaybackState.playing) { log.info('Syncing with the controls playing'); // Sync with the controls playing - WakelockPlus.enable(); + // WakelockPlus.enable(); log.info('Synced with the controls playing'); } else { log.info('Syncing with the controls pause'); // Sync with the controls pause - WakelockPlus.disable(); + // WakelockPlus.disable(); log.info('Synced with the controls pause'); } } @@ -233,7 +233,7 @@ class NativeVideoViewerPage extends HookConsumerWidget { log.info('initController: added onPlaybackEnded listener'); log.info('initController: loading video source'); - nc.loadVideoSource(await videoSource); + nc.loadVideoSource(videoSource); log.info('initController: loaded video source'); log.info('initController: setting controller'); @@ -280,26 +280,24 @@ class NativeVideoViewerPage extends HookConsumerWidget { playerController.onPlaybackEnded.removeListener(onPlaybackEnded); log.info('Removed onPlaybackEnded listener'); - Future.microtask(() async { - log.info('Stopping video'); - await playerController.stop(); - log.info('Stopped video'); - - log.info('Disabling wakelock'); - await WakelockPlus.disable(); - log.info('Disabled wakelock'); - }); + log.info('Stopping video'); + playerController.stop(); + log.info('Stopped video'); log.info('Disposing controller'); controller.value = null; log.info('Disposed controller'); + + // log.info('Disabling Wakelock'); + // WakelockPlus.disable(); + // log.info('Disabled Wakelock'); } catch (error) { log.severe('Error during useEffect cleanup: $error'); // Consume error from the controller } }; }, - [], + [videoSource], ); return Stack( 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 d15b26ea20..9920951cb6 100644 --- a/mobile/lib/providers/asset_viewer/video_player_controls_provider.dart +++ b/mobile/lib/providers/asset_viewer/video_player_controls_provider.dart @@ -36,6 +36,10 @@ class VideoPlayerControls extends StateNotifier { } void reset() { + if (state.position == 0 && !state.mute && !state.pause) { + return; + } + state = VideoPlaybackControls( position: 0, pause: false, @@ -47,6 +51,10 @@ class VideoPlayerControls extends StateNotifier { bool get mute => state.mute; set position(double value) { + if (state.position == value) { + return; + } + state = VideoPlaybackControls( position: value, mute: state.mute, @@ -55,6 +63,10 @@ class VideoPlayerControls extends StateNotifier { } set mute(bool value) { + if (state.mute == value) { + return; + } + state = VideoPlaybackControls( position: state.position, mute: value, @@ -71,6 +83,10 @@ class VideoPlayerControls extends StateNotifier { } void pause() { + if (state.pause) { + return; + } + state = VideoPlaybackControls( position: state.position, mute: state.mute, @@ -79,6 +95,10 @@ class VideoPlayerControls extends StateNotifier { } void play() { + if (!state.pause) { + return; + } + state = VideoPlaybackControls( position: state.position, mute: state.mute, @@ -95,11 +115,13 @@ class VideoPlayerControls extends StateNotifier { } void restart() { - state = VideoPlaybackControls( - position: 0, - mute: state.mute, - pause: true, - ); + if (state.position > 0 || !state.pause) { + state = VideoPlaybackControls( + position: 0, + mute: state.mute, + pause: false, + ); + } state = VideoPlaybackControls( position: 0,