From 93a89ba4b9c7358da63c3b2d07429c50701c5e1c Mon Sep 17 00:00:00 2001 From: Flummi Date: Tue, 24 Jun 2025 13:05:08 +0200 Subject: [PATCH] .. --- lib/screens/mediadetail.dart | 63 +++++++++++++------------ lib/widgets/video_controls_overlay.dart | 43 +++++++++-------- lib/widgets/video_widget.dart | 28 +++++------ 3 files changed, 67 insertions(+), 67 deletions(-) diff --git a/lib/screens/mediadetail.dart b/lib/screens/mediadetail.dart index 261df73..09d4abd 100644 --- a/lib/screens/mediadetail.dart +++ b/lib/screens/mediadetail.dart @@ -282,17 +282,24 @@ class _MediaDetailScreenState extends State { Widget _buildMedia(MediaItem item, bool isActive) { Widget mediaWidget; + final bool isFavorite = + item.favorites?.any((f) => f.userId == authController.user.value?.id) ?? + false; + if (item.mime.startsWith('image/')) { - mediaWidget = CachedNetworkImage( - imageUrl: item.mediaUrl, - fit: BoxFit.contain, - placeholder: (context, url) => - const Center(child: CircularProgressIndicator()), - errorWidget: (c, e, s) => const Icon(Icons.broken_image, size: 100), + mediaWidget = GestureDetector( + onDoubleTap: () => _handleFavoriteToggle(item, isFavorite), + child: CachedNetworkImage( + imageUrl: item.mediaUrl, + fit: BoxFit.contain, + placeholder: (context, url) => + const Center(child: CircularProgressIndicator()), + errorWidget: (c, e, s) => const Icon(Icons.broken_image, size: 100), + ), ); } else if (item.mime.startsWith('video/') || item.mime.startsWith('audio/')) { - final key = _videoWidgetKeys.putIfAbsent( + final GlobalKey key = _videoWidgetKeys.putIfAbsent( item.id, () => GlobalKey(), ); @@ -305,39 +312,33 @@ class _MediaDetailScreenState extends State { setState(() => _readyItemIds.add(item.id)); } }, + onDoubleTap: () => _handleFavoriteToggle(item, isFavorite), ); } else { mediaWidget = const Icon(Icons.help_outline, size: 100); } - final bool isFavorite = - item.favorites?.any((f) => f.userId == authController.user.value?.id) ?? - false; - return Hero( tag: 'media_${item.id}', - child: GestureDetector( - onDoubleTap: () => _handleFavoriteToggle(item, isFavorite), - child: Stack( - alignment: Alignment.center, - children: [ - mediaWidget, - AnimatedOpacity( - opacity: _showFavoriteAnimation[item.id] ?? false ? 1.0 : 0.0, - duration: const Duration(milliseconds: 200), - child: AnimatedScale( - scale: _showFavoriteAnimation[item.id] ?? false ? 1.0 : 0.5, - duration: const Duration(milliseconds: 400), - curve: Curves.easeOutBack, - child: Icon( - isFavorite ? Icons.favorite : Icons.favorite_outline, - color: Colors.red, - size: 100, - ), + child: Stack( + alignment: Alignment.center, + children: [ + mediaWidget, + AnimatedOpacity( + opacity: _showFavoriteAnimation[item.id] ?? false ? 1.0 : 0.0, + duration: const Duration(milliseconds: 200), + child: AnimatedScale( + scale: _showFavoriteAnimation[item.id] ?? false ? 1.0 : 0.5, + duration: const Duration(milliseconds: 400), + curve: Curves.easeOutBack, + child: Icon( + isFavorite ? Icons.favorite : Icons.favorite_outline, + color: Colors.red, + size: 100, ), ), - ], - ), + ), + ], ), ); } diff --git a/lib/widgets/video_controls_overlay.dart b/lib/widgets/video_controls_overlay.dart index b5b36be..f9a4644 100644 --- a/lib/widgets/video_controls_overlay.dart +++ b/lib/widgets/video_controls_overlay.dart @@ -6,8 +6,13 @@ import 'package:f0ckapp/controller/settingscontroller.dart'; class VideoControlsOverlay extends StatefulWidget { final CachedVideoPlayerPlusController controller; + final VoidCallback? onDoubleTap; - const VideoControlsOverlay({super.key, required this.controller}); + const VideoControlsOverlay({ + super.key, + required this.controller, + this.onDoubleTap, + }); @override State createState() => _VideoControlsOverlayState(); @@ -140,27 +145,9 @@ class _VideoControlsOverlayState extends State { AnimatedOpacity( opacity: _controlsVisible && !_isScrubbing ? 1.0 : 0.0, duration: const Duration(milliseconds: 300), - child: IgnorePointer( - ignoring: !_controlsVisible, - child: Stack( - alignment: Alignment.center, - children: [ - IconButton( - icon: Icon( - widget.controller.value.isPlaying - ? Icons.pause - : Icons.play_arrow, - size: 64, - color: Theme.of(context).colorScheme.primary, - ), - onPressed: _handlePlayPause, - ), - Align( - alignment: Alignment.bottomCenter, - child: _buildBottomBar(), - ), - ], - ), + child: Align( + alignment: Alignment.bottomCenter, + child: _buildBottomBar(), ), ), ], @@ -208,6 +195,18 @@ class _VideoControlsOverlayState extends State { padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), child: Row( children: [ + IconButton( + icon: Icon( + widget.controller.value.isPlaying + ? Icons.pause + : Icons.play_arrow, + color: Theme.of(context).colorScheme.primary, + size: 20, + ), + onPressed: _handlePlayPause, + constraints: const BoxConstraints(), + padding: EdgeInsets.zero, + ), Text( _formatDuration(widget.controller.value.position), style: TextStyle( diff --git a/lib/widgets/video_widget.dart b/lib/widgets/video_widget.dart index 7d12238..1e8ad27 100644 --- a/lib/widgets/video_widget.dart +++ b/lib/widgets/video_widget.dart @@ -17,6 +17,7 @@ class VideoWidget extends StatefulWidget { final bool fullScreen; final VoidCallback? onInitialized; final Duration? initialPosition; + final VoidCallback? onDoubleTap; const VideoWidget({ super.key, @@ -25,6 +26,7 @@ class VideoWidget extends StatefulWidget { this.fullScreen = false, this.onInitialized, this.initialPosition, + this.onDoubleTap, }); @override @@ -56,6 +58,7 @@ class VideoWidgetState extends State { await videoController.initialize(); if (!mounted) return; + // Rebuild the widget to reflect the initialized state setState(() {}); if (widget.initialPosition != null) { @@ -100,7 +103,8 @@ class VideoWidgetState extends State { @override Widget build(BuildContext context) { - bool isAudio = widget.details.mime.startsWith('audio'); + final bool isInitialized = videoController.value.isInitialized; + final bool isAudio = widget.details.mime.startsWith('audio'); Widget mediaContent; if (isAudio) { @@ -114,30 +118,26 @@ class VideoWidgetState extends State { ), ); } else { - mediaContent = videoController.value.isInitialized + mediaContent = isInitialized ? CachedVideoPlayerPlus(videoController) : const Center(child: CircularProgressIndicator()); } return AspectRatio( - aspectRatio: videoController.value.isInitialized + aspectRatio: isInitialized ? videoController.value.aspectRatio : (isAudio ? 16 / 9 : 9 / 16), child: Stack( alignment: Alignment.center, children: [ mediaContent, - AnimatedBuilder( - animation: videoController, - builder: (context, child) { - if (videoController.value.isInitialized) { - return Positioned.fill( - child: VideoControlsOverlay(controller: videoController), - ); - } - return const SizedBox.shrink(); - }, - ), + if (isInitialized) + Positioned.fill( + child: VideoControlsOverlay( + controller: videoController, + onDoubleTap: widget.onDoubleTap, + ), + ), ], ), );