diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9f29d8253..b2e361db1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,8 +31,9 @@ jobs: # refer to https://docs.flutter.dev/development/tools/sdk/releases. # Note: The version below should be manually updated to the latest second most recent version # after a new stable version comes out. - - "3.27.4" + - "3.29.3" - "3.x" + fail-fast: false steps: - name: 📚 Git Checkout uses: actions/checkout@v4 @@ -59,3 +60,5 @@ jobs: - name: 📁 Upload coverage to Codecov uses: codecov/codecov-action@v5 + # TODO: Remove the below once we have adequate tests for this library. + continue-on-error: true diff --git a/.gitignore b/.gitignore index ccaa8833f..5a47f7877 100644 --- a/.gitignore +++ b/.gitignore @@ -45,4 +45,6 @@ build/ .project .classpath -.settings \ No newline at end of file +.settings + +coverage/* \ No newline at end of file diff --git a/example/lib/app/app.dart b/example/lib/app/app.dart index 6d58f29f6..7bd09c598 100644 --- a/example/lib/app/app.dart +++ b/example/lib/app/app.dart @@ -1,4 +1,3 @@ - import 'package:chewie/chewie.dart'; import 'package:chewie_example/app/theme.dart'; import 'package:flutter/material.dart'; diff --git a/lib/src/center_play_button.dart b/lib/src/center_play_button.dart index 2b1656497..c8a87067f 100644 --- a/lib/src/center_play_button.dart +++ b/lib/src/center_play_button.dart @@ -38,12 +38,13 @@ class CenterPlayButton extends StatelessWidget { child: IconButton( iconSize: 32, padding: const EdgeInsets.all(12.0), - icon: isFinished - ? Icon(Icons.replay, color: iconColor) - : AnimatedPlayPause( - color: iconColor, - playing: isPlaying, - ), + icon: + isFinished + ? Icon(Icons.replay, color: iconColor) + : AnimatedPlayPause( + color: iconColor, + playing: isPlaying, + ), onPressed: onPressed, ), ), diff --git a/lib/src/chewie_player.dart b/lib/src/chewie_player.dart index 5d76fdf6d..463140167 100644 --- a/lib/src/chewie_player.dart +++ b/lib/src/chewie_player.dart @@ -13,22 +13,20 @@ import 'package:provider/provider.dart'; import 'package:video_player/video_player.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; -typedef ChewieRoutePageBuilder = Widget Function( - BuildContext context, - Animation animation, - Animation secondaryAnimation, - ChewieControllerProvider controllerProvider, -); +typedef ChewieRoutePageBuilder = + Widget Function( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + ChewieControllerProvider controllerProvider, + ); /// A Video Player with Material and Cupertino skins. /// /// `video_player` is pretty low level. Chewie wraps it in a friendly skin to /// make it easy to use! class Chewie extends StatefulWidget { - const Chewie({ - super.key, - required this.controller, - }); + const Chewie({super.key, required this.controller}); /// The [ChewieController] final ChewieController controller; @@ -223,7 +221,6 @@ class ChewieState extends State { DeviceOrientation.landscapeRight, ]); } - /// Video h > w means we force portrait else if (isPortraitVideo) { SystemChrome.setPreferredOrientations([ @@ -231,7 +228,6 @@ class ChewieState extends State { DeviceOrientation.portraitDown, ]); } - /// Otherwise if h == w (square video) else { SystemChrome.setPreferredOrientations(DeviceOrientation.values); @@ -310,9 +306,9 @@ class ChewieController extends ChangeNotifier { this.controlsSafeAreaMinimum = EdgeInsets.zero, this.pauseOnBackgroundTap = false, }) : assert( - playbackSpeeds.every((speed) => speed > 0), - 'The playbackSpeeds values must all be greater than 0', - ) { + playbackSpeeds.every((speed) => speed > 0), + 'The playbackSpeeds values must all be greater than 0', + ) { _initialize(); } @@ -365,7 +361,8 @@ class ChewieController extends ChangeNotifier { Animation, Animation, ChewieControllerProvider, - )? routePageBuilder, + )? + routePageBuilder, bool? pauseOnBackgroundTap, }) { return ChewieController( @@ -409,14 +406,16 @@ class ChewieController extends ChangeNotifier { allowPlaybackSpeedChanging ?? this.allowPlaybackSpeedChanging, useRootNavigator: useRootNavigator ?? this.useRootNavigator, playbackSpeeds: playbackSpeeds ?? this.playbackSpeeds, - systemOverlaysOnEnterFullScreen: systemOverlaysOnEnterFullScreen ?? + systemOverlaysOnEnterFullScreen: + systemOverlaysOnEnterFullScreen ?? this.systemOverlaysOnEnterFullScreen, deviceOrientationsOnEnterFullScreen: deviceOrientationsOnEnterFullScreen ?? - this.deviceOrientationsOnEnterFullScreen, + this.deviceOrientationsOnEnterFullScreen, systemOverlaysAfterFullScreen: systemOverlaysAfterFullScreen ?? this.systemOverlaysAfterFullScreen, - deviceOrientationsAfterFullScreen: deviceOrientationsAfterFullScreen ?? + deviceOrientationsAfterFullScreen: + deviceOrientationsAfterFullScreen ?? this.deviceOrientationsAfterFullScreen, routePageBuilder: routePageBuilder ?? this.routePageBuilder, hideControlsTimer: hideControlsTimer ?? this.hideControlsTimer, @@ -449,7 +448,8 @@ class ChewieController extends ChangeNotifier { final Future Function( BuildContext context, List chewieOptions, - )? optionsBuilder; + )? + optionsBuilder; /// Add your own additional options on top of chewie options final List Function(BuildContext context)? additionalOptions; @@ -506,7 +506,7 @@ class ChewieController extends ChangeNotifier { /// When the video playback runs into an error, you can build a custom /// error message. final Widget Function(BuildContext context, String errorMessage)? - errorBuilder; + errorBuilder; /// When the video is buffering, you can build a custom widget. final WidgetBuilder? bufferingBuilder; diff --git a/lib/src/chewie_progress_colors.dart b/lib/src/chewie_progress_colors.dart index 75e48c1cf..d0187d0ea 100644 --- a/lib/src/chewie_progress_colors.dart +++ b/lib/src/chewie_progress_colors.dart @@ -6,10 +6,10 @@ class ChewieProgressColors { Color bufferedColor = const Color.fromRGBO(30, 30, 200, 0.2), Color handleColor = const Color.fromRGBO(200, 200, 200, 1.0), Color backgroundColor = const Color.fromRGBO(200, 200, 200, 0.5), - }) : playedPaint = Paint()..color = playedColor, - bufferedPaint = Paint()..color = bufferedColor, - handlePaint = Paint()..color = handleColor, - backgroundPaint = Paint()..color = backgroundColor; + }) : playedPaint = Paint()..color = playedColor, + bufferedPaint = Paint()..color = bufferedColor, + handlePaint = Paint()..color = handleColor, + backgroundPaint = Paint()..color = backgroundColor; final Paint playedPaint; final Paint bufferedPaint; diff --git a/lib/src/cupertino/cupertino_controls.dart b/lib/src/cupertino/cupertino_controls.dart index 7e1a7330c..5029b7d65 100644 --- a/lib/src/cupertino/cupertino_controls.dart +++ b/lib/src/cupertino/cupertino_controls.dart @@ -67,16 +67,16 @@ class _CupertinoControlsState extends State if (_latestValue.hasError) { return chewieController.errorBuilder != null ? chewieController.errorBuilder!( - context, - chewieController.videoPlayerController.value.errorDescription!, - ) + context, + chewieController.videoPlayerController.value.errorDescription!, + ) : const Center( - child: Icon( - CupertinoIcons.exclamationmark_circle, - color: Colors.white, - size: 42, - ), - ); + child: Icon( + CupertinoIcons.exclamationmark_circle, + color: Colors.white, + size: 42, + ), + ); } final backgroundColor = widget.backgroundColor; @@ -95,9 +95,7 @@ class _CupertinoControlsState extends State children: [ if (_displayBufferingIndicator) _chewieController?.bufferingBuilder?.call(context) ?? - const Center( - child: CircularProgressIndicator(), - ) + const Center(child: CircularProgressIndicator()) else _buildHitArea(), Column( @@ -155,10 +153,7 @@ class _CupertinoControlsState extends State super.didChangeDependencies(); } - GestureDetector _buildOptionsButton( - Color iconColor, - double barHeight, - ) { + GestureDetector _buildOptionsButton(Color iconColor, double barHeight) { final options = []; if (chewieController.additionalOptions != null && @@ -177,11 +172,12 @@ class _CupertinoControlsState extends State context: context, semanticsDismissible: true, useRootNavigator: chewieController.useRootNavigator, - builder: (context) => CupertinoOptionsDialog( - options: options, - cancelButtonText: - chewieController.optionsTranslation?.cancelButtonText, - ), + builder: + (context) => CupertinoOptionsDialog( + options: options, + cancelButtonText: + chewieController.optionsTranslation?.cancelButtonText, + ), ); if (_latestValue.isPlaying) { _startHideTimer(); @@ -193,11 +189,7 @@ class _CupertinoControlsState extends State color: Colors.transparent, padding: const EdgeInsets.only(left: 4.0, right: 8.0), margin: const EdgeInsets.only(right: 6.0), - child: Icon( - Icons.more_vert, - color: iconColor, - size: 18, - ), + child: Icon(Icons.more_vert, color: iconColor, size: 18), ), ); } @@ -231,9 +223,7 @@ class _CupertinoControlsState extends State ), child: Text( currentSubtitle.first!.text.toString(), - style: const TextStyle( - fontSize: 18, - ), + style: const TextStyle(fontSize: 18), textAlign: TextAlign.center, ), ), @@ -258,38 +248,41 @@ class _CupertinoControlsState extends State child: ClipRRect( borderRadius: BorderRadius.circular(10.0), child: BackdropFilter( - filter: ui.ImageFilter.blur( - sigmaX: 10.0, - sigmaY: 10.0, - ), + filter: ui.ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), child: Container( height: barHeight, color: backgroundColor, - child: chewieController.isLive - ? Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _buildPlayPause(controller, iconColor, barHeight), - _buildLive(iconColor), - ], - ) - : Row( - children: [ - _buildSkipBack(iconColor, barHeight), - _buildPlayPause(controller, iconColor, barHeight), - _buildSkipForward(iconColor, barHeight), - _buildPosition(iconColor), - _buildProgressBar(), - _buildRemaining(iconColor), - _buildSubtitleToggle(iconColor, barHeight), - if (chewieController.allowPlaybackSpeedChanging) - _buildSpeedButton(controller, iconColor, barHeight), - if (chewieController.additionalOptions != null && - chewieController - .additionalOptions!(context).isNotEmpty) - _buildOptionsButton(iconColor, barHeight), - ], - ), + child: + chewieController.isLive + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _buildPlayPause(controller, iconColor, barHeight), + _buildLive(iconColor), + ], + ) + : Row( + children: [ + _buildSkipBack(iconColor, barHeight), + _buildPlayPause(controller, iconColor, barHeight), + _buildSkipForward(iconColor, barHeight), + _buildPosition(iconColor), + _buildProgressBar(), + _buildRemaining(iconColor), + _buildSubtitleToggle(iconColor, barHeight), + if (chewieController.allowPlaybackSpeedChanging) + _buildSpeedButton( + controller, + iconColor, + barHeight, + ), + if (chewieController.additionalOptions != null && + chewieController + .additionalOptions!(context) + .isNotEmpty) + _buildOptionsButton(iconColor, barHeight), + ], + ), ), ), ), @@ -301,10 +294,7 @@ class _CupertinoControlsState extends State Widget _buildLive(Color iconColor) { return Padding( padding: const EdgeInsets.only(right: 12.0), - child: Text( - 'LIVE', - style: TextStyle(color: iconColor, fontSize: 12.0), - ), + child: Text('LIVE', style: TextStyle(color: iconColor, fontSize: 12.0)), ); } @@ -347,29 +337,31 @@ class _CupertinoControlsState extends State } Widget _buildHitArea() { - final bool isFinished = (_latestValue.position >= _latestValue.duration) && + final bool isFinished = + (_latestValue.position >= _latestValue.duration) && _latestValue.duration.inSeconds > 0; final bool showPlayButton = widget.showPlayButton && !_latestValue.isPlaying && !_dragging; return GestureDetector( - onTap: _latestValue.isPlaying - ? _chewieController?.pauseOnBackgroundTap ?? false - ? () { - _playPause(); - - setState(() { - notifier.hideStuff = true; - }); - } - : _cancelAndRestartTimer - : () { - _hideTimer?.cancel(); - - setState(() { - notifier.hideStuff = false; - }); - }, + onTap: + _latestValue.isPlaying + ? _chewieController?.pauseOnBackgroundTap ?? false + ? () { + _playPause(); + + setState(() { + notifier.hideStuff = true; + }); + } + : _cancelAndRestartTimer + : () { + _hideTimer?.cancel(); + + setState(() { + notifier.hideStuff = false; + }); + }, child: CenterPlayButton( backgroundColor: widget.backgroundColor, iconColor: widget.iconColor, @@ -437,10 +429,7 @@ class _CupertinoControlsState extends State child: Container( height: barHeight, color: Colors.transparent, - padding: const EdgeInsets.only( - left: 6.0, - right: 6.0, - ), + padding: const EdgeInsets.only(left: 6.0, right: 6.0), child: AnimatedPlayPause( color: widget.iconColor, playing: controller.value.isPlaying, @@ -456,10 +445,7 @@ class _CupertinoControlsState extends State padding: const EdgeInsets.only(right: 12.0), child: Text( formatDuration(position), - style: TextStyle( - color: iconColor, - fontSize: 12.0, - ), + style: TextStyle(color: iconColor, fontSize: 12.0), ), ); } @@ -487,10 +473,7 @@ class _CupertinoControlsState extends State height: barHeight, color: Colors.transparent, margin: const EdgeInsets.only(right: 10.0), - padding: const EdgeInsets.only( - left: 6.0, - right: 6.0, - ), + padding: const EdgeInsets.only(left: 6.0, right: 6.0), child: Icon( Icons.subtitles, color: _subtitleOn ? iconColor : Colors.grey[700], @@ -513,15 +496,8 @@ class _CupertinoControlsState extends State height: barHeight, color: Colors.transparent, margin: const EdgeInsets.only(left: 10.0), - padding: const EdgeInsets.only( - left: 6.0, - right: 6.0, - ), - child: Icon( - CupertinoIcons.gobackward_15, - color: iconColor, - size: 18.0, - ), + padding: const EdgeInsets.only(left: 6.0, right: 6.0), + child: Icon(CupertinoIcons.gobackward_15, color: iconColor, size: 18.0), ), ); } @@ -532,18 +508,9 @@ class _CupertinoControlsState extends State child: Container( height: barHeight, color: Colors.transparent, - padding: const EdgeInsets.only( - left: 6.0, - right: 8.0, - ), - margin: const EdgeInsets.only( - right: 8.0, - ), - child: Icon( - CupertinoIcons.goforward_15, - color: iconColor, - size: 18.0, - ), + padding: const EdgeInsets.only(left: 6.0, right: 8.0), + margin: const EdgeInsets.only(right: 8.0), + child: Icon(CupertinoIcons.goforward_15, color: iconColor, size: 18.0), ), ); } @@ -561,10 +528,11 @@ class _CupertinoControlsState extends State context: context, semanticsDismissible: true, useRootNavigator: chewieController.useRootNavigator, - builder: (context) => _PlaybackSpeedDialog( - speeds: chewieController.playbackSpeeds, - selected: _latestValue.playbackSpeed, - ), + builder: + (context) => _PlaybackSpeedDialog( + speeds: chewieController.playbackSpeeds, + selected: _latestValue.playbackSpeed, + ), ); if (chosenSpeed != null) { @@ -580,23 +548,15 @@ class _CupertinoControlsState extends State child: Container( height: barHeight, color: Colors.transparent, - padding: const EdgeInsets.only( - left: 6.0, - right: 8.0, - ), - margin: const EdgeInsets.only( - right: 8.0, - ), + padding: const EdgeInsets.only(left: 6.0, right: 8.0), + margin: const EdgeInsets.only(right: 8.0), child: Transform( alignment: Alignment.center, - transform: Matrix4.skewY(0.0) - ..rotateX(math.pi) - ..rotateZ(math.pi * 0.8), - child: Icon( - Icons.speed, - color: iconColor, - size: 18.0, - ), + transform: + Matrix4.skewY(0.0) + ..rotateX(math.pi) + ..rotateZ(math.pi * 0.8), + child: Icon(Icons.speed, color: iconColor, size: 18.0), ), ), ); @@ -649,7 +609,8 @@ class _CupertinoControlsState extends State } Future _initialize() async { - _subtitleOn = chewieController.showSubtitles && + _subtitleOn = + chewieController.showSubtitles && (chewieController.subtitle?.isNotEmpty ?? false); controller.addListener(_updateState); @@ -704,32 +665,13 @@ class _CupertinoControlsState extends State _startHideTimer(); }, - colors: chewieController.cupertinoProgressColors ?? + colors: + chewieController.cupertinoProgressColors ?? ChewieProgressColors( - playedColor: const Color.fromARGB( - 120, - 255, - 255, - 255, - ), - handleColor: const Color.fromARGB( - 255, - 255, - 255, - 255, - ), - bufferedColor: const Color.fromARGB( - 60, - 255, - 255, - 255, - ), - backgroundColor: const Color.fromARGB( - 20, - 255, - 255, - 255, - ), + playedColor: const Color.fromARGB(120, 255, 255, 255), + handleColor: const Color.fromARGB(255, 255, 255, 255), + bufferedColor: const Color.fromARGB(60, 255, 255, 255), + backgroundColor: const Color.fromARGB(20, 255, 255, 255), ), draggableProgressBar: chewieController.draggableProgressBar, ), @@ -738,7 +680,8 @@ class _CupertinoControlsState extends State } void _playPause() { - final isFinished = _latestValue.position >= _latestValue.duration && + final isFinished = + _latestValue.position >= _latestValue.duration && _latestValue.duration.inSeconds > 0; setState(() { @@ -790,9 +733,10 @@ class _CupertinoControlsState extends State } void _startHideTimer() { - final hideControlsTimer = chewieController.hideControlsTimer.isNegative - ? ChewieController.defaultHideControlsTimer - : chewieController.hideControlsTimer; + final hideControlsTimer = + chewieController.hideControlsTimer.isNegative + ? ChewieController.defaultHideControlsTimer + : chewieController.hideControlsTimer; _hideTimer = Timer(hideControlsTimer, () { setState(() { notifier.hideStuff = true; @@ -839,8 +783,8 @@ class _PlaybackSpeedDialog extends StatelessWidget { const _PlaybackSpeedDialog({ required List speeds, required double selected, - }) : _speeds = speeds, - _selected = selected; + }) : _speeds = speeds, + _selected = selected; final List _speeds; final double _selected; @@ -850,23 +794,24 @@ class _PlaybackSpeedDialog extends StatelessWidget { final selectedColor = CupertinoTheme.of(context).primaryColor; return CupertinoActionSheet( - actions: _speeds - .map( - (e) => CupertinoActionSheetAction( - onPressed: () { - Navigator.of(context).pop(e); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (e == _selected) - Icon(Icons.check, size: 20.0, color: selectedColor), - Text(e.toString()), - ], - ), - ), - ) - .toList(), + actions: + _speeds + .map( + (e) => CupertinoActionSheetAction( + onPressed: () { + Navigator.of(context).pop(e); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (e == _selected) + Icon(Icons.check, size: 20.0, color: selectedColor), + Text(e.toString()), + ], + ), + ), + ) + .toList(), ); } } diff --git a/lib/src/cupertino/widgets/cupertino_options_dialog.dart b/lib/src/cupertino/widgets/cupertino_options_dialog.dart index 4b923dc6e..72cc74f4c 100644 --- a/lib/src/cupertino/widgets/cupertino_options_dialog.dart +++ b/lib/src/cupertino/widgets/cupertino_options_dialog.dart @@ -21,14 +21,15 @@ class _CupertinoOptionsDialogState extends State { Widget build(BuildContext context) { return SafeArea( child: CupertinoActionSheet( - actions: widget.options - .map( - (option) => CupertinoActionSheetAction( - onPressed: () => option.onTap(context), - child: Text(option.title), - ), - ) - .toList(), + actions: + widget.options + .map( + (option) => CupertinoActionSheetAction( + onPressed: () => option.onTap(context), + child: Text(option.title), + ), + ) + .toList(), cancelButton: CupertinoActionSheetAction( onPressed: () => Navigator.pop(context), isDestructiveAction: true, diff --git a/lib/src/helpers/adaptive_controls.dart b/lib/src/helpers/adaptive_controls.dart index ef8968d3b..518ec376e 100644 --- a/lib/src/helpers/adaptive_controls.dart +++ b/lib/src/helpers/adaptive_controls.dart @@ -2,9 +2,7 @@ import 'package:chewie/chewie.dart'; import 'package:flutter/material.dart'; class AdaptiveControls extends StatelessWidget { - const AdaptiveControls({ - super.key, - }); + const AdaptiveControls({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/src/helpers/utils.dart b/lib/src/helpers/utils.dart index 17ae2161a..855e48004 100644 --- a/lib/src/helpers/utils.dart +++ b/lib/src/helpers/utils.dart @@ -10,21 +10,24 @@ String formatDuration(Duration position) { final minutes = seconds ~/ 60; seconds = seconds % 60; - final hoursString = hours >= 10 - ? '$hours' - : hours == 0 + final hoursString = + hours >= 10 + ? '$hours' + : hours == 0 ? '00' : '0$hours'; - final minutesString = minutes >= 10 - ? '$minutes' - : minutes == 0 + final minutesString = + minutes >= 10 + ? '$minutes' + : minutes == 0 ? '00' : '0$minutes'; - final secondsString = seconds >= 10 - ? '$seconds' - : seconds == 0 + final secondsString = + seconds >= 10 + ? '$seconds' + : seconds == 0 ? '00' : '0$seconds'; diff --git a/lib/src/material/color_compat_extensions.dart b/lib/src/material/color_compat_extensions.dart deleted file mode 100644 index bff4f3071..000000000 --- a/lib/src/material/color_compat_extensions.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:flutter/material.dart'; - -//ignore_for_file: deprecated_member_use -extension ColorCompatExtensions on Color { - /// Returns a new color that matches this color with the given opacity. - /// - /// This is a compatibility layer that ensures compatibility with Flutter - /// versions below 3.27. In Flutter 3.27 and later, `Color.withOpacity` - /// has been deprecated in favor of `Color.withValues`. - /// - /// This method bridges the gap by providing a consistent way to adjust - /// the opacity of a color across different Flutter versions. - /// - /// **Important:** Once the minimum supported Flutter version is bumped - /// to 3.27 or higher, this method should be removed and replaced with - /// `withValues(alpha: opacity)`. - /// - /// See also: - /// * [Color.withOpacity], which is deprecated in Flutter 3.27 and later. - /// * [Color.withValues], the recommended replacement for `withOpacity`. - Color withOpacityCompat(double opacity) { - // Compatibility layer that uses the legacy withOpacity method, while - // ignoring the deprecation for now (in order to guarantee N-1 minimum - // version compatibility). - // Once it's removed from a future update, we'll have to replace uses of - // this method with withValues(alpha: opacity). - // TODO: Replace this bridge method once the above holds true. - return withOpacity(opacity); - } -} diff --git a/lib/src/material/material_controls.dart b/lib/src/material/material_controls.dart index 3ea67f31d..c8c7cbfe1 100644 --- a/lib/src/material/material_controls.dart +++ b/lib/src/material/material_controls.dart @@ -5,7 +5,6 @@ import 'package:chewie/src/center_seek_button.dart'; import 'package:chewie/src/chewie_player.dart'; import 'package:chewie/src/chewie_progress_colors.dart'; import 'package:chewie/src/helpers/utils.dart'; -import 'package:chewie/src/material/color_compat_extensions.dart'; import 'package:chewie/src/material/material_progress_bar.dart'; import 'package:chewie/src/material/widgets/options_dialog.dart'; import 'package:chewie/src/material/widgets/playback_speed_dialog.dart'; @@ -17,10 +16,7 @@ import 'package:provider/provider.dart'; import 'package:video_player/video_player.dart'; class MaterialControls extends StatefulWidget { - const MaterialControls({ - this.showPlayButton = true, - super.key, - }); + const MaterialControls({this.showPlayButton = true, super.key}); final bool showPlayButton; @@ -67,13 +63,7 @@ class _MaterialControlsState extends State context, chewieController.videoPlayerController.value.errorDescription!, ) ?? - const Center( - child: Icon( - Icons.error, - color: Colors.white, - size: 42, - ), - ); + const Center(child: Icon(Icons.error, color: Colors.white, size: 42)); } return MouseRegion( @@ -88,9 +78,7 @@ class _MaterialControlsState extends State children: [ if (_displayBufferingIndicator) _chewieController?.bufferingBuilder?.call(context) ?? - const Center( - child: CircularProgressIndicator(), - ) + const Center(child: CircularProgressIndicator()) else _buildHitArea(), _buildActionBar(), @@ -103,8 +91,10 @@ class _MaterialControlsState extends State 0.0, notifier.hideStuff ? barHeight * 0.8 : 0.0, ), - child: - _buildSubtitles(context, chewieController.subtitle!), + child: _buildSubtitles( + context, + chewieController.subtitle!, + ), ), _buildBottomBar(context), ], @@ -170,9 +160,10 @@ class _MaterialControlsState extends State _onSpeedButtonTap(); }, iconData: Icons.speed, - title: chewieController.optionsTranslation?.playbackSpeedButtonText ?? + title: + chewieController.optionsTranslation?.playbackSpeedButtonText ?? 'Playback speed', - ) + ), ]; if (chewieController.additionalOptions != null && @@ -192,17 +183,20 @@ class _MaterialControlsState extends State if (chewieController.optionsBuilder != null) { await chewieController.optionsBuilder!( - context, _buildOptions(context)); + context, + _buildOptions(context), + ); } else { await showModalBottomSheet( context: context, isScrollControlled: true, useRootNavigator: chewieController.useRootNavigator, - builder: (context) => OptionsDialog( - options: _buildOptions(context), - cancelButtonText: - chewieController.optionsTranslation?.cancelButtonText, - ), + builder: + (context) => OptionsDialog( + options: _buildOptions(context), + cancelButtonText: + chewieController.optionsTranslation?.cancelButtonText, + ), ); } @@ -210,10 +204,7 @@ class _MaterialControlsState extends State _startHideTimer(); } }, - icon: const Icon( - Icons.more_vert, - color: Colors.white, - ), + icon: const Icon(Icons.more_vert, color: Colors.white), ), ); } @@ -244,18 +235,14 @@ class _MaterialControlsState extends State ), child: Text( currentSubtitle.first!.text.toString(), - style: const TextStyle( - fontSize: 18, - ), + style: const TextStyle(fontSize: 18), textAlign: TextAlign.center, ), ), ); } - AnimatedOpacity _buildBottomBar( - BuildContext context, - ) { + AnimatedOpacity _buildBottomBar(BuildContext context) { final iconColor = Theme.of(context).textTheme.labelLarge!.color; return AnimatedOpacity( @@ -291,18 +278,12 @@ class _MaterialControlsState extends State ], ), ), - SizedBox( - height: chewieController.isFullScreen ? 15.0 : 0, - ), + SizedBox(height: chewieController.isFullScreen ? 15.0 : 0), if (!chewieController.isLive) Expanded( child: Container( padding: const EdgeInsets.symmetric(horizontal: 20), - child: Row( - children: [ - _buildProgressBar(), - ], - ), + child: Row(children: [_buildProgressBar()]), ), ), ], @@ -312,9 +293,7 @@ class _MaterialControlsState extends State ); } - GestureDetector _buildMuteButton( - VideoPlayerController controller, - ) { + GestureDetector _buildMuteButton(VideoPlayerController controller) { return GestureDetector( onTap: () { _cancelAndRestartTimer(); @@ -332,9 +311,7 @@ class _MaterialControlsState extends State child: ClipRect( child: Container( height: barHeight, - padding: const EdgeInsets.only( - left: 6.0, - ), + padding: const EdgeInsets.only(left: 6.0), child: Icon( _latestValue.volume > 0 ? Icons.volume_up : Icons.volume_off, color: Colors.white, @@ -354,10 +331,7 @@ class _MaterialControlsState extends State child: Container( height: barHeight + (chewieController.isFullScreen ? 15.0 : 0), margin: const EdgeInsets.only(right: 12.0), - padding: const EdgeInsets.only( - left: 8.0, - right: 8.0, - ), + padding: const EdgeInsets.only(left: 8.0, right: 8.0), child: Center( child: Icon( chewieController.isFullScreen @@ -372,7 +346,8 @@ class _MaterialControlsState extends State } Widget _buildHitArea() { - final bool isFinished = (_latestValue.position >= _latestValue.duration) && + final bool isFinished = + (_latestValue.position >= _latestValue.duration) && _latestValue.duration.inSeconds > 0; final bool showPlayButton = widget.showPlayButton && !_dragging && !notifier.hideStuff; @@ -402,8 +377,9 @@ class _MaterialControlsState extends State }, child: Container( alignment: Alignment.center, - color: Colors - .transparent, // The Gesture Detector doesn't expand to the full size of the container without this; Not sure why! + color: + Colors + .transparent, // The Gesture Detector doesn't expand to the full size of the container without this; Not sure why! child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -418,9 +394,7 @@ class _MaterialControlsState extends State onPressed: _seekBackward, ), Container( - margin: EdgeInsets.symmetric( - horizontal: marginSize, - ), + margin: EdgeInsets.symmetric(horizontal: marginSize), child: CenterPlayButton( backgroundColor: Colors.black54, iconColor: Colors.white, @@ -453,10 +427,11 @@ class _MaterialControlsState extends State context: context, isScrollControlled: true, useRootNavigator: chewieController.useRootNavigator, - builder: (context) => PlaybackSpeedDialog( - speeds: chewieController.playbackSpeeds, - selected: _latestValue.playbackSpeed, - ), + builder: + (context) => PlaybackSpeedDialog( + speeds: chewieController.playbackSpeeds, + selected: _latestValue.playbackSpeed, + ), ); if (chosenSpeed != null) { @@ -480,10 +455,10 @@ class _MaterialControlsState extends State text: '/ ${formatDuration(duration)}', style: TextStyle( fontSize: 14.0, - color: Colors.white.withOpacityCompat(.75), + color: Colors.white.withValues(alpha: .75), fontWeight: FontWeight.normal, ), - ) + ), ], style: const TextStyle( fontSize: 14.0, @@ -504,10 +479,7 @@ class _MaterialControlsState extends State child: Container( height: barHeight, color: Colors.transparent, - padding: const EdgeInsets.only( - left: 12.0, - right: 12.0, - ), + padding: const EdgeInsets.only(left: 12.0, right: 12.0), child: Icon( _subtitleOn ? Icons.closed_caption @@ -535,7 +507,8 @@ class _MaterialControlsState extends State } Future _initialize() async { - _subtitleOn = chewieController.showSubtitles && + _subtitleOn = + chewieController.showSubtitles && (chewieController.subtitle?.isNotEmpty ?? false); controller.addListener(_updateState); @@ -559,17 +532,20 @@ class _MaterialControlsState extends State notifier.hideStuff = true; chewieController.toggleFullScreen(); - _showAfterExpandCollapseTimer = - Timer(const Duration(milliseconds: 300), () { - setState(() { - _cancelAndRestartTimer(); - }); - }); + _showAfterExpandCollapseTimer = Timer( + const Duration(milliseconds: 300), + () { + setState(() { + _cancelAndRestartTimer(); + }); + }, + ); }); } void _playPause() { - final bool isFinished = (_latestValue.position >= _latestValue.duration) && + final bool isFinished = + (_latestValue.position >= _latestValue.duration) && _latestValue.duration.inSeconds > 0; setState(() { @@ -609,25 +585,18 @@ class _MaterialControlsState extends State } void _seekBackward() { - _seekRelative( - const Duration( - seconds: -10, - ), - ); + _seekRelative(const Duration(seconds: -10)); } void _seekForward() { - _seekRelative( - const Duration( - seconds: 10, - ), - ); + _seekRelative(const Duration(seconds: 10)); } void _startHideTimer() { - final hideControlsTimer = chewieController.hideControlsTimer.isNegative - ? ChewieController.defaultHideControlsTimer - : chewieController.hideControlsTimer; + final hideControlsTimer = + chewieController.hideControlsTimer.isNegative + ? ChewieController.defaultHideControlsTimer + : chewieController.hideControlsTimer; _hideTimer = Timer(hideControlsTimer, () { setState(() { notifier.hideStuff = true; @@ -690,14 +659,17 @@ class _MaterialControlsState extends State _startHideTimer(); }, - colors: chewieController.materialProgressColors ?? + colors: + chewieController.materialProgressColors ?? ChewieProgressColors( playedColor: Theme.of(context).colorScheme.secondary, handleColor: Theme.of(context).colorScheme.secondary, - bufferedColor: - Theme.of(context).colorScheme.surface.withOpacityCompat(0.5), - backgroundColor: - Theme.of(context).disabledColor.withOpacityCompat(.5), + bufferedColor: Theme.of( + context, + ).colorScheme.surface.withValues(alpha: 0.5), + backgroundColor: Theme.of( + context, + ).disabledColor.withValues(alpha: .5), ), draggableProgressBar: chewieController.draggableProgressBar, ), diff --git a/lib/src/material/material_desktop_controls.dart b/lib/src/material/material_desktop_controls.dart index ebffd9560..5ca96c55f 100644 --- a/lib/src/material/material_desktop_controls.dart +++ b/lib/src/material/material_desktop_controls.dart @@ -5,7 +5,6 @@ import 'package:chewie/src/center_play_button.dart'; import 'package:chewie/src/chewie_player.dart'; import 'package:chewie/src/chewie_progress_colors.dart'; import 'package:chewie/src/helpers/utils.dart'; -import 'package:chewie/src/material/color_compat_extensions.dart'; import 'package:chewie/src/material/material_progress_bar.dart'; import 'package:chewie/src/material/widgets/options_dialog.dart'; import 'package:chewie/src/material/widgets/playback_speed_dialog.dart'; @@ -18,10 +17,7 @@ import 'package:provider/provider.dart'; import 'package:video_player/video_player.dart'; class MaterialDesktopControls extends StatefulWidget { - const MaterialDesktopControls({ - this.showPlayButton = true, - super.key, - }); + const MaterialDesktopControls({this.showPlayButton = true, super.key}); final bool showPlayButton; @@ -64,7 +60,7 @@ class _MaterialDesktopControlsState extends State notifier = Provider.of(context, listen: false); } - void _handleKeyPress(event) { + void _handleKeyPress(KeyEvent event) { if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.space) { _playPause(); } else if (event is KeyDownEvent && @@ -88,13 +84,7 @@ class _MaterialDesktopControlsState extends State context, chewieController.videoPlayerController.value.errorDescription!, ) ?? - const Center( - child: Icon( - Icons.error, - color: Colors.white, - size: 42, - ), - ); + const Center(child: Icon(Icons.error, color: Colors.white, size: 42)); } return KeyboardListener( @@ -116,9 +106,7 @@ class _MaterialDesktopControlsState extends State children: [ if (_displayBufferingIndicator) _chewieController?.bufferingBuilder?.call(context) ?? - const Center( - child: CircularProgressIndicator(), - ) + const Center(child: CircularProgressIndicator()) else _buildHitArea(), Column( @@ -131,7 +119,9 @@ class _MaterialDesktopControlsState extends State notifier.hideStuff ? barHeight * 0.8 : 0.0, ), child: _buildSubtitles( - context, chewieController.subtitle!), + context, + chewieController.subtitle!, + ), ), _buildBottomBar(context), ], @@ -180,10 +170,7 @@ class _MaterialDesktopControlsState extends State ); } - Widget _buildOptionsButton({ - IconData? icon, - bool isPadded = false, - }) { + Widget _buildOptionsButton({IconData? icon, bool isPadded = false}) { final options = [ OptionItem( onTap: (context) async { @@ -191,9 +178,10 @@ class _MaterialDesktopControlsState extends State _onSpeedButtonTap(); }, iconData: Icons.speed, - title: chewieController.optionsTranslation?.playbackSpeedButtonText ?? + title: + chewieController.optionsTranslation?.playbackSpeedButtonText ?? 'Playback speed', - ) + ), ]; if (chewieController.additionalOptions != null && @@ -216,11 +204,12 @@ class _MaterialDesktopControlsState extends State context: context, isScrollControlled: true, useRootNavigator: chewieController.useRootNavigator, - builder: (context) => OptionsDialog( - options: options, - cancelButtonText: - chewieController.optionsTranslation?.cancelButtonText, - ), + builder: + (context) => OptionsDialog( + options: options, + cancelButtonText: + chewieController.optionsTranslation?.cancelButtonText, + ), ); } @@ -228,10 +217,7 @@ class _MaterialDesktopControlsState extends State _startHideTimer(); } }, - icon: Icon( - icon ?? Icons.more_vert, - color: Colors.white, - ), + icon: Icon(icon ?? Icons.more_vert, color: Colors.white), ), ); } @@ -262,18 +248,14 @@ class _MaterialDesktopControlsState extends State ), child: Text( currentSubtitle.first!.text.toString(), - style: const TextStyle( - fontSize: 18, - ), + style: const TextStyle(fontSize: 18), textAlign: TextAlign.center, ), ), ); } - AnimatedOpacity _buildBottomBar( - BuildContext context, - ) { + AnimatedOpacity _buildBottomBar(BuildContext context) { final iconColor = Theme.of(context).textTheme.labelLarge!.color; return AnimatedOpacity( @@ -281,8 +263,9 @@ class _MaterialDesktopControlsState extends State duration: const Duration(milliseconds: 300), child: Container( height: barHeight + (chewieController.isFullScreen ? 20.0 : 0), - padding: - EdgeInsets.only(bottom: chewieController.isFullScreen ? 10.0 : 15), + padding: EdgeInsets.only( + bottom: chewieController.isFullScreen ? 10.0 : 15, + ), child: SafeArea( bottom: chewieController.isFullScreen, child: Column( @@ -319,11 +302,7 @@ class _MaterialDesktopControlsState extends State left: 20, bottom: chewieController.isFullScreen ? 5.0 : 0, ), - child: Row( - children: [ - _buildProgressBar(), - ], - ), + child: Row(children: [_buildProgressBar()]), ), ), ], @@ -342,10 +321,7 @@ class _MaterialDesktopControlsState extends State child: Container( height: barHeight + (chewieController.isFullScreen ? 15.0 : 0), margin: const EdgeInsets.only(right: 12.0), - padding: const EdgeInsets.only( - left: 8.0, - right: 8.0, - ), + padding: const EdgeInsets.only(left: 8.0, right: 8.0), child: Center( child: Icon( chewieController.isFullScreen @@ -360,7 +336,8 @@ class _MaterialDesktopControlsState extends State } Widget _buildHitArea() { - final bool isFinished = _latestValue.position >= _latestValue.duration && + final bool isFinished = + _latestValue.position >= _latestValue.duration && _latestValue.duration.inSeconds > 0; final bool showPlayButton = widget.showPlayButton && !_dragging && !notifier.hideStuff; @@ -406,10 +383,11 @@ class _MaterialDesktopControlsState extends State context: context, isScrollControlled: true, useRootNavigator: chewieController.useRootNavigator, - builder: (context) => PlaybackSpeedDialog( - speeds: chewieController.playbackSpeeds, - selected: _latestValue.playbackSpeed, - ), + builder: + (context) => PlaybackSpeedDialog( + speeds: chewieController.playbackSpeeds, + selected: _latestValue.playbackSpeed, + ), ); if (chosenSpeed != null) { @@ -421,9 +399,7 @@ class _MaterialDesktopControlsState extends State } } - GestureDetector _buildMuteButton( - VideoPlayerController controller, - ) { + GestureDetector _buildMuteButton(VideoPlayerController controller) { return GestureDetector( onTap: () { _cancelAndRestartTimer(); @@ -441,9 +417,7 @@ class _MaterialDesktopControlsState extends State child: ClipRect( child: Container( height: barHeight, - padding: const EdgeInsets.only( - right: 15.0, - ), + padding: const EdgeInsets.only(right: 15.0), child: Icon( _latestValue.volume > 0 ? Icons.volume_up : Icons.volume_off, color: Colors.white, @@ -461,10 +435,7 @@ class _MaterialDesktopControlsState extends State height: barHeight, color: Colors.transparent, margin: const EdgeInsets.only(left: 8.0, right: 4.0), - padding: const EdgeInsets.only( - left: 12.0, - right: 12.0, - ), + padding: const EdgeInsets.only(left: 12.0, right: 12.0), child: AnimatedPlayPause( playing: controller.value.isPlaying, color: Colors.white, @@ -479,10 +450,7 @@ class _MaterialDesktopControlsState extends State return Text( '${formatDuration(position)} / ${formatDuration(duration)}', - style: const TextStyle( - fontSize: 14.0, - color: Colors.white, - ), + style: const TextStyle(fontSize: 14.0, color: Colors.white), ); } @@ -503,7 +471,8 @@ class _MaterialDesktopControlsState extends State } Future _initialize() async { - _subtitleOn = chewieController.showSubtitles && + _subtitleOn = + chewieController.showSubtitles && (chewieController.subtitle?.isNotEmpty ?? false); controller.addListener(_updateState); @@ -529,12 +498,14 @@ class _MaterialDesktopControlsState extends State chewieController.toggleFullScreen(); - _showAfterExpandCollapseTimer = - Timer(const Duration(milliseconds: 300), () { - setState(() { - _cancelAndRestartTimer(); - }); - }); + _showAfterExpandCollapseTimer = Timer( + const Duration(milliseconds: 300), + () { + setState(() { + _cancelAndRestartTimer(); + }); + }, + ); } void _playPause() { @@ -561,9 +532,10 @@ class _MaterialDesktopControlsState extends State } void _startHideTimer() { - final hideControlsTimer = chewieController.hideControlsTimer.isNegative - ? ChewieController.defaultHideControlsTimer - : chewieController.hideControlsTimer; + final hideControlsTimer = + chewieController.hideControlsTimer.isNegative + ? ChewieController.defaultHideControlsTimer + : chewieController.hideControlsTimer; _hideTimer = Timer(hideControlsTimer, () { setState(() { notifier.hideStuff = true; @@ -606,19 +578,11 @@ class _MaterialDesktopControlsState extends State } void _seekBackward() { - _seekRelative( - const Duration( - seconds: -10, - ), - ); + _seekRelative(const Duration(seconds: -10)); } void _seekForward() { - _seekRelative( - const Duration( - seconds: 10, - ), - ); + _seekRelative(const Duration(seconds: 10)); } void _seekRelative(Duration relativeSeek) { @@ -656,14 +620,17 @@ class _MaterialDesktopControlsState extends State _startHideTimer(); }, - colors: chewieController.materialProgressColors ?? + colors: + chewieController.materialProgressColors ?? ChewieProgressColors( playedColor: Theme.of(context).colorScheme.secondary, handleColor: Theme.of(context).colorScheme.secondary, - bufferedColor: - Theme.of(context).colorScheme.surface.withOpacityCompat(0.5), - backgroundColor: - Theme.of(context).disabledColor.withOpacityCompat(0.5), + bufferedColor: Theme.of( + context, + ).colorScheme.surface.withValues(alpha: 0.5), + backgroundColor: Theme.of( + context, + ).disabledColor.withValues(alpha: 0.5), ), draggableProgressBar: chewieController.draggableProgressBar, ), diff --git a/lib/src/material/widgets/options_dialog.dart b/lib/src/material/widgets/options_dialog.dart index 047f12097..80817868f 100644 --- a/lib/src/material/widgets/options_dialog.dart +++ b/lib/src/material/widgets/options_dialog.dart @@ -31,24 +31,21 @@ class _OptionsDialogState extends State { onTap: () => widget.options[i].onTap(context), leading: Icon(widget.options[i].iconData), title: Text(widget.options[i].title), - subtitle: widget.options[i].subtitle != null - ? Text(widget.options[i].subtitle!) - : null, + subtitle: + widget.options[i].subtitle != null + ? Text(widget.options[i].subtitle!) + : null, ); }, ), const Padding( padding: EdgeInsets.symmetric(horizontal: 16), - child: Divider( - thickness: 1.0, - ), + child: Divider(thickness: 1.0), ), ListTile( onTap: () => Navigator.pop(context), leading: const Icon(Icons.close), - title: Text( - widget.cancelButtonText ?? 'Cancel', - ), + title: Text(widget.cancelButtonText ?? 'Cancel'), ), ], ), diff --git a/lib/src/material/widgets/playback_speed_dialog.dart b/lib/src/material/widgets/playback_speed_dialog.dart index 0525a8f3b..331c8ee72 100644 --- a/lib/src/material/widgets/playback_speed_dialog.dart +++ b/lib/src/material/widgets/playback_speed_dialog.dart @@ -5,8 +5,8 @@ class PlaybackSpeedDialog extends StatelessWidget { super.key, required List speeds, required double selected, - }) : _speeds = speeds, - _selected = selected; + }) : _speeds = speeds, + _selected = selected; final List _speeds; final double _selected; @@ -25,11 +25,7 @@ class PlaybackSpeedDialog extends StatelessWidget { title: Row( children: [ if (speed == _selected) - Icon( - Icons.check, - size: 20.0, - color: selectedColor, - ) + Icon(Icons.check, size: 20.0, color: selectedColor) else Container(width: 20.0), const SizedBox(width: 16.0), diff --git a/lib/src/models/subtitle_model.dart b/lib/src/models/subtitle_model.dart index edcac3a59..e77182e6c 100644 --- a/lib/src/models/subtitle_model.dart +++ b/lib/src/models/subtitle_model.dart @@ -8,10 +8,13 @@ class Subtitles { bool get isNotEmpty => !isEmpty; List getByPosition(Duration position) { - final found = subtitle.where((item) { - if (item != null) return position >= item.start && position <= item.end; - return false; - }).toList(); + final found = + subtitle.where((item) { + if (item != null) { + return position >= item.start && position <= item.end; + } + return false; + }).toList(); return found; } diff --git a/lib/src/notifiers/player_notifier.dart b/lib/src/notifiers/player_notifier.dart index dbba4faac..c70fa8665 100644 --- a/lib/src/notifiers/player_notifier.dart +++ b/lib/src/notifiers/player_notifier.dart @@ -6,9 +6,7 @@ import 'package:flutter/material.dart'; /// over all State-Changes inside chewie /// class PlayerNotifier extends ChangeNotifier { - PlayerNotifier._( - bool hideStuff, - ) : _hideStuff = hideStuff; + PlayerNotifier._(bool hideStuff) : _hideStuff = hideStuff; bool _hideStuff; @@ -21,8 +19,6 @@ class PlayerNotifier extends ChangeNotifier { // ignore: prefer_constructors_over_static_methods static PlayerNotifier init() { - return PlayerNotifier._( - true, - ); + return PlayerNotifier._(true); } } diff --git a/lib/src/player_with_controls.dart b/lib/src/player_with_controls.dart index 65d51a69b..f394a4541 100644 --- a/lib/src/player_with_controls.dart +++ b/lib/src/player_with_controls.dart @@ -44,7 +44,8 @@ class PlayerWithControls extends StatelessWidget { scaleEnabled: chewieController.zoomAndPan, child: Center( child: AspectRatio( - aspectRatio: chewieController.aspectRatio ?? + aspectRatio: + chewieController.aspectRatio ?? chewieController.videoPlayerController.value.aspectRatio, child: VideoPlayer(chewieController.videoPlayerController), ), @@ -53,24 +54,22 @@ class PlayerWithControls extends StatelessWidget { if (chewieController.overlay != null) chewieController.overlay!, if (Theme.of(context).platform != TargetPlatform.iOS) Consumer( - builder: ( - BuildContext context, - PlayerNotifier notifier, - Widget? widget, - ) => - Visibility( - visible: !notifier.hideStuff, - child: AnimatedOpacity( - opacity: notifier.hideStuff ? 0.0 : 0.8, - duration: const Duration( - milliseconds: 250, + builder: + ( + BuildContext context, + PlayerNotifier notifier, + Widget? widget, + ) => Visibility( + visible: !notifier.hideStuff, + child: AnimatedOpacity( + opacity: notifier.hideStuff ? 0.0 : 0.8, + duration: const Duration(milliseconds: 250), + child: const DecoratedBox( + decoration: BoxDecoration(color: Colors.black54), + child: SizedBox.expand(), + ), + ), ), - child: const DecoratedBox( - decoration: BoxDecoration(color: Colors.black54), - child: SizedBox.expand(), - ), - ), - ), ), if (!chewieController.isFullScreen) buildControls(context, chewieController) @@ -84,17 +83,18 @@ class PlayerWithControls extends StatelessWidget { } return LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - return Center( - child: SizedBox( - height: constraints.maxHeight, - width: constraints.maxWidth, - child: AspectRatio( - aspectRatio: calculateAspectRatio(context), - child: buildPlayerWithControls(chewieController, context), + builder: (BuildContext context, BoxConstraints constraints) { + return Center( + child: SizedBox( + height: constraints.maxHeight, + width: constraints.maxWidth, + child: AspectRatio( + aspectRatio: calculateAspectRatio(context), + child: buildPlayerWithControls(chewieController, context), + ), ), - ), - ); - }); + ); + }, + ); } } diff --git a/lib/src/progress_bar.dart b/lib/src/progress_bar.dart index b07a16e5b..052060497 100644 --- a/lib/src/progress_bar.dart +++ b/lib/src/progress_bar.dart @@ -59,10 +59,9 @@ class _VideoProgressBarState extends State { } void _seekToRelativePosition(Offset globalPosition) { - controller.seekTo(context.calcRelativePosition( - controller.value.duration, - globalPosition, - )); + controller.seekTo( + context.calcRelativePosition(controller.value.duration, globalPosition), + ); } @override @@ -80,46 +79,46 @@ class _VideoProgressBarState extends State { return widget.draggableProgressBar ? GestureDetector( - onHorizontalDragStart: (DragStartDetails details) { - if (!controller.value.isInitialized) { - return; - } - _controllerWasPlaying = controller.value.isPlaying; - if (_controllerWasPlaying) { - controller.pause(); - } - - widget.onDragStart?.call(); - }, - onHorizontalDragUpdate: (DragUpdateDetails details) { - if (!controller.value.isInitialized) { - return; - } - _latestDraggableOffset = details.globalPosition; - listener(); - - widget.onDragUpdate?.call(); - }, - onHorizontalDragEnd: (DragEndDetails details) { - if (_controllerWasPlaying) { - controller.play(); - } - - if (_latestDraggableOffset != null) { - _seekToRelativePosition(_latestDraggableOffset!); - _latestDraggableOffset = null; - } - - widget.onDragEnd?.call(); - }, - onTapDown: (TapDownDetails details) { - if (!controller.value.isInitialized) { - return; - } - _seekToRelativePosition(details.globalPosition); - }, - child: child, - ) + onHorizontalDragStart: (DragStartDetails details) { + if (!controller.value.isInitialized) { + return; + } + _controllerWasPlaying = controller.value.isPlaying; + if (_controllerWasPlaying) { + controller.pause(); + } + + widget.onDragStart?.call(); + }, + onHorizontalDragUpdate: (DragUpdateDetails details) { + if (!controller.value.isInitialized) { + return; + } + _latestDraggableOffset = details.globalPosition; + listener(); + + widget.onDragUpdate?.call(); + }, + onHorizontalDragEnd: (DragEndDetails details) { + if (_controllerWasPlaying) { + controller.play(); + } + + if (_latestDraggableOffset != null) { + _seekToRelativePosition(_latestDraggableOffset!); + _latestDraggableOffset = null; + } + + widget.onDragEnd?.call(); + }, + onTapDown: (TapDownDetails details) { + if (!controller.value.isInitialized) { + return; + } + _seekToRelativePosition(details.globalPosition); + }, + child: child, + ) : child; } } @@ -152,12 +151,13 @@ class StaticProgressBar extends StatelessWidget { child: CustomPaint( painter: _ProgressBarPainter( value: value, - draggableValue: latestDraggableOffset != null - ? context.calcRelativePosition( - value.duration, - latestDraggableOffset!, - ) - : null, + draggableValue: + latestDraggableOffset != null + ? context.calcRelativePosition( + value.duration, + latestDraggableOffset!, + ) + : null, colors: colors, barHeight: barHeight, handleHeight: handleHeight, @@ -211,7 +211,8 @@ class _ProgressBarPainter extends CustomPainter { if (!value.isInitialized) { return; } - final double playedPartPercent = (draggableValue != null + final double playedPartPercent = + (draggableValue != null ? draggableValue!.inMilliseconds : value.position.inMilliseconds) / value.duration.inMilliseconds; @@ -243,13 +244,13 @@ class _ProgressBarPainter extends CustomPainter { ); if (drawShadow) { - final Path shadowPath = Path() - ..addOval( - Rect.fromCircle( - center: Offset(playedPart, baseOffset + barHeight / 2), - radius: handleHeight, - ), - ); + final Path shadowPath = + Path()..addOval( + Rect.fromCircle( + center: Offset(playedPart, baseOffset + barHeight / 2), + radius: handleHeight, + ), + ); canvas.drawShadow(shadowPath, Colors.black, 0.2, false); } @@ -263,10 +264,7 @@ class _ProgressBarPainter extends CustomPainter { } extension RelativePositionExtensions on BuildContext { - Duration calcRelativePosition( - Duration videoDuration, - Offset globalPosition, - ) { + Duration calcRelativePosition(Duration videoDuration, Offset globalPosition) { final box = findRenderObject()! as RenderBox; final Offset tapPos = box.globalToLocal(globalPosition); final double relative = (tapPos.dx / box.size.width).clamp(0, 1); diff --git a/pubspec.yaml b/pubspec.yaml index 8b8441c26..e4f46ad0b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,16 +4,16 @@ version: 1.11.3 homepage: https://github.com/fluttercommunity/chewie environment: - sdk: '>=3.6.0 <4.0.0' - flutter: ">=3.27.0" + sdk: '>=3.7.0 <4.0.0' + flutter: ">=3.29.0" dependencies: cupertino_icons: ^1.0.8 flutter: sdk: flutter - provider: ^6.1.2 - video_player: ^2.9.3 - wakelock_plus: ^1.2.10 + provider: ^6.1.5 + video_player: ^2.10.0 + wakelock_plus: ^1.3.2 dev_dependencies: flutter_test: diff --git a/test/uninitialized_controls_state_test.dart b/test/uninitialized_controls_state_test.dart index 0b538784a..0db7a83b7 100644 --- a/test/uninitialized_controls_state_test.dart +++ b/test/uninitialized_controls_state_test.dart @@ -7,10 +7,10 @@ import 'package:video_player/video_player.dart'; List srcs = [ "https://assets.mixkit.co/videos/preview/mixkit-spinning-around-the-earth-29351-large.mp4", "https://assets.mixkit.co/videos/preview/mixkit-daytime-city-traffic-aerial-view-56-large.mp4", - "https://assets.mixkit.co/videos/preview/mixkit-a-girl-blowing-a-bubble-gum-at-an-amusement-park-1226-large.mp4" + "https://assets.mixkit.co/videos/preview/mixkit-a-girl-blowing-a-bubble-gum-at-an-amusement-park-1226-large.mp4", ]; -main() { +void main() { testWidgets("MaterialControls state test", (WidgetTester tester) async { // Build our app and trigger a frame. var videoPlayerController = VideoPlayerController.networkUrl( @@ -21,18 +21,10 @@ main() { videoPlayerController: videoPlayerController, autoPlay: false, looping: false, - customControls: MaterialControls( - key: materialControlsKey, - ), + customControls: MaterialControls(key: materialControlsKey), ); await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: Chewie( - controller: chewieController, - ), - ), - ), + MaterialApp(home: Scaffold(body: Chewie(controller: chewieController))), ); await tester.pump(); @@ -61,13 +53,7 @@ main() { ), ); await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: Chewie( - controller: chewieController, - ), - ), - ), + MaterialApp(home: Scaffold(body: Chewie(controller: chewieController))), ); await tester.pump(); @@ -79,8 +65,9 @@ main() { expect(playButtonWidget.isFinished, false); }); - testWidgets("MaterialDesktopControls state test", - (WidgetTester tester) async { + testWidgets("MaterialDesktopControls state test", ( + WidgetTester tester, + ) async { // Build our app and trigger a frame. var videoPlayerController = VideoPlayerController.networkUrl( Uri.parse(srcs[0]), @@ -90,18 +77,10 @@ main() { videoPlayerController: videoPlayerController, autoPlay: false, looping: false, - customControls: MaterialDesktopControls( - key: materialControlsKey, - ), + customControls: MaterialDesktopControls(key: materialControlsKey), ); await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: Chewie( - controller: chewieController, - ), - ), - ), + MaterialApp(home: Scaffold(body: Chewie(controller: chewieController))), ); await tester.pump();