diff --git a/lib/src/features/feed/ui/widgets/videos/video_player.dart b/lib/src/features/feed/ui/widgets/videos/video_player.dart index dfbeef52..9627c549 100644 --- a/lib/src/features/feed/ui/widgets/videos/video_player.dart +++ b/lib/src/features/feed/ui/widgets/videos/video_player.dart @@ -7,6 +7,16 @@ import 'package:spark/src/features/feed/ui/widgets/videos/feed_video_better_play import 'package:spark/src/features/feed/ui/widgets/videos/video_frame.dart'; import 'package:spark/src/features/feed/ui/widgets/videos/video_progress_bar.dart'; +bool hasRenderableFeedVideoPlaybackFrame(VideoPlayerValue value) { + final size = value.size; + return value.initialized && + value.isPlaying && + value.position > Duration.zero && + size != null && + size.width > 0 && + size.height > 0; +} + class PostVideoPlayer extends StatefulWidget { const PostVideoPlayer({ required this.videoUrl, @@ -112,14 +122,6 @@ class PostVideoPlayerState extends State } } - void _hideThumbnailOverlay() { - if (!_showThumbnailOverlay || !mounted) return; - - setState(() { - _showThumbnailOverlay = false; - }); - } - void _videoListener(BetterPlayerEvent event) { if (mounted) { final paused = event.betterPlayerEventType == BetterPlayerEventType.pause; @@ -141,15 +143,6 @@ class PostVideoPlayerState extends State }); } } - - final progress = - event.betterPlayerEventType == BetterPlayerEventType.progress; - final progressPosition = event.parameters?['progress']; - if (progress && - progressPosition is Duration && - progressPosition > Duration.zero) { - _hideThumbnailOverlay(); - } } } @@ -252,12 +245,24 @@ class PostVideoPlayerState extends State if (!mounted) return; final controller = videoController; if (controller == null) return; - final videoSize = controller.videoPlayerController?.value.size; + final videoValue = controller.videoPlayerController?.value; + if (videoValue == null) return; + final videoSize = videoValue.size; _syncPlayerLayout(controller: controller, videoSize: videoSize); - if (_playerVideoSize == videoSize) return; + final shouldHideThumbnail = + _showThumbnailOverlay && + hasRenderableFeedVideoPlaybackFrame(videoValue); + final shouldUpdateVideoSize = _playerVideoSize != videoSize; + if (!shouldHideThumbnail && !shouldUpdateVideoSize) return; + setState(() { - _playerVideoSize = videoSize; + if (shouldHideThumbnail) { + _showThumbnailOverlay = false; + } + if (shouldUpdateVideoSize) { + _playerVideoSize = videoSize; + } }); } diff --git a/test/src/features/feed/ui/widgets/videos/video_player_test.dart b/test/src/features/feed/ui/widgets/videos/video_player_test.dart new file mode 100644 index 00000000..319d3add --- /dev/null +++ b/test/src/features/feed/ui/widgets/videos/video_player_test.dart @@ -0,0 +1,63 @@ +import 'package:better_player_plus/better_player_plus.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:spark/src/features/feed/ui/widgets/videos/video_player.dart'; + +void main() { + group('hasRenderableFeedVideoPlaybackFrame', () { + test('requires initialized playing video beyond the first position', () { + final readyValue = VideoPlayerValue( + duration: Duration(seconds: 3), + isPlaying: true, + position: Duration(milliseconds: 1), + size: Size(1080, 1920), + ); + + expect(hasRenderableFeedVideoPlaybackFrame(readyValue), isTrue); + expect( + hasRenderableFeedVideoPlaybackFrame( + readyValue.copyWith(position: Duration.zero), + ), + isFalse, + ); + expect( + hasRenderableFeedVideoPlaybackFrame( + readyValue.copyWith(isPlaying: false), + ), + isFalse, + ); + expect( + hasRenderableFeedVideoPlaybackFrame( + VideoPlayerValue.uninitialized().copyWith( + isPlaying: true, + position: const Duration(milliseconds: 1), + size: const Size(1080, 1920), + ), + ), + isFalse, + ); + }); + + test('requires a non-zero rendered size', () { + final readyValue = VideoPlayerValue( + duration: Duration(seconds: 3), + isPlaying: true, + position: Duration(milliseconds: 1), + size: Size(1080, 1920), + ); + + expect( + hasRenderableFeedVideoPlaybackFrame( + readyValue.copyWith(size: Size.zero), + ), + isFalse, + ); + expect( + hasRenderableFeedVideoPlaybackFrame( + readyValue.copyWith(size: const Size(1080, 0)), + ), + isFalse, + ); + }); + }); +}