From 361cc02a067be6fef596bfa78daefcd2d6139b1f Mon Sep 17 00:00:00 2001 From: Lenny Lin Date: Sun, 30 Mar 2025 11:11:45 -0500 Subject: [PATCH] lightbox: Allow zooming in with video lightbox. Fixes #1287 --- lib/widgets/lightbox.dart | 29 ++++++++++++++++------------- test/widgets/lightbox_test.dart | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/lib/widgets/lightbox.dart b/lib/widgets/lightbox.dart index dd2aca5b82..1772c4e296 100644 --- a/lib/widgets/lightbox.dart +++ b/lib/widgets/lightbox.dart @@ -549,19 +549,22 @@ class _VideoLightboxPageState extends State with PerAccountSt message: widget.message, buildAppBarBottom: (context) => null, buildBottomAppBar: _buildBottomAppBar, - child: SafeArea( - child: Center( - child: Stack(alignment: Alignment.center, children: [ - if (_controller != null && _controller!.value.isInitialized) - AspectRatio( - aspectRatio: _controller!.value.aspectRatio, - child: VideoPlayer(_controller!)), - if (_controller == null || !_controller!.value.isInitialized || _controller!.value.isBuffering) - const SizedBox( - width: 32, - height: 32, - child: CircularProgressIndicator(color: Colors.white)), - ])))); + child: Stack(alignment: Alignment.center, children: [ + InteractiveViewer( + child: SafeArea( + child: Center( + child: (_controller != null && _controller!.value.isInitialized) + ? AspectRatio( + aspectRatio: _controller!.value.aspectRatio, + child: VideoPlayer(_controller!)) + : Container())) + ), + if (_controller == null || !_controller!.value.isInitialized || _controller!.value.isBuffering) + const SizedBox( + width: 32, + height: 32, + child: CircularProgressIndicator(color: Colors.white)), + ])); } } diff --git a/test/widgets/lightbox_test.dart b/test/widgets/lightbox_test.dart index 31a4132a7c..f01ac4af04 100644 --- a/test/widgets/lightbox_test.dart +++ b/test/widgets/lightbox_test.dart @@ -557,5 +557,38 @@ void main() { check(position).isGreaterThan(basePosition); check(platform.position).equals(position); }); + + testWidgets('video can be zoomed in and out', (tester) async { + await setupPage(tester, videoSrc: Uri.parse(kTestVideoUrl)); + check(platform.isPlaying).isTrue(); + + final initialRect = tester.getRect(find.byType(VideoPlayer)); + final bottomRight = initialRect.bottomRight; + // Define initial positions for two fingers near bottom right corner: + // In the case of mismatch between media and device orientation, + // the zoom gesture is still expected to work, + // even if the fingers are not in the image's frame. + final Offset finger1Start = bottomRight + const Offset(-70.0, -70.0); + final Offset finger2Start = bottomRight + const Offset(-20.0, -20.0); + final TestGesture gesture1 = await tester.startGesture(finger1Start); + final TestGesture gesture2 = await tester.startGesture(finger2Start); + await tester.pump(); + + // Simulate pinch out (zoom in) + await gesture1.moveBy(const Offset(-20.0, -20.0)); + await gesture2.moveBy(const Offset(20.0, 20.0)); + await tester.pump(); + final zoomedInRect = tester.getRect(find.byType(VideoPlayer)); + check(zoomedInRect.width).isGreaterThan(initialRect.width); + check(zoomedInRect.height).isGreaterThan(initialRect.height); + + // Simulate pinch out (zoom in) + await gesture1.moveBy(const Offset(30.0, 30.0)); + await gesture2.moveBy(const Offset(-30.0, -30.0)); + await tester.pump(); + final zoomedOutRect = tester.getRect(find.byType(VideoPlayer)); + check(zoomedOutRect.width).isLessThan(zoomedInRect.width); + check(zoomedOutRect.height).isLessThan(zoomedInRect.height); + }); }); }