From 990d8396db933913ad72f66d539a1857ec33f593 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Tue, 15 Jan 2019 16:42:46 +0100 Subject: [PATCH 01/24] Remove new statement --- lib/src/chewie_player.dart | 18 +-- lib/src/chewie_progress_colors.dart | 8 +- lib/src/cupertino_controls.dart | 188 ++++++++++++++-------------- lib/src/cupertino_progress_bar.dart | 54 ++++---- lib/src/material_controls.dart | 104 +++++++-------- lib/src/material_progress_bar.dart | 48 +++---- lib/src/player_with_controls.dart | 32 ++--- 7 files changed, 226 insertions(+), 226 deletions(-) diff --git a/lib/src/chewie_player.dart b/lib/src/chewie_player.dart index 83ee9f252..522290440 100644 --- a/lib/src/chewie_player.dart +++ b/lib/src/chewie_player.dart @@ -79,7 +79,7 @@ class Chewie extends StatefulWidget { @override State createState() { - return new _ChewiePlayerState(); + return _ChewiePlayerState(); } } @@ -89,7 +89,7 @@ class _ChewiePlayerState extends State { @override Widget build(BuildContext context) { - return new PlayerWithControls( + return PlayerWithControls( controller: _controller, onExpandCollapse: () => _pushFullScreenWidget(context), aspectRatio: widget.aspectRatio ?? _calculateAspectRatio(context), @@ -111,15 +111,15 @@ class _ChewiePlayerState extends State { Widget _buildFullScreenVideo( BuildContext context, Animation animation) { - return new Scaffold( + return Scaffold( resizeToAvoidBottomPadding: false, - body: new Container( + body: Container( alignment: Alignment.center, color: Colors.black, - child: new PlayerWithControls( + child: PlayerWithControls( controller: _controller, onExpandCollapse: () => - new Future.value(Navigator.of(context).pop()), + Future.value(Navigator.of(context).pop()), aspectRatio: widget.aspectRatio ?? _calculateAspectRatio(context), fullScreen: true, isLive: widget.isLive, @@ -135,7 +135,7 @@ class _ChewiePlayerState extends State { Animation animation, Animation secondaryAnimation, ) { - return new AnimatedBuilder( + return AnimatedBuilder( animation: animation, builder: (BuildContext context, Widget child) { return _buildFullScreenVideo(context, animation); @@ -187,8 +187,8 @@ class _ChewiePlayerState extends State { Future _pushFullScreenWidget(BuildContext context) async { final isAndroid = Theme.of(context).platform == TargetPlatform.android; - final TransitionRoute route = new PageRouteBuilder( - settings: new RouteSettings(isInitialRoute: false), + final TransitionRoute route = PageRouteBuilder( + settings: RouteSettings(isInitialRoute: false), pageBuilder: _fullScreenRoutePageBuilder, ); diff --git a/lib/src/chewie_progress_colors.dart b/lib/src/chewie_progress_colors.dart index 312f0b835..3392ed57e 100644 --- a/lib/src/chewie_progress_colors.dart +++ b/lib/src/chewie_progress_colors.dart @@ -11,8 +11,8 @@ 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 = new Paint()..color = playedColor, - bufferedPaint = new Paint()..color = bufferedColor, - handlePaint = new Paint()..color = handleColor, - backgroundPaint = new Paint()..color = backgroundColor; + }) : playedPaint = Paint()..color = playedColor, + bufferedPaint = Paint()..color = bufferedColor, + handlePaint = Paint()..color = handleColor, + backgroundPaint = Paint()..color = backgroundColor; } diff --git a/lib/src/cupertino_controls.dart b/lib/src/cupertino_controls.dart index e435fc3ae..663d1ecde 100644 --- a/lib/src/cupertino_controls.dart +++ b/lib/src/cupertino_controls.dart @@ -33,7 +33,7 @@ class CupertinoControls extends StatefulWidget { @override State createState() { - return new _CupertinoControlsState(); + return _CupertinoControlsState(); } } @@ -55,7 +55,7 @@ class _CupertinoControlsState extends State { final barHeight = orientation == Orientation.portrait ? 30.0 : 47.0; final buttonPadding = orientation == Orientation.portrait ? 16.0 : 24.0; - return new Column( + return Column( children: [ _buildTopBar( backgroundColor, iconColor, controller, barHeight, buttonPadding), @@ -101,25 +101,25 @@ class _CupertinoControlsState extends State { VideoPlayerController controller, double barHeight, ) { - return new AnimatedOpacity( + return AnimatedOpacity( opacity: _hideStuff ? 0.0 : 1.0, - duration: new Duration(milliseconds: 300), - child: new Container( + duration: Duration(milliseconds: 300), + child: Container( color: Colors.transparent, alignment: Alignment.bottomCenter, - margin: new EdgeInsets.all(marginSize), - child: new ClipRect( - child: new BackdropFilter( - filter: new ui.ImageFilter.blur( + margin: EdgeInsets.all(marginSize), + child: ClipRect( + child: BackdropFilter( + filter: ui.ImageFilter.blur( sigmaX: 10.0, sigmaY: 10.0, ), - child: new Container( + child: Container( height: barHeight, - decoration: new BoxDecoration( + decoration: BoxDecoration( color: backgroundColor, - borderRadius: new BorderRadius.all( - new Radius.circular(10.0), + borderRadius: BorderRadius.all( + Radius.circular(10.0), ), ), child: widget.isLive @@ -130,7 +130,7 @@ class _CupertinoControlsState extends State { _buildLive(iconColor), ], ) - : new Row( + : Row( children: [ _buildSkipBack(iconColor, barHeight), _buildPlayPause(controller, iconColor, barHeight), @@ -148,11 +148,11 @@ class _CupertinoControlsState extends State { } Widget _buildLive(Color iconColor) { - return new Padding( - padding: new EdgeInsets.only(right: 12.0), - child: new Text( + return Padding( + padding: EdgeInsets.only(right: 12.0), + child: Text( 'LIVE', - style: new TextStyle(color: iconColor, fontSize: 12.0), + style: TextStyle(color: iconColor, fontSize: 12.0), ), ); } @@ -163,28 +163,28 @@ class _CupertinoControlsState extends State { double barHeight, double buttonPadding, ) { - return new GestureDetector( + return GestureDetector( onTap: _onExpandCollapse, - child: new AnimatedOpacity( + child: AnimatedOpacity( opacity: _hideStuff ? 0.0 : 1.0, - duration: new Duration(milliseconds: 300), - child: new ClipRect( - child: new BackdropFilter( - filter: new ui.ImageFilter.blur(sigmaX: 10.0), - child: new Container( + duration: Duration(milliseconds: 300), + child: ClipRect( + child: BackdropFilter( + filter: ui.ImageFilter.blur(sigmaX: 10.0), + child: Container( height: barHeight, - padding: new EdgeInsets.only( + padding: EdgeInsets.only( left: buttonPadding, right: buttonPadding, ), - decoration: new BoxDecoration( + decoration: BoxDecoration( color: backgroundColor, - borderRadius: new BorderRadius.all( - new Radius.circular(10.0), + borderRadius: BorderRadius.all( + Radius.circular(10.0), ), ), - child: new Center( - child: new Icon( + child: Center( + child: Icon( widget.fullScreen ? OpenIconicIcons.fullscreenExit : OpenIconicIcons.fullscreenEnter, @@ -200,8 +200,8 @@ class _CupertinoControlsState extends State { } Expanded _buildHitArea() { - return new Expanded( - child: new GestureDetector( + return Expanded( + child: GestureDetector( onTap: _latestValue != null && _latestValue.isPlaying ? _cancelAndRestartTimer : () { @@ -211,7 +211,7 @@ class _CupertinoControlsState extends State { _hideStuff = false; }); }, - child: new Container( + child: Container( color: Colors.transparent, ), ), @@ -225,7 +225,7 @@ class _CupertinoControlsState extends State { double barHeight, double buttonPadding, ) { - return new GestureDetector( + return GestureDetector( onTap: () { _cancelAndRestartTimer(); @@ -236,26 +236,26 @@ class _CupertinoControlsState extends State { controller.setVolume(0.0); } }, - child: new AnimatedOpacity( + child: AnimatedOpacity( opacity: _hideStuff ? 0.0 : 1.0, - duration: new Duration(milliseconds: 300), - child: new ClipRect( - child: new BackdropFilter( - filter: new ui.ImageFilter.blur(sigmaX: 10.0), - child: new Container( - decoration: new BoxDecoration( + duration: Duration(milliseconds: 300), + child: ClipRect( + child: BackdropFilter( + filter: ui.ImageFilter.blur(sigmaX: 10.0), + child: Container( + decoration: BoxDecoration( color: backgroundColor, - borderRadius: new BorderRadius.all( - new Radius.circular(10.0), + borderRadius: BorderRadius.all( + Radius.circular(10.0), ), ), - child: new Container( + child: Container( height: barHeight, - padding: new EdgeInsets.only( + padding: EdgeInsets.only( left: buttonPadding, right: buttonPadding, ), - child: new Icon( + child: Icon( (_latestValue != null && _latestValue.volume > 0) ? Icons.volume_up : Icons.volume_off, @@ -275,16 +275,16 @@ class _CupertinoControlsState extends State { Color iconColor, double barHeight, ) { - return new GestureDetector( + return GestureDetector( onTap: _playPause, - child: new Container( + child: Container( height: barHeight, color: Colors.transparent, - padding: new EdgeInsets.only( + padding: EdgeInsets.only( left: 6.0, right: 6.0, ), - child: new Icon( + child: Icon( controller.value.isPlaying ? OpenIconicIcons.mediaPause : OpenIconicIcons.mediaPlay, @@ -297,13 +297,13 @@ class _CupertinoControlsState extends State { Widget _buildPosition(Color iconColor) { final position = - _latestValue != null ? _latestValue.position : new Duration(seconds: 0); + _latestValue != null ? _latestValue.position : Duration(seconds: 0); - return new Padding( - padding: new EdgeInsets.only(right: 12.0), - child: new Text( + return Padding( + padding: EdgeInsets.only(right: 12.0), + child: Text( formatDuration(position), - style: new TextStyle( + style: TextStyle( color: iconColor, fontSize: 12.0, ), @@ -314,34 +314,34 @@ class _CupertinoControlsState extends State { Widget _buildRemaining(Color iconColor) { final position = _latestValue != null && _latestValue.duration != null ? _latestValue.duration - _latestValue.position - : new Duration(seconds: 0); + : Duration(seconds: 0); - return new Padding( - padding: new EdgeInsets.only(right: 12.0), - child: new Text( + return Padding( + padding: EdgeInsets.only(right: 12.0), + child: Text( '-${formatDuration(position)}', - style: new TextStyle(color: iconColor, fontSize: 12.0), + style: TextStyle(color: iconColor, fontSize: 12.0), ), ); } GestureDetector _buildSkipBack(Color iconColor, double barHeight) { - return new GestureDetector( + return GestureDetector( onTap: _skipBack, - child: new Container( + child: Container( height: barHeight, color: Colors.transparent, - margin: new EdgeInsets.only(left: 10.0), - padding: new EdgeInsets.only( + margin: EdgeInsets.only(left: 10.0), + padding: EdgeInsets.only( left: 6.0, right: 6.0, ), - child: new Transform( + child: Transform( alignment: Alignment.center, - transform: new Matrix4.skewY(0.0) + transform: Matrix4.skewY(0.0) ..rotateX(math.pi) ..rotateZ(math.pi), - child: new Icon( + child: Icon( OpenIconicIcons.reload, color: iconColor, size: 12.0, @@ -352,19 +352,19 @@ class _CupertinoControlsState extends State { } GestureDetector _buildSkipForward(Color iconColor, double barHeight) { - return new GestureDetector( + return GestureDetector( onTap: _skipForward, - child: new Container( + child: Container( height: barHeight, color: Colors.transparent, - padding: new EdgeInsets.only( + padding: EdgeInsets.only( left: 6.0, right: 8.0, ), - margin: new EdgeInsets.only( + margin: EdgeInsets.only( right: 8.0, ), - child: new Icon( + child: Icon( OpenIconicIcons.reload, color: iconColor, size: 12.0, @@ -380,18 +380,18 @@ class _CupertinoControlsState extends State { double barHeight, double buttonPadding, ) { - return new Container( + return Container( height: barHeight, - margin: new EdgeInsets.only( + margin: EdgeInsets.only( top: marginSize, right: marginSize, left: marginSize, ), - child: new Row( + child: Row( children: [ _buildExpandButton( backgroundColor, iconColor, barHeight, buttonPadding), - new Expanded(child: new Container()), + Expanded(child: Container()), _buildMuteButton( controller, backgroundColor, iconColor, barHeight, buttonPadding), ], @@ -420,7 +420,7 @@ class _CupertinoControlsState extends State { _startHideTimer(); } - _initTimer = new Timer(new Duration(milliseconds: 200), () { + _initTimer = Timer(Duration(milliseconds: 200), () { setState(() { _hideStuff = false; }); @@ -432,7 +432,7 @@ class _CupertinoControlsState extends State { _hideStuff = true; widget.onExpandCollapse().then((dynamic _) { - _expandCollapseTimer = new Timer(new Duration(milliseconds: 300), () { + _expandCollapseTimer = Timer(Duration(milliseconds: 300), () { setState(() { _cancelAndRestartTimer(); }); @@ -442,10 +442,10 @@ class _CupertinoControlsState extends State { } Widget _buildProgressBar() { - return new Expanded( - child: new Padding( - padding: new EdgeInsets.only(right: 12.0), - child: new CupertinoVideoProgressBar( + return Expanded( + child: Padding( + padding: EdgeInsets.only(right: 12.0), + child: CupertinoVideoProgressBar( widget.controller, onDragStart: () { _hideTimer?.cancel(); @@ -454,26 +454,26 @@ class _CupertinoControlsState extends State { _startHideTimer(); }, colors: widget.progressColors ?? - new ChewieProgressColors( - playedColor: new Color.fromARGB( + ChewieProgressColors( + playedColor: Color.fromARGB( 120, 255, 255, 255, ), - handleColor: new Color.fromARGB( + handleColor: Color.fromARGB( 255, 255, 255, 255, ), - bufferedColor: new Color.fromARGB( + bufferedColor: Color.fromARGB( 60, 255, 255, 255, ), - backgroundColor: new Color.fromARGB( + backgroundColor: Color.fromARGB( 20, 255, 255, @@ -507,23 +507,23 @@ class _CupertinoControlsState extends State { void _skipBack() { _cancelAndRestartTimer(); - final beginning = new Duration(seconds: 0).inMilliseconds; + final beginning = Duration(seconds: 0).inMilliseconds; final skip = - (_latestValue.position - new Duration(seconds: 15)).inMilliseconds; + (_latestValue.position - Duration(seconds: 15)).inMilliseconds; widget.controller - .seekTo(new Duration(milliseconds: math.max(skip, beginning))); + .seekTo(Duration(milliseconds: math.max(skip, beginning))); } void _skipForward() { _cancelAndRestartTimer(); final end = _latestValue.duration.inMilliseconds; final skip = - (_latestValue.position + new Duration(seconds: 15)).inMilliseconds; - widget.controller.seekTo(new Duration(milliseconds: math.min(skip, end))); + (_latestValue.position + Duration(seconds: 15)).inMilliseconds; + widget.controller.seekTo(Duration(milliseconds: math.min(skip, end))); } void _startHideTimer() { - _hideTimer = new Timer(const Duration(seconds: 3), () { + _hideTimer = Timer(const Duration(seconds: 3), () { setState(() { _hideStuff = true; }); diff --git a/lib/src/cupertino_progress_bar.dart b/lib/src/cupertino_progress_bar.dart index 7c0a9721f..996f447f9 100644 --- a/lib/src/cupertino_progress_bar.dart +++ b/lib/src/cupertino_progress_bar.dart @@ -16,11 +16,11 @@ class CupertinoVideoProgressBar extends StatefulWidget { this.onDragEnd, this.onDragStart, this.onDragUpdate, - }) : colors = colors ?? new ChewieProgressColors(); + }) : colors = colors ?? ChewieProgressColors(); @override _VideoProgressBarState createState() { - return new _VideoProgressBarState(); + return _VideoProgressBarState(); } } @@ -59,16 +59,16 @@ class _VideoProgressBarState extends State { controller.seekTo(position); } - return new GestureDetector( + return GestureDetector( child: (controller.value.hasError) - ? new Text(controller.value.errorDescription) - : new Center( - child: new Container( + ? Text(controller.value.errorDescription) + : Center( + child: Container( height: MediaQuery.of(context).size.height, width: MediaQuery.of(context).size.width, color: Colors.transparent, - child: new CustomPaint( - painter: new _ProgressBarPainter( + child: CustomPaint( + painter: _ProgressBarPainter( controller.value, widget.colors, ), @@ -135,12 +135,12 @@ class _ProgressBarPainter extends CustomPainter { final baseOffset = size.height / 2 - barHeight / 2.0; canvas.drawRRect( - new RRect.fromRectAndRadius( - new Rect.fromPoints( - new Offset(0.0, baseOffset), - new Offset(size.width, baseOffset + barHeight), + RRect.fromRectAndRadius( + Rect.fromPoints( + Offset(0.0, baseOffset), + Offset(size.width, baseOffset + barHeight), ), - new Radius.circular(4.0), + Radius.circular(4.0), ), colors.backgroundPaint, ); @@ -154,35 +154,35 @@ class _ProgressBarPainter extends CustomPainter { final double start = range.startFraction(value.duration) * size.width; final double end = range.endFraction(value.duration) * size.width; canvas.drawRRect( - new RRect.fromRectAndRadius( - new Rect.fromPoints( - new Offset(start, baseOffset), - new Offset(end, baseOffset + barHeight), + RRect.fromRectAndRadius( + Rect.fromPoints( + Offset(start, baseOffset), + Offset(end, baseOffset + barHeight), ), - new Radius.circular(4.0), + Radius.circular(4.0), ), colors.bufferedPaint, ); } canvas.drawRRect( - new RRect.fromRectAndRadius( - new Rect.fromPoints( - new Offset(0.0, baseOffset), - new Offset(playedPart, baseOffset + barHeight), + RRect.fromRectAndRadius( + Rect.fromPoints( + Offset(0.0, baseOffset), + Offset(playedPart, baseOffset + barHeight), ), - new Radius.circular(4.0), + Radius.circular(4.0), ), colors.playedPaint, ); - final shadowPath = new Path() - ..addOval(new Rect.fromCircle( - center: new Offset(playedPart, baseOffset + barHeight / 2), + final shadowPath = Path() + ..addOval(Rect.fromCircle( + center: Offset(playedPart, baseOffset + barHeight / 2), radius: handleHeight)); canvas.drawShadow(shadowPath, Colors.black, 0.2, false); canvas.drawCircle( - new Offset(playedPart, baseOffset + barHeight / 2), + Offset(playedPart, baseOffset + barHeight / 2), handleHeight, colors.handlePaint, ); diff --git a/lib/src/material_controls.dart b/lib/src/material_controls.dart index 1cc335ba6..48390e786 100644 --- a/lib/src/material_controls.dart +++ b/lib/src/material_controls.dart @@ -26,7 +26,7 @@ class MaterialControls extends StatefulWidget { @override State createState() { - return new _MaterialControlsState(); + return _MaterialControlsState(); } } @@ -44,7 +44,7 @@ class _MaterialControlsState extends State { @override Widget build(BuildContext context) { - return new Column( + return Column( children: [ _latestValue != null && !_latestValue.isPlaying && @@ -96,13 +96,13 @@ class _MaterialControlsState extends State { ) { final iconColor = Theme.of(context).textTheme.button.color; - return new AnimatedOpacity( + return AnimatedOpacity( opacity: _hideStuff ? 0.0 : 1.0, - duration: new Duration(milliseconds: 300), - child: new Container( + duration: Duration(milliseconds: 300), + child: Container( height: barHeight, color: Theme.of(context).dialogBackgroundColor, - child: new Row( + child: Row( children: [ _buildPlayPause(controller), widget.isLive @@ -118,20 +118,20 @@ class _MaterialControlsState extends State { } GestureDetector _buildExpandButton() { - return new GestureDetector( + return GestureDetector( onTap: _onExpandCollapse, - child: new AnimatedOpacity( + child: AnimatedOpacity( opacity: _hideStuff ? 0.0 : 1.0, - duration: new Duration(milliseconds: 300), - child: new Container( + duration: Duration(milliseconds: 300), + child: Container( height: barHeight, - margin: new EdgeInsets.only(right: 12.0), - padding: new EdgeInsets.only( + margin: EdgeInsets.only(right: 12.0), + padding: EdgeInsets.only( left: 8.0, right: 8.0, ), - child: new Center( - child: new Icon( + child: Center( + child: Icon( widget.fullScreen ? Icons.fullscreen_exit : Icons.fullscreen, ), ), @@ -141,8 +141,8 @@ class _MaterialControlsState extends State { } Expanded _buildHitArea() { - return new Expanded( - child: new GestureDetector( + return Expanded( + child: GestureDetector( onTap: _latestValue != null && _latestValue.isPlaying ? _cancelAndRestartTimer : () { @@ -152,24 +152,24 @@ class _MaterialControlsState extends State { _hideStuff = true; }); }, - child: new Container( + child: Container( color: Colors.transparent, - child: new Center( - child: new AnimatedOpacity( + child: Center( + child: AnimatedOpacity( opacity: _latestValue != null && !_latestValue.isPlaying && !_dragging ? 1.0 : 0.0, - duration: new Duration(milliseconds: 300), - child: new GestureDetector( - child: new Container( - decoration: new BoxDecoration( + duration: Duration(milliseconds: 300), + child: GestureDetector( + child: Container( + decoration: BoxDecoration( color: Theme.of(context).dialogBackgroundColor, - borderRadius: new BorderRadius.circular(48.0), + borderRadius: BorderRadius.circular(48.0), ), - child: new Padding( - padding: new EdgeInsets.all(12.0), - child: new Icon(Icons.play_arrow, size: 32.0), + child: Padding( + padding: EdgeInsets.all(12.0), + child: Icon(Icons.play_arrow, size: 32.0), ), ), ), @@ -183,7 +183,7 @@ class _MaterialControlsState extends State { GestureDetector _buildMuteButton( VideoPlayerController controller, ) { - return new GestureDetector( + return GestureDetector( onTap: () { _cancelAndRestartTimer(); @@ -194,18 +194,18 @@ class _MaterialControlsState extends State { controller.setVolume(0.0); } }, - child: new AnimatedOpacity( + child: AnimatedOpacity( opacity: _hideStuff ? 0.0 : 1.0, - duration: new Duration(milliseconds: 300), - child: new ClipRect( - child: new Container( - child: new Container( + duration: Duration(milliseconds: 300), + child: ClipRect( + child: Container( + child: Container( height: barHeight, - padding: new EdgeInsets.only( + padding: EdgeInsets.only( left: 8.0, right: 8.0, ), - child: new Icon( + child: Icon( (_latestValue != null && _latestValue.volume > 0) ? Icons.volume_up : Icons.volume_off, @@ -218,17 +218,17 @@ class _MaterialControlsState extends State { } GestureDetector _buildPlayPause(VideoPlayerController controller) { - return new GestureDetector( + return GestureDetector( onTap: _playPause, - child: new Container( + child: Container( height: barHeight, color: Colors.transparent, - margin: new EdgeInsets.only(left: 8.0, right: 4.0), - padding: new EdgeInsets.only( + margin: EdgeInsets.only(left: 8.0, right: 4.0), + padding: EdgeInsets.only( left: 12.0, right: 12.0, ), - child: new Icon( + child: Icon( controller.value.isPlaying ? Icons.pause : Icons.play_arrow, ), ), @@ -243,11 +243,11 @@ class _MaterialControlsState extends State { ? _latestValue.duration : Duration.zero; - return new Padding( - padding: new EdgeInsets.only(right: 24.0), - child: new Text( + return Padding( + padding: EdgeInsets.only(right: 24.0), + child: Text( '${formatDuration(position)} / ${formatDuration(duration)}', - style: new TextStyle( + style: TextStyle( fontSize: 14.0, ), ), @@ -274,7 +274,7 @@ class _MaterialControlsState extends State { _startHideTimer(); } - _showTimer = new Timer(new Duration(milliseconds: 200), () { + _showTimer = Timer(Duration(milliseconds: 200), () { setState(() { _hideStuff = false; }); @@ -287,7 +287,7 @@ class _MaterialControlsState extends State { widget.onExpandCollapse().then((dynamic _) { _showAfterExpandCollapseTimer = - new Timer(new Duration(milliseconds: 300), () { + Timer(Duration(milliseconds: 300), () { setState(() { _cancelAndRestartTimer(); }); @@ -317,7 +317,7 @@ class _MaterialControlsState extends State { } void _startHideTimer() { - _hideTimer = new Timer(const Duration(seconds: 3), () { + _hideTimer = Timer(const Duration(seconds: 3), () { setState(() { _hideStuff = true; }); @@ -331,10 +331,10 @@ class _MaterialControlsState extends State { } Widget _buildProgressBar() { - return new Expanded( - child: new Padding( - padding: new EdgeInsets.only(right: 20.0), - child: new MaterialVideoProgressBar( + return Expanded( + child: Padding( + padding: EdgeInsets.only(right: 20.0), + child: MaterialVideoProgressBar( widget.controller, onDragStart: () { setState(() { @@ -351,7 +351,7 @@ class _MaterialControlsState extends State { _startHideTimer(); }, colors: widget.progressColors ?? - new ChewieProgressColors( + ChewieProgressColors( playedColor: Theme.of(context).accentColor, handleColor: Theme.of(context).accentColor, bufferedColor: Theme.of(context).backgroundColor, diff --git a/lib/src/material_progress_bar.dart b/lib/src/material_progress_bar.dart index 376de389b..13ef8c162 100644 --- a/lib/src/material_progress_bar.dart +++ b/lib/src/material_progress_bar.dart @@ -16,11 +16,11 @@ class MaterialVideoProgressBar extends StatefulWidget { this.onDragEnd, this.onDragStart, this.onDragUpdate, - }) : colors = colors ?? new ChewieProgressColors(); + }) : colors = colors ?? ChewieProgressColors(); @override _VideoProgressBarState createState() { - return new _VideoProgressBarState(); + return _VideoProgressBarState(); } } @@ -59,16 +59,16 @@ class _VideoProgressBarState extends State { controller.seekTo(position); } - return new GestureDetector( + return GestureDetector( child: (controller.value.hasError) - ? new Text(controller.value.errorDescription) - : new Center( - child: new Container( + ? Text(controller.value.errorDescription) + : Center( + child: Container( height: MediaQuery.of(context).size.height / 2, width: MediaQuery.of(context).size.width, color: Colors.transparent, - child: new CustomPaint( - painter: new _ProgressBarPainter( + child: CustomPaint( + painter: _ProgressBarPainter( controller.value, widget.colors, ), @@ -133,12 +133,12 @@ class _ProgressBarPainter extends CustomPainter { final height = 2.0; canvas.drawRRect( - new RRect.fromRectAndRadius( - new Rect.fromPoints( - new Offset(0.0, size.height / 2), - new Offset(size.width, size.height / 2 + height), + RRect.fromRectAndRadius( + Rect.fromPoints( + Offset(0.0, size.height / 2), + Offset(size.width, size.height / 2 + height), ), - new Radius.circular(4.0), + Radius.circular(4.0), ), colors.backgroundPaint, ); @@ -152,28 +152,28 @@ class _ProgressBarPainter extends CustomPainter { final double start = range.startFraction(value.duration) * size.width; final double end = range.endFraction(value.duration) * size.width; canvas.drawRRect( - new RRect.fromRectAndRadius( - new Rect.fromPoints( - new Offset(start, size.height / 2), - new Offset(end, size.height / 2 + height), + RRect.fromRectAndRadius( + Rect.fromPoints( + Offset(start, size.height / 2), + Offset(end, size.height / 2 + height), ), - new Radius.circular(4.0), + Radius.circular(4.0), ), colors.bufferedPaint, ); } canvas.drawRRect( - new RRect.fromRectAndRadius( - new Rect.fromPoints( - new Offset(0.0, size.height / 2), - new Offset(playedPart, size.height / 2 + height), + RRect.fromRectAndRadius( + Rect.fromPoints( + Offset(0.0, size.height / 2), + Offset(playedPart, size.height / 2 + height), ), - new Radius.circular(4.0), + Radius.circular(4.0), ), colors.playedPaint, ); canvas.drawCircle( - new Offset(playedPart, size.height / 2 + height / 2), + Offset(playedPart, size.height / 2 + height / 2), height * 3, colors.handlePaint, ); diff --git a/lib/src/player_with_controls.dart b/lib/src/player_with_controls.dart index 7c1d81aed..faa16ca08 100644 --- a/lib/src/player_with_controls.dart +++ b/lib/src/player_with_controls.dart @@ -36,7 +36,7 @@ class PlayerWithControls extends StatefulWidget { @override State createState() { - return new _VideoPlayerWithControlsState(); + return _VideoPlayerWithControlsState(); } } @@ -45,10 +45,10 @@ class _VideoPlayerWithControlsState extends State { Widget build(BuildContext context) { final controller = widget.controller; - return new Center( - child: new Container( + return Center( + child: Container( width: MediaQuery.of(context).size.width, - child: new AspectRatio( + child: AspectRatio( aspectRatio: widget.aspectRatio, child: _buildPlayerWithControls(controller, context), ), @@ -58,16 +58,16 @@ class _VideoPlayerWithControlsState extends State { Container _buildPlayerWithControls( VideoPlayerController controller, BuildContext context) { - return new Container( - child: new Stack( + return Container( + child: Stack( children: [ - widget.placeholder ?? new Container(), - new Center( - child: new Hero( + widget.placeholder ?? Container(), + Center( + child: Hero( tag: controller, - child: new AspectRatio( + child: AspectRatio( aspectRatio: widget.aspectRatio, - child: new VideoPlayer(controller), + child: VideoPlayer(controller), ), ), ), @@ -83,7 +83,7 @@ class _VideoPlayerWithControlsState extends State { ) { return widget.showControls ? Theme.of(context).platform == TargetPlatform.android - ? new MaterialControls( + ? MaterialControls( controller: controller, onExpandCollapse: widget.onExpandCollapse, fullScreen: widget.fullScreen, @@ -91,9 +91,9 @@ class _VideoPlayerWithControlsState extends State { autoPlay: widget.autoPlay, isLive: widget.isLive, ) - : new CupertinoControls( - backgroundColor: new Color.fromRGBO(41, 41, 41, 0.7), - iconColor: new Color.fromARGB(255, 200, 200, 200), + : CupertinoControls( + backgroundColor: Color.fromRGBO(41, 41, 41, 0.7), + iconColor: Color.fromARGB(255, 200, 200, 200), controller: controller, onExpandCollapse: widget.onExpandCollapse, fullScreen: widget.fullScreen, @@ -101,7 +101,7 @@ class _VideoPlayerWithControlsState extends State { autoPlay: widget.autoPlay, isLive: widget.isLive, ) - : new Container(); + : Container(); } @override From ef4cfeb40d77a8d94de84d069190a96348aeeeae Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Tue, 15 Jan 2019 17:26:13 +0100 Subject: [PATCH 02/24] Run dartfmt --- lib/src/cupertino_controls.dart | 9 +++------ lib/src/material_controls.dart | 3 +-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/src/cupertino_controls.dart b/lib/src/cupertino_controls.dart index 663d1ecde..a099331a9 100644 --- a/lib/src/cupertino_controls.dart +++ b/lib/src/cupertino_controls.dart @@ -508,17 +508,14 @@ class _CupertinoControlsState extends State { void _skipBack() { _cancelAndRestartTimer(); final beginning = Duration(seconds: 0).inMilliseconds; - final skip = - (_latestValue.position - Duration(seconds: 15)).inMilliseconds; - widget.controller - .seekTo(Duration(milliseconds: math.max(skip, beginning))); + final skip = (_latestValue.position - Duration(seconds: 15)).inMilliseconds; + widget.controller.seekTo(Duration(milliseconds: math.max(skip, beginning))); } void _skipForward() { _cancelAndRestartTimer(); final end = _latestValue.duration.inMilliseconds; - final skip = - (_latestValue.position + Duration(seconds: 15)).inMilliseconds; + final skip = (_latestValue.position + Duration(seconds: 15)).inMilliseconds; widget.controller.seekTo(Duration(milliseconds: math.min(skip, end))); } diff --git a/lib/src/material_controls.dart b/lib/src/material_controls.dart index 48390e786..5fa14854d 100644 --- a/lib/src/material_controls.dart +++ b/lib/src/material_controls.dart @@ -286,8 +286,7 @@ class _MaterialControlsState extends State { _hideStuff = true; widget.onExpandCollapse().then((dynamic _) { - _showAfterExpandCollapseTimer = - Timer(Duration(milliseconds: 300), () { + _showAfterExpandCollapseTimer = Timer(Duration(milliseconds: 300), () { setState(() { _cancelAndRestartTimer(); }); From 5ee660827cd94549dd524c7d9d143dda9a819c4f Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Wed, 16 Jan 2019 10:55:08 +0100 Subject: [PATCH 03/24] ChewieController accessed by an InheritedWidget --- example/lib/main.dart | 58 ++++++---- lib/src/chewie_controller.dart | 182 ++++++++++++++++++++++++++++++ lib/src/chewie_player.dart | 181 +++++++---------------------- lib/src/cupertino_controls.dart | 88 ++++++--------- lib/src/material_controls.dart | 85 ++++++-------- lib/src/player_with_controls.dart | 143 +++++++++-------------- 6 files changed, 380 insertions(+), 357 deletions(-) create mode 100644 lib/src/chewie_controller.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index 040e70cf0..79e8e2fc2 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,4 +1,5 @@ import 'package:chewie/chewie.dart'; +import 'package:chewie/src/chewie_controller.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; @@ -22,14 +23,33 @@ class ChewieDemo extends StatefulWidget { class _ChewieDemoState extends State { TargetPlatform _platform; - VideoPlayerController _controller; + VideoPlayerController _videoPlayerController; + ChewieController _chewieController; @override void initState() { super.initState(); - _controller = VideoPlayerController.network( + _videoPlayerController = VideoPlayerController.network( 'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4', ); + _chewieController = ChewieController( + _videoPlayerController, aspectRatio: 3 / 2, + autoPlay: true, + looping: true, + // Try playing around with some of these other options: + + // showControls: false, + // materialProgressColors: ChewieProgressColors( + // playedColor: Colors.red, + // handleColor: Colors.blue, + // backgroundColor: Colors.grey, + // bufferedColor: Colors.lightGreen, + // ), + // placeholder: Container( + // color: Colors.grey, + // ), + // autoInitialize: true, + ); } @override @@ -48,34 +68,24 @@ class _ChewieDemoState extends State { Expanded( child: Center( child: Chewie( - _controller, - aspectRatio: 3 / 2, - autoPlay: true, - looping: true, - - // Try playing around with some of these other options: - - // showControls: false, - // materialProgressColors: ChewieProgressColors( - // playedColor: Colors.red, - // handleColor: Colors.blue, - // backgroundColor: Colors.grey, - // bufferedColor: Colors.lightGreen, - // ), - // placeholder: Container( - // color: Colors.grey, - // ), - // autoInitialize: true, + controller: _chewieController, ), ), ), + FlatButton( + onPressed: () { + _chewieController.enterFullscreen(); + }, + child: Text('Fullscreen'), + ), Row( children: [ Expanded( child: FlatButton( onPressed: () { setState(() { - _controller = VideoPlayerController.network( + _chewieController.videoPlayerController = + VideoPlayerController.network( 'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4', ); }); @@ -90,8 +100,10 @@ class _ChewieDemoState extends State { child: FlatButton( onPressed: () { setState(() { - _controller = VideoPlayerController.network( - 'https://www.sample-videos.com/video123/mp4/480/big_buck_bunny_480p_20mb.mp4', + _chewieController.videoPlayerController = + VideoPlayerController.network( + 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4', +// 'https://www.sample-videos.com/video123/mp4/480/big_buck_bunny_480p_20mb.mp4', ); }); }, diff --git a/lib/src/chewie_controller.dart b/lib/src/chewie_controller.dart new file mode 100644 index 000000000..24596e63f --- /dev/null +++ b/lib/src/chewie_controller.dart @@ -0,0 +1,182 @@ +import 'package:chewie/src/chewie_progress_colors.dart'; +import 'package:flutter/material.dart'; +import 'package:video_player/video_player.dart'; + +/// The state of the [ChewieController]. +@immutable +class ChewieValue { + ChewieValue( + this.videoPlayerController, { + this.isFullScreen = false, + }); + + /// True if the video is currently playing fullscreen + final bool isFullScreen; + + /// The controller for the video you want to play + final VideoPlayerController videoPlayerController; + + ChewieValue copyWith({ + VideoPlayerController videoPlayerController, + bool isFullScreen, + }) { + return ChewieValue( + videoPlayerController ?? this.videoPlayerController, + isFullScreen: isFullScreen ?? this.isFullScreen, + ); + } + + @override + String toString() { + return '$runtimeType(' + 'isFullscreen: $isFullScreen, ' + 'videoPlayerController: $videoPlayerController, '; + } +} + +class ChewieController extends ValueNotifier { + ChewieController( + VideoPlayerController videoPlayerController, { + this.aspectRatio, + this.autoInitialize = false, + this.autoPlay = false, + this.startAt, + this.looping = false, + this.fullScreenByDefault = false, + this.cupertinoProgressColors, + this.materialProgressColors, + this.placeholder, + this.showControls = true, + this.allowedScreenSleep = true, + this.isLive = false, + }) : assert(videoPlayerController != null, + 'You must provide a controller to play a video'), + super(ChewieValue(videoPlayerController)) { + _initialize(); + } + + /// Initialize the Video on Startup. This will prep the video for playback. + final bool autoInitialize; + + /// Play the video as soon as it's displayed + final bool autoPlay; + + /// Start video at a certain position + final Duration startAt; + + /// Whether or not the video should loop + final bool looping; + + /// Whether or not to show the controls + final bool showControls; + + /// The Aspect Ratio of the Video. Important to get the correct size of the + /// video! + /// + /// Will fallback to fitting within the space allowed. + final double aspectRatio; + + /// The colors to use for controls on iOS. By default, the iOS player uses + /// colors sampled from the original iOS 11 designs. + final ChewieProgressColors cupertinoProgressColors; + + /// The colors to use for the Material Progress Bar. By default, the Material + /// player uses the colors from your Theme. + final ChewieProgressColors materialProgressColors; + + /// The placeholder is displayed underneath the Video before it is initialized + /// or played. + final Widget placeholder; + + /// Defines if the player will start in fullscreen when play is pressed + final bool fullScreenByDefault; + + /// Defines if the player will sleep in fullscreen or not + final bool allowedScreenSleep; + + /// Defines if the controls should be for live stream video + final bool isLive; + + Future _initialize() async { + await value.videoPlayerController.setLooping(looping); + + if (autoInitialize || autoPlay) { + await value.videoPlayerController.initialize(); + } + + if (autoPlay) { + if (fullScreenByDefault) { + enterFullscreen(); + } + + await value.videoPlayerController.play(); + } + + if (startAt != null) { + await value.videoPlayerController.seekTo(startAt); + } + + if (fullScreenByDefault) { + value.videoPlayerController.addListener(() async { + if (await value.videoPlayerController.value.isPlaying && + !value.isFullScreen) { + enterFullscreen(); + } + }); + } + } + + void enterFullscreen() { + value = value.copyWith(isFullScreen: true); + } + + void exitFullscreen() { + value = value.copyWith(isFullScreen: false); + } + + void toggleFullscreen() { + value = value.copyWith(isFullScreen: !value.isFullScreen); + } + + void play() { + value.videoPlayerController.play(); + } + + void pause() { + value.videoPlayerController.pause(); + } + + // TODO: Do we really need the ability to change the controller? + set videoPlayerController(VideoPlayerController controller) { + if (value.videoPlayerController.dataSource != controller.dataSource) { + // FIXME: The VideoPlayer widget still tries to access the controller + value.videoPlayerController.dispose(); + value = value.copyWith(videoPlayerController: controller); + exitFullscreen(); + _initialize(); + } + } +} + +class ChewieControllerProvider extends InheritedWidget { + const ChewieControllerProvider({ + Key key, + @required this.controller, + @required Widget child, + }) : assert(controller != null), + assert(child != null), + super(key: key, child: child); + + final ChewieController controller; + + static ChewieController of(BuildContext context) { + final ChewieControllerProvider chewieControllerProvider = + context.inheritFromWidgetOfExactType(ChewieControllerProvider); + + return chewieControllerProvider.controller; + } + + @override + bool updateShouldNotify(ChewieControllerProvider old) => + controller != old.controller; +} diff --git a/lib/src/chewie_player.dart b/lib/src/chewie_player.dart index 522290440..b60c8d5b8 100644 --- a/lib/src/chewie_player.dart +++ b/lib/src/chewie_player.dart @@ -1,112 +1,63 @@ import 'dart:async'; -import 'package:chewie/src/chewie_progress_colors.dart'; +import 'package:chewie/src/chewie_controller.dart'; import 'package:chewie/src/player_with_controls.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:screen/screen.dart'; -import 'package:video_player/video_player.dart'; /// 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 { - /// The Controller for the Video you want to play - final VideoPlayerController controller; - - /// Initialize the Video on Startup. This will prep the video for playback. - final bool autoInitialize; - - /// Play the video as soon as it's displayed - final bool autoPlay; - - /// Start video at a certain position - final Duration startAt; - - /// Whether or not the video should loop - final bool looping; - - /// Whether or not to show the controls - final bool showControls; - - /// The Aspect Ratio of the Video. Important to get the correct size of the - /// video! - /// - /// Will fallback to fitting within the space allowed. - final double aspectRatio; - - /// The colors to use for controls on iOS. By default, the iOS player uses - /// colors sampled from the original iOS 11 designs. - final ChewieProgressColors cupertinoProgressColors; - - /// The colors to use for the Material Progress Bar. By default, the Material - /// player uses the colors from your Theme. - final ChewieProgressColors materialProgressColors; - - /// The placeholder is displayed underneath the Video before it is initialized - /// or played. - final Widget placeholder; - - /// Defines if the player will start in fullscreen when play is pressed - final bool fullScreenByDefault; - - /// Defines if the player will sleep in fullscreen or not - final bool allowedScreenSleep; - - /// Defines if the controls should be for live stream video - final bool isLive; - - Chewie( - this.controller, { + Chewie({ Key key, - this.aspectRatio, - this.autoInitialize = false, - this.autoPlay = false, - this.startAt, - this.looping = false, - this.fullScreenByDefault = false, - this.cupertinoProgressColors, - this.materialProgressColors, - this.placeholder, - this.showControls = true, - this.allowedScreenSleep = true, - this.isLive = false, - }) : assert(controller != null, - 'You must provide a controller to play a video'), + this.controller, + }) : assert(controller != null, 'You must provide a chewie controller'), super(key: key); + /// The [ChewieController] + final ChewieController controller; + @override - State createState() { - return _ChewiePlayerState(); + ChewieState createState() { + return ChewieState(); } } -class _ChewiePlayerState extends State { - VideoPlayerController _controller; +class ChewieState extends State { bool _isFullScreen = false; @override - Widget build(BuildContext context) { - return PlayerWithControls( - controller: _controller, - onExpandCollapse: () => _pushFullScreenWidget(context), - aspectRatio: widget.aspectRatio ?? _calculateAspectRatio(context), - cupertinoProgressColors: widget.cupertinoProgressColors, - materialProgressColors: widget.materialProgressColors, - placeholder: widget.placeholder, - autoPlay: widget.autoPlay, - showControls: widget.showControls, - isLive: widget.isLive, - ); + void initState() { + super.initState(); + widget.controller.addListener(listener); } @override - void initState() { - super.initState(); - _controller = widget.controller; - _initialize(); + void dispose() { + widget.controller.removeListener(listener); + super.dispose(); + } + + void listener() async { + if (widget.controller.value.isFullScreen && !_isFullScreen) { + _isFullScreen = true; + await _pushFullScreenWidget(context); + } else if (_isFullScreen) { + Navigator.of(context).pop(); + _isFullScreen = false; + } + } + + @override + Widget build(BuildContext context) { + return ChewieControllerProvider( + controller: widget.controller, + child: PlayerWithControls(), + ); } Widget _buildFullScreenVideo( @@ -116,15 +67,9 @@ class _ChewiePlayerState extends State { body: Container( alignment: Alignment.center, color: Colors.black, - child: PlayerWithControls( - controller: _controller, - onExpandCollapse: () => - Future.value(Navigator.of(context).pop()), - aspectRatio: widget.aspectRatio ?? _calculateAspectRatio(context), - fullScreen: true, - isLive: widget.isLive, - cupertinoProgressColors: widget.cupertinoProgressColors, - materialProgressColors: widget.materialProgressColors, + child: ChewieControllerProvider( + controller: widget.controller, + child: PlayerWithControls(), ), ), ); @@ -143,48 +88,6 @@ class _ChewiePlayerState extends State { ); } - Future _initialize() async { - await _controller.setLooping(widget.looping); - - if (widget.autoInitialize || widget.autoPlay) { - await _controller.initialize(); - } - - if (widget.autoPlay) { - if (widget.fullScreenByDefault) { - _isFullScreen = true; - await _pushFullScreenWidget(context); - } - - await _controller.play(); - } - - if (widget.startAt != null) { - await _controller.seekTo(widget.startAt); - } - - if (widget.fullScreenByDefault) { - widget.controller.addListener(() async { - if (await widget.controller.value.isPlaying && !_isFullScreen) { - _isFullScreen = true; - await _pushFullScreenWidget(context); - } - }); - } - } - - @override - void didUpdateWidget(Chewie oldWidget) { - super.didUpdateWidget(oldWidget); - - if (widget.controller.dataSource != _controller.dataSource) { - _controller.dispose(); - _controller = widget.controller; - _isFullScreen = false; - _initialize(); - } - } - Future _pushFullScreenWidget(BuildContext context) async { final isAndroid = Theme.of(context).platform == TargetPlatform.android; final TransitionRoute route = PageRouteBuilder( @@ -200,7 +103,7 @@ class _ChewiePlayerState extends State { ]); } - if (!widget.allowedScreenSleep) { + if (!widget.controller.allowedScreenSleep) { Screen.keepOn(true); } @@ -219,12 +122,4 @@ class _ChewiePlayerState extends State { DeviceOrientation.landscapeRight, ]); } - - double _calculateAspectRatio(BuildContext context) { - final size = MediaQuery.of(context).size; - final width = size.width; - final height = size.height; - - return width > height ? width / height : height / width; - } } diff --git a/lib/src/cupertino_controls.dart b/lib/src/cupertino_controls.dart index a099331a9..250878169 100644 --- a/lib/src/cupertino_controls.dart +++ b/lib/src/cupertino_controls.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:math' as math; import 'dart:ui' as ui; +import 'package:chewie/src/chewie_controller.dart'; import 'package:chewie/src/chewie_progress_colors.dart'; import 'package:chewie/src/cupertino_progress_bar.dart'; import 'package:chewie/src/utils.dart'; @@ -13,22 +14,10 @@ import 'package:video_player/video_player.dart'; class CupertinoControls extends StatefulWidget { final Color backgroundColor; final Color iconColor; - final VideoPlayerController controller; - final Future Function() onExpandCollapse; - final bool fullScreen; - final ChewieProgressColors progressColors; - final bool autoPlay; - final bool isLive; CupertinoControls({ @required this.backgroundColor, @required this.iconColor, - @required this.controller, - @required this.onExpandCollapse, - @required this.fullScreen, - @required this.progressColors, - @required this.autoPlay, - @required this.isLive, }); @override @@ -46,21 +35,24 @@ class _CupertinoControlsState extends State { Timer _expandCollapseTimer; Timer _initTimer; + VideoPlayerController controller; + ChewieController chewieController; + @override Widget build(BuildContext context) { final backgroundColor = widget.backgroundColor; final iconColor = widget.iconColor; - final controller = widget.controller; + chewieController = ChewieControllerProvider.of(context); + controller = chewieController.value.videoPlayerController; final orientation = MediaQuery.of(context).orientation; final barHeight = orientation == Orientation.portrait ? 30.0 : 47.0; final buttonPadding = orientation == Orientation.portrait ? 16.0 : 24.0; return Column( children: [ - _buildTopBar( - backgroundColor, iconColor, controller, barHeight, buttonPadding), + _buildTopBar(backgroundColor, iconColor, barHeight, buttonPadding), _buildHitArea(), - _buildBottomBar(backgroundColor, iconColor, controller, barHeight), + _buildBottomBar(backgroundColor, iconColor, barHeight), ], ); } @@ -72,33 +64,26 @@ class _CupertinoControlsState extends State { } void _dispose() { - widget.controller.removeListener(_updateState); + controller.removeListener(_updateState); _hideTimer?.cancel(); _expandCollapseTimer?.cancel(); _initTimer?.cancel(); } @override - void initState() { - _initialize(); - - super.initState(); - } + void didChangeDependencies() { + chewieController = ChewieControllerProvider.of(context); + controller = chewieController.value.videoPlayerController; - @override - void didUpdateWidget(CupertinoControls oldWidget) { - super.didUpdateWidget(oldWidget); + _dispose(); + _initialize(); - if (widget.controller.dataSource != oldWidget.controller.dataSource) { - _dispose(); - _initialize(); - } + super.didChangeDependencies(); } AnimatedOpacity _buildBottomBar( Color backgroundColor, Color iconColor, - VideoPlayerController controller, double barHeight, ) { return AnimatedOpacity( @@ -122,7 +107,7 @@ class _CupertinoControlsState extends State { Radius.circular(10.0), ), ), - child: widget.isLive + child: chewieController.isLive ? Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -185,7 +170,7 @@ class _CupertinoControlsState extends State { ), child: Center( child: Icon( - widget.fullScreen + chewieController.value.isFullScreen ? OpenIconicIcons.fullscreenExit : OpenIconicIcons.fullscreenEnter, color: iconColor, @@ -376,7 +361,6 @@ class _CupertinoControlsState extends State { Widget _buildTopBar( Color backgroundColor, Color iconColor, - VideoPlayerController controller, double barHeight, double buttonPadding, ) { @@ -410,13 +394,12 @@ class _CupertinoControlsState extends State { } Future _initialize() async { - widget.controller.addListener(_updateState); + controller.addListener(_updateState); _updateState(); - if ((widget.controller.value != null && - widget.controller.value.isPlaying) || - widget.autoPlay) { + if ((controller.value != null && controller.value.isPlaying) || + chewieController.autoPlay) { _startHideTimer(); } @@ -431,11 +414,10 @@ class _CupertinoControlsState extends State { setState(() { _hideStuff = true; - widget.onExpandCollapse().then((dynamic _) { - _expandCollapseTimer = Timer(Duration(milliseconds: 300), () { - setState(() { - _cancelAndRestartTimer(); - }); + chewieController.toggleFullscreen(); + _expandCollapseTimer = Timer(Duration(milliseconds: 300), () { + setState(() { + _cancelAndRestartTimer(); }); }); }); @@ -446,14 +428,14 @@ class _CupertinoControlsState extends State { child: Padding( padding: EdgeInsets.only(right: 12.0), child: CupertinoVideoProgressBar( - widget.controller, + controller, onDragStart: () { _hideTimer?.cancel(); }, onDragEnd: () { _startHideTimer(); }, - colors: widget.progressColors ?? + colors: chewieController.cupertinoProgressColors ?? ChewieProgressColors( playedColor: Color.fromARGB( 120, @@ -487,19 +469,19 @@ class _CupertinoControlsState extends State { void _playPause() { setState(() { - if (widget.controller.value.isPlaying) { + if (controller.value.isPlaying) { _hideStuff = false; _hideTimer?.cancel(); - widget.controller.pause(); + controller.pause(); } else { _cancelAndRestartTimer(); - if (!widget.controller.value.initialized) { - widget.controller.initialize().then((_) { - widget.controller.play(); + if (!controller.value.initialized) { + controller.initialize().then((_) { + controller.play(); }); } else { - widget.controller.play(); + controller.play(); } } }); @@ -509,14 +491,14 @@ class _CupertinoControlsState extends State { _cancelAndRestartTimer(); final beginning = Duration(seconds: 0).inMilliseconds; final skip = (_latestValue.position - Duration(seconds: 15)).inMilliseconds; - widget.controller.seekTo(Duration(milliseconds: math.max(skip, beginning))); + controller.seekTo(Duration(milliseconds: math.max(skip, beginning))); } void _skipForward() { _cancelAndRestartTimer(); final end = _latestValue.duration.inMilliseconds; final skip = (_latestValue.position + Duration(seconds: 15)).inMilliseconds; - widget.controller.seekTo(Duration(milliseconds: math.min(skip, end))); + controller.seekTo(Duration(milliseconds: math.min(skip, end))); } void _startHideTimer() { @@ -529,7 +511,7 @@ class _CupertinoControlsState extends State { void _updateState() { setState(() { - _latestValue = widget.controller.value; + _latestValue = controller.value; }); } } diff --git a/lib/src/material_controls.dart b/lib/src/material_controls.dart index 5fa14854d..2957829d9 100644 --- a/lib/src/material_controls.dart +++ b/lib/src/material_controls.dart @@ -1,28 +1,14 @@ import 'dart:async'; +import 'package:chewie/src/chewie_controller.dart'; import 'package:chewie/src/chewie_progress_colors.dart'; import 'package:chewie/src/material_progress_bar.dart'; import 'package:chewie/src/utils.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; class MaterialControls extends StatefulWidget { - final VideoPlayerController controller; - final bool fullScreen; - final Future Function() onExpandCollapse; - final ChewieProgressColors progressColors; - final bool autoPlay; - final bool isLive; - - MaterialControls({ - @required this.controller, - @required this.fullScreen, - @required this.onExpandCollapse, - @required this.progressColors, - @required this.autoPlay, - @required this.isLive, - }); + MaterialControls({Key key}) : super(key: key); @override State createState() { @@ -42,6 +28,9 @@ class _MaterialControlsState extends State { final barHeight = 48.0; final marginSize = 5.0; + VideoPlayerController controller; + ChewieController chewieController; + @override Widget build(BuildContext context) { return Column( @@ -56,7 +45,7 @@ class _MaterialControlsState extends State { ), ) : _buildHitArea(), - _buildBottomBar(context, widget.controller), + _buildBottomBar(context), ], ); } @@ -68,31 +57,25 @@ class _MaterialControlsState extends State { } void _dispose() { - widget.controller.removeListener(_updateState); + controller.removeListener(_updateState); _hideTimer?.cancel(); _showTimer?.cancel(); _showAfterExpandCollapseTimer?.cancel(); } @override - void initState() { + void didChangeDependencies() { + chewieController = ChewieControllerProvider.of(context); + controller = chewieController.value.videoPlayerController; + + _dispose(); _initialize(); - super.initState(); - } - - @override - void didUpdateWidget(MaterialControls oldWidget) { - super.didUpdateWidget(oldWidget); - if (widget.controller.dataSource != oldWidget.controller.dataSource) { - _dispose(); - _initialize(); - } + super.didChangeDependencies(); } AnimatedOpacity _buildBottomBar( BuildContext context, - VideoPlayerController controller, ) { final iconColor = Theme.of(context).textTheme.button.color; @@ -105,10 +88,10 @@ class _MaterialControlsState extends State { child: Row( children: [ _buildPlayPause(controller), - widget.isLive + chewieController.isLive ? Expanded(child: const Text('LIVE')) : _buildPosition(iconColor), - widget.isLive ? const SizedBox() : _buildProgressBar(), + chewieController.isLive ? const SizedBox() : _buildProgressBar(), _buildMuteButton(controller), _buildExpandButton(), ], @@ -132,7 +115,9 @@ class _MaterialControlsState extends State { ), child: Center( child: Icon( - widget.fullScreen ? Icons.fullscreen_exit : Icons.fullscreen, + chewieController.value.isFullScreen + ? Icons.fullscreen_exit + : Icons.fullscreen, ), ), ), @@ -264,13 +249,12 @@ class _MaterialControlsState extends State { } Future _initialize() async { - widget.controller.addListener(_updateState); + controller.addListener(_updateState); _updateState(); - if ((widget.controller.value != null && - widget.controller.value.isPlaying) || - widget.autoPlay) { + if ((controller.value != null && controller.value.isPlaying) || + chewieController.autoPlay) { _startHideTimer(); } @@ -285,11 +269,10 @@ class _MaterialControlsState extends State { setState(() { _hideStuff = true; - widget.onExpandCollapse().then((dynamic _) { - _showAfterExpandCollapseTimer = Timer(Duration(milliseconds: 300), () { - setState(() { - _cancelAndRestartTimer(); - }); + chewieController.toggleFullscreen(); + _showAfterExpandCollapseTimer = Timer(Duration(milliseconds: 300), () { + setState(() { + _cancelAndRestartTimer(); }); }); }); @@ -297,19 +280,19 @@ class _MaterialControlsState extends State { void _playPause() { setState(() { - if (widget.controller.value.isPlaying) { + if (controller.value.isPlaying) { _hideStuff = false; _hideTimer?.cancel(); - widget.controller.pause(); + controller.pause(); } else { _cancelAndRestartTimer(); - if (!widget.controller.value.initialized) { - widget.controller.initialize().then((_) { - widget.controller.play(); + if (!controller.value.initialized) { + controller.initialize().then((_) { + controller.play(); }); } else { - widget.controller.play(); + controller.play(); } } }); @@ -325,7 +308,7 @@ class _MaterialControlsState extends State { void _updateState() { setState(() { - _latestValue = widget.controller.value; + _latestValue = controller.value; }); } @@ -334,7 +317,7 @@ class _MaterialControlsState extends State { child: Padding( padding: EdgeInsets.only(right: 20.0), child: MaterialVideoProgressBar( - widget.controller, + controller, onDragStart: () { setState(() { _dragging = true; @@ -349,7 +332,7 @@ class _MaterialControlsState extends State { _startHideTimer(); }, - colors: widget.progressColors ?? + colors: chewieController.materialProgressColors ?? ChewieProgressColors( playedColor: Theme.of(context).accentColor, handleColor: Theme.of(context).accentColor, diff --git a/lib/src/player_with_controls.dart b/lib/src/player_with_controls.dart index faa16ca08..eca4ba81a 100644 --- a/lib/src/player_with_controls.dart +++ b/lib/src/player_with_controls.dart @@ -1,77 +1,50 @@ -import 'dart:async'; import 'dart:ui'; -import 'package:chewie/src/chewie_progress_colors.dart'; +import 'package:chewie/src/chewie_controller.dart'; import 'package:chewie/src/cupertino_controls.dart'; import 'package:chewie/src/material_controls.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; -class PlayerWithControls extends StatefulWidget { - final VideoPlayerController controller; - final Future Function() onExpandCollapse; - final bool fullScreen; - final ChewieProgressColors cupertinoProgressColors; - final ChewieProgressColors materialProgressColors; - final Widget placeholder; - final double aspectRatio; - final bool autoPlay; - final bool showControls; - final bool isLive; +class PlayerWithControls extends StatelessWidget { + PlayerWithControls({Key key}) : super(key: key); - PlayerWithControls({ - Key key, - @required this.controller, - @required this.onExpandCollapse, - @required this.aspectRatio, - this.fullScreen = false, - this.showControls = true, - this.cupertinoProgressColors, - this.materialProgressColors, - this.placeholder, - this.autoPlay, - this.isLive = false, - }) : super(key: key); - - @override - State createState() { - return _VideoPlayerWithControlsState(); - } -} - -class _VideoPlayerWithControlsState extends State { @override Widget build(BuildContext context) { - final controller = widget.controller; + final ChewieController chewieController = + ChewieControllerProvider.of(context); return Center( child: Container( width: MediaQuery.of(context).size.width, child: AspectRatio( - aspectRatio: widget.aspectRatio, - child: _buildPlayerWithControls(controller, context), + aspectRatio: + chewieController.aspectRatio ?? _calculateAspectRatio(context), + child: _buildPlayerWithControls(chewieController, context), ), ), ); } Container _buildPlayerWithControls( - VideoPlayerController controller, BuildContext context) { + ChewieController chewieController, BuildContext context) { return Container( child: Stack( children: [ - widget.placeholder ?? Container(), + chewieController.placeholder ?? Container(), Center( child: Hero( - tag: controller, + tag: chewieController.value.videoPlayerController, child: AspectRatio( - aspectRatio: widget.aspectRatio, - child: VideoPlayer(controller), + aspectRatio: chewieController.aspectRatio ?? + _calculateAspectRatio(context), + child: + VideoPlayer(chewieController.value.videoPlayerController), ), ), ), - _buildControls(context, controller), + _buildControls(context, chewieController), ], ), ); @@ -79,60 +52,56 @@ class _VideoPlayerWithControlsState extends State { Widget _buildControls( BuildContext context, - VideoPlayerController controller, + ChewieController chewieController, ) { - return widget.showControls + return chewieController.showControls ? Theme.of(context).platform == TargetPlatform.android - ? MaterialControls( - controller: controller, - onExpandCollapse: widget.onExpandCollapse, - fullScreen: widget.fullScreen, - progressColors: widget.materialProgressColors, - autoPlay: widget.autoPlay, - isLive: widget.isLive, - ) + ? MaterialControls() : CupertinoControls( backgroundColor: Color.fromRGBO(41, 41, 41, 0.7), iconColor: Color.fromARGB(255, 200, 200, 200), - controller: controller, - onExpandCollapse: widget.onExpandCollapse, - fullScreen: widget.fullScreen, - progressColors: widget.cupertinoProgressColors, - autoPlay: widget.autoPlay, - isLive: widget.isLive, ) : Container(); } - @override - void initState() { - // Hack to show the video when it starts playing. Should be fixed by the - // Plugin IMO. - widget.controller.addListener(_onPlay); + double _calculateAspectRatio(BuildContext context) { + final size = MediaQuery.of(context).size; + final width = size.width; + final height = size.height; - super.initState(); + return width > height ? width / height : height / width; } - @override - void didUpdateWidget(PlayerWithControls oldWidget) { - super.didUpdateWidget(oldWidget); - - if (widget.controller.dataSource != oldWidget.controller.dataSource) { - widget.controller.addListener(_onPlay); - } - } - - @override - dispose() { - widget.controller.removeListener(_onPlay); - super.dispose(); - } - - void _onPlay() { - if (widget.controller.value.isPlaying) { - setState(() { - widget.controller.removeListener(_onPlay); - }); - } - } +// TODO: Add playback hack somewhere or better: fix in the VideoPlayer plugin +// @override +// void initState() { +// // Hack to show the video when it starts playing. Should be fixed by the +// // Plugin IMO. +// widget.controller.addListener(_onPlay); +// +// super.initState(); +// } +// +// @override +// void didUpdateWidget(PlayerWithControls oldWidget) { +// super.didUpdateWidget(oldWidget); +// +// if (widget.controller.dataSource != oldWidget.controller.dataSource) { +// widget.controller.addListener(_onPlay); +// } +// } +// +// @override +// dispose() { +// widget.controller.removeListener(_onPlay); +// super.dispose(); +// } +// +// void _onPlay() { +// if (widget.controller.value.isPlaying) { +// setState(() { +// widget.controller.removeListener(_onPlay); +// }); +// } +// } } From 5961f50fa43bf5d5240ff7cd72d2a6d37e1b0688 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Wed, 16 Jan 2019 16:09:53 +0100 Subject: [PATCH 04/24] Add myself to the authors --- pubspec.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 8e3f2f171..f38cc7d38 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,9 @@ name: chewie description: A video player for Flutter with Cupertino and Material play controls version: 0.8.0 homepage: https://github.com/brianegan/chewie -author: Brian Egan +authors: + - Brian Egan + - Ben Hagen environment: sdk: ">=2.0.0-dev.28.0 <3.0.0" From b578b47f0c011df41614c202f5ee0ac0ceb372bd Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Wed, 16 Jan 2019 16:10:14 +0100 Subject: [PATCH 05/24] Remove comments --- pubspec.yaml | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index f38cc7d38..a96de9777 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,44 +20,5 @@ dev_dependencies: flutter_test: sdk: flutter -# For information on the generic Dart part of this file, see the -# following page: https://www.dartlang.org/tools/pub/pubspec - -# The following section is specific to Flutter. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.io/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.io/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.io/custom-fonts/#from-packages From 79abb082af1e910c46ad56a64c0f5a3607cea770 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Wed, 16 Jan 2019 16:29:14 +0100 Subject: [PATCH 06/24] Shorten API by adding getters --- lib/src/chewie_controller.dart | 5 +++++ lib/src/chewie_player.dart | 2 +- lib/src/cupertino_controls.dart | 6 +++--- lib/src/material_controls.dart | 4 ++-- lib/src/player_with_controls.dart | 4 ++-- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/src/chewie_controller.dart b/lib/src/chewie_controller.dart index 24596e63f..012173481 100644 --- a/lib/src/chewie_controller.dart +++ b/lib/src/chewie_controller.dart @@ -97,6 +97,11 @@ class ChewieController extends ValueNotifier { /// Defines if the controls should be for live stream video final bool isLive; + bool get isFullScreen => value.isFullScreen; + + VideoPlayerController get videoPlayerController => + value.videoPlayerController; + Future _initialize() async { await value.videoPlayerController.setLooping(looping); diff --git a/lib/src/chewie_player.dart b/lib/src/chewie_player.dart index b60c8d5b8..060c21953 100644 --- a/lib/src/chewie_player.dart +++ b/lib/src/chewie_player.dart @@ -43,7 +43,7 @@ class ChewieState extends State { } void listener() async { - if (widget.controller.value.isFullScreen && !_isFullScreen) { + if (widget.controller.isFullScreen && !_isFullScreen) { _isFullScreen = true; await _pushFullScreenWidget(context); } else if (_isFullScreen) { diff --git a/lib/src/cupertino_controls.dart b/lib/src/cupertino_controls.dart index 250878169..d133a5662 100644 --- a/lib/src/cupertino_controls.dart +++ b/lib/src/cupertino_controls.dart @@ -43,7 +43,7 @@ class _CupertinoControlsState extends State { final backgroundColor = widget.backgroundColor; final iconColor = widget.iconColor; chewieController = ChewieControllerProvider.of(context); - controller = chewieController.value.videoPlayerController; + controller = chewieController.videoPlayerController; final orientation = MediaQuery.of(context).orientation; final barHeight = orientation == Orientation.portrait ? 30.0 : 47.0; final buttonPadding = orientation == Orientation.portrait ? 16.0 : 24.0; @@ -73,7 +73,7 @@ class _CupertinoControlsState extends State { @override void didChangeDependencies() { chewieController = ChewieControllerProvider.of(context); - controller = chewieController.value.videoPlayerController; + controller = chewieController.videoPlayerController; _dispose(); _initialize(); @@ -170,7 +170,7 @@ class _CupertinoControlsState extends State { ), child: Center( child: Icon( - chewieController.value.isFullScreen + chewieController.isFullScreen ? OpenIconicIcons.fullscreenExit : OpenIconicIcons.fullscreenEnter, color: iconColor, diff --git a/lib/src/material_controls.dart b/lib/src/material_controls.dart index 2957829d9..201c130a8 100644 --- a/lib/src/material_controls.dart +++ b/lib/src/material_controls.dart @@ -66,7 +66,7 @@ class _MaterialControlsState extends State { @override void didChangeDependencies() { chewieController = ChewieControllerProvider.of(context); - controller = chewieController.value.videoPlayerController; + controller = chewieController.videoPlayerController; _dispose(); _initialize(); @@ -115,7 +115,7 @@ class _MaterialControlsState extends State { ), child: Center( child: Icon( - chewieController.value.isFullScreen + chewieController.isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen, ), diff --git a/lib/src/player_with_controls.dart b/lib/src/player_with_controls.dart index eca4ba81a..b88878e8c 100644 --- a/lib/src/player_with_controls.dart +++ b/lib/src/player_with_controls.dart @@ -35,12 +35,12 @@ class PlayerWithControls extends StatelessWidget { chewieController.placeholder ?? Container(), Center( child: Hero( - tag: chewieController.value.videoPlayerController, + tag: chewieController.videoPlayerController, child: AspectRatio( aspectRatio: chewieController.aspectRatio ?? _calculateAspectRatio(context), child: - VideoPlayer(chewieController.value.videoPlayerController), + VideoPlayer(chewieController.videoPlayerController), ), ), ), From 79011c777ebdcaf8027ee9846901d405ceb41fd3 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Thu, 17 Jan 2019 13:34:59 +0100 Subject: [PATCH 07/24] Remove setter for videoPlayerController --- example/lib/main.dart | 40 ++++++++++++++++++--------- lib/src/chewie_controller.dart | 49 +++++++++++----------------------- 2 files changed, 44 insertions(+), 45 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 79e8e2fc2..146ad9838 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -23,17 +23,20 @@ class ChewieDemo extends StatefulWidget { class _ChewieDemoState extends State { TargetPlatform _platform; - VideoPlayerController _videoPlayerController; + VideoPlayerController _videoPlayerController1; + VideoPlayerController _videoPlayerController2; ChewieController _chewieController; @override void initState() { super.initState(); - _videoPlayerController = VideoPlayerController.network( - 'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4', - ); + _videoPlayerController1 = VideoPlayerController.network( + 'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4'); + _videoPlayerController2 = VideoPlayerController.network( + 'https://www.sample-videos.com/video123/mp4/480/big_buck_bunny_480p_20mb.mp4'); _chewieController = ChewieController( - _videoPlayerController, aspectRatio: 3 / 2, + videoPlayerController: _videoPlayerController1, + aspectRatio: 3 / 2, autoPlay: true, looping: true, // Try playing around with some of these other options: @@ -52,6 +55,14 @@ class _ChewieDemoState extends State { ); } + @override + void dispose() { + _videoPlayerController1.dispose(); + _videoPlayerController2.dispose(); + _chewieController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return MaterialApp( @@ -84,9 +95,12 @@ class _ChewieDemoState extends State { child: FlatButton( onPressed: () { setState(() { - _chewieController.videoPlayerController = - VideoPlayerController.network( - 'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4', + _chewieController.dispose(); + _chewieController = ChewieController( + videoPlayerController: _videoPlayerController1, + aspectRatio: 3 / 2, + autoPlay: true, + looping: true, ); }); }, @@ -100,10 +114,12 @@ class _ChewieDemoState extends State { child: FlatButton( onPressed: () { setState(() { - _chewieController.videoPlayerController = - VideoPlayerController.network( - 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4', -// 'https://www.sample-videos.com/video123/mp4/480/big_buck_bunny_480p_20mb.mp4', + _chewieController.dispose(); + _chewieController = ChewieController( + videoPlayerController: _videoPlayerController2, + aspectRatio: 3 / 2, + autoPlay: true, + looping: true, ); }); }, diff --git a/lib/src/chewie_controller.dart b/lib/src/chewie_controller.dart index 012173481..87b7ff4c5 100644 --- a/lib/src/chewie_controller.dart +++ b/lib/src/chewie_controller.dart @@ -5,23 +5,18 @@ import 'package:video_player/video_player.dart'; /// The state of the [ChewieController]. @immutable class ChewieValue { - ChewieValue( - this.videoPlayerController, { + ChewieValue({ this.isFullScreen = false, }); /// True if the video is currently playing fullscreen final bool isFullScreen; - /// The controller for the video you want to play - final VideoPlayerController videoPlayerController; - ChewieValue copyWith({ VideoPlayerController videoPlayerController, bool isFullScreen, }) { return ChewieValue( - videoPlayerController ?? this.videoPlayerController, isFullScreen: isFullScreen ?? this.isFullScreen, ); } @@ -29,14 +24,13 @@ class ChewieValue { @override String toString() { return '$runtimeType(' - 'isFullscreen: $isFullScreen, ' - 'videoPlayerController: $videoPlayerController, '; + 'isFullscreen: $isFullScreen, '; } } class ChewieController extends ValueNotifier { - ChewieController( - VideoPlayerController videoPlayerController, { + ChewieController({ + this.videoPlayerController, this.aspectRatio, this.autoInitialize = false, this.autoPlay = false, @@ -51,10 +45,13 @@ class ChewieController extends ValueNotifier { this.isLive = false, }) : assert(videoPlayerController != null, 'You must provide a controller to play a video'), - super(ChewieValue(videoPlayerController)) { + super(ChewieValue()) { _initialize(); } + /// The controller for the video you want to play + final VideoPlayerController videoPlayerController; + /// Initialize the Video on Startup. This will prep the video for playback. final bool autoInitialize; @@ -99,14 +96,11 @@ class ChewieController extends ValueNotifier { bool get isFullScreen => value.isFullScreen; - VideoPlayerController get videoPlayerController => - value.videoPlayerController; - Future _initialize() async { - await value.videoPlayerController.setLooping(looping); + await videoPlayerController.setLooping(looping); if (autoInitialize || autoPlay) { - await value.videoPlayerController.initialize(); + await videoPlayerController.initialize(); } if (autoPlay) { @@ -114,16 +108,16 @@ class ChewieController extends ValueNotifier { enterFullscreen(); } - await value.videoPlayerController.play(); + await videoPlayerController.play(); } if (startAt != null) { - await value.videoPlayerController.seekTo(startAt); + await videoPlayerController.seekTo(startAt); } if (fullScreenByDefault) { - value.videoPlayerController.addListener(() async { - if (await value.videoPlayerController.value.isPlaying && + videoPlayerController.addListener(() async { + if (await videoPlayerController.value.isPlaying && !value.isFullScreen) { enterFullscreen(); } @@ -144,22 +138,11 @@ class ChewieController extends ValueNotifier { } void play() { - value.videoPlayerController.play(); + videoPlayerController.play(); } void pause() { - value.videoPlayerController.pause(); - } - - // TODO: Do we really need the ability to change the controller? - set videoPlayerController(VideoPlayerController controller) { - if (value.videoPlayerController.dataSource != controller.dataSource) { - // FIXME: The VideoPlayer widget still tries to access the controller - value.videoPlayerController.dispose(); - value = value.copyWith(videoPlayerController: controller); - exitFullscreen(); - _initialize(); - } + videoPlayerController.pause(); } } From 40e8700404e9dfde35ffb92f08eb0894bfc86a1e Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Thu, 17 Jan 2019 13:35:23 +0100 Subject: [PATCH 08/24] Push version to 1.0.0 -> breaking changes --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index a96de9777..785da5b9b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: chewie description: A video player for Flutter with Cupertino and Material play controls -version: 0.8.0 +version: 1.0.0 homepage: https://github.com/brianegan/chewie authors: - Brian Egan From 5b33793c8a89faa77c38feb7ecdac21af7f37a59 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Thu, 17 Jan 2019 14:03:25 +0100 Subject: [PATCH 09/24] Pause and rewind video when switching --- example/lib/main.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/example/lib/main.dart b/example/lib/main.dart index 146ad9838..b635d3d9d 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -96,6 +96,8 @@ class _ChewieDemoState extends State { onPressed: () { setState(() { _chewieController.dispose(); + _videoPlayerController2.pause(); + _videoPlayerController2.seekTo(Duration(seconds: 0)); _chewieController = ChewieController( videoPlayerController: _videoPlayerController1, aspectRatio: 3 / 2, @@ -115,6 +117,8 @@ class _ChewieDemoState extends State { onPressed: () { setState(() { _chewieController.dispose(); + _videoPlayerController1.pause(); + _videoPlayerController1.seekTo(Duration(seconds: 0)); _chewieController = ChewieController( videoPlayerController: _videoPlayerController2, aspectRatio: 3 / 2, From e9d84e0901a85d49b5ae70d0a384e30f62f29961 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Thu, 17 Jan 2019 15:04:15 +0100 Subject: [PATCH 10/24] Allow replacing the ChewieController --- lib/src/chewie_player.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/src/chewie_player.dart b/lib/src/chewie_player.dart index 060c21953..41c53fe47 100644 --- a/lib/src/chewie_player.dart +++ b/lib/src/chewie_player.dart @@ -42,6 +42,14 @@ class ChewieState extends State { super.dispose(); } + @override + void didUpdateWidget(Chewie oldWidget) { + if (oldWidget.controller != widget.controller) { + widget.controller.addListener(listener); + } + super.didUpdateWidget(oldWidget); + } + void listener() async { if (widget.controller.isFullScreen && !_isFullScreen) { _isFullScreen = true; From bc1268610df2c2d4cad4b374fe9e66800517e058 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Thu, 17 Jan 2019 15:09:22 +0100 Subject: [PATCH 11/24] Switch to using ChangeNotifier We can switch back to using ValueNotifier when we have a lot more values and it is more convenient to change and notify with one `value.copyWith(foo='bar')` instead of explicitly having to call notifyListeners(). Until then the code is just much cleaner without so much boiler plate. --- lib/src/chewie_controller.dart | 49 +++++++++------------------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/lib/src/chewie_controller.dart b/lib/src/chewie_controller.dart index 87b7ff4c5..eb9c19d48 100644 --- a/lib/src/chewie_controller.dart +++ b/lib/src/chewie_controller.dart @@ -2,33 +2,7 @@ import 'package:chewie/src/chewie_progress_colors.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; -/// The state of the [ChewieController]. -@immutable -class ChewieValue { - ChewieValue({ - this.isFullScreen = false, - }); - - /// True if the video is currently playing fullscreen - final bool isFullScreen; - - ChewieValue copyWith({ - VideoPlayerController videoPlayerController, - bool isFullScreen, - }) { - return ChewieValue( - isFullScreen: isFullScreen ?? this.isFullScreen, - ); - } - - @override - String toString() { - return '$runtimeType(' - 'isFullscreen: $isFullScreen, '; - } -} - -class ChewieController extends ValueNotifier { +class ChewieController extends ChangeNotifier { ChewieController({ this.videoPlayerController, this.aspectRatio, @@ -43,9 +17,8 @@ class ChewieController extends ValueNotifier { this.showControls = true, this.allowedScreenSleep = true, this.isLive = false, - }) : assert(videoPlayerController != null, - 'You must provide a controller to play a video'), - super(ChewieValue()) { + }) : assert(videoPlayerController != null, + 'You must provide a controller to play a video') { _initialize(); } @@ -94,7 +67,9 @@ class ChewieController extends ValueNotifier { /// Defines if the controls should be for live stream video final bool isLive; - bool get isFullScreen => value.isFullScreen; + bool _isFullScreen = false; + + bool get isFullScreen => _isFullScreen; Future _initialize() async { await videoPlayerController.setLooping(looping); @@ -117,8 +92,7 @@ class ChewieController extends ValueNotifier { if (fullScreenByDefault) { videoPlayerController.addListener(() async { - if (await videoPlayerController.value.isPlaying && - !value.isFullScreen) { + if (await videoPlayerController.value.isPlaying && !_isFullScreen) { enterFullscreen(); } }); @@ -126,15 +100,18 @@ class ChewieController extends ValueNotifier { } void enterFullscreen() { - value = value.copyWith(isFullScreen: true); + _isFullScreen = true; + notifyListeners(); } void exitFullscreen() { - value = value.copyWith(isFullScreen: false); + _isFullScreen = false; + notifyListeners(); } void toggleFullscreen() { - value = value.copyWith(isFullScreen: !value.isFullScreen); + _isFullScreen = !_isFullScreen; + notifyListeners(); } void play() { From 4b96ceb0a0252646e5a48c9a7beff0275b67404f Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Thu, 17 Jan 2019 15:16:53 +0100 Subject: [PATCH 12/24] Remove todo --- lib/src/player_with_controls.dart | 33 ------------------------------- 1 file changed, 33 deletions(-) diff --git a/lib/src/player_with_controls.dart b/lib/src/player_with_controls.dart index b88878e8c..ce408ab41 100644 --- a/lib/src/player_with_controls.dart +++ b/lib/src/player_with_controls.dart @@ -71,37 +71,4 @@ class PlayerWithControls extends StatelessWidget { return width > height ? width / height : height / width; } - -// TODO: Add playback hack somewhere or better: fix in the VideoPlayer plugin -// @override -// void initState() { -// // Hack to show the video when it starts playing. Should be fixed by the -// // Plugin IMO. -// widget.controller.addListener(_onPlay); -// -// super.initState(); -// } -// -// @override -// void didUpdateWidget(PlayerWithControls oldWidget) { -// super.didUpdateWidget(oldWidget); -// -// if (widget.controller.dataSource != oldWidget.controller.dataSource) { -// widget.controller.addListener(_onPlay); -// } -// } -// -// @override -// dispose() { -// widget.controller.removeListener(_onPlay); -// super.dispose(); -// } -// -// void _onPlay() { -// if (widget.controller.value.isPlaying) { -// setState(() { -// widget.controller.removeListener(_onPlay); -// }); -// } -// } } From f3fa33516701d91adddbf673dbdbb2ce5d76765b Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Thu, 17 Jan 2019 15:59:58 +0100 Subject: [PATCH 13/24] Pass through all methods of VideoPlayerController --- lib/src/chewie_controller.dart | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/src/chewie_controller.dart b/lib/src/chewie_controller.dart index eb9c19d48..b5632bb9a 100644 --- a/lib/src/chewie_controller.dart +++ b/lib/src/chewie_controller.dart @@ -114,12 +114,24 @@ class ChewieController extends ChangeNotifier { notifyListeners(); } - void play() { - videoPlayerController.play(); + Future play() async { + await videoPlayerController.play(); } - void pause() { - videoPlayerController.pause(); + Future setLooping(bool looping) async { + await videoPlayerController.setLooping(looping); + } + + Future pause() async { + await videoPlayerController.pause(); + } + + Future seekTo(Duration moment) async { + await videoPlayerController.seekTo(moment); + } + + Future setVolume(double volume) async { + await videoPlayerController.setVolume(volume); } } From aeac81200e52abb64d253ffceb25609ce0efb1f0 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Thu, 17 Jan 2019 17:28:01 +0100 Subject: [PATCH 14/24] Allow customising controls More finegraned customisation of exisiting controls to be added later. --- lib/chewie.dart | 1 + lib/src/chewie_controller.dart | 5 +++++ lib/src/player_with_controls.dart | 17 +++++++++-------- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/chewie.dart b/lib/chewie.dart index ed95928a7..ce542ebc6 100644 --- a/lib/chewie.dart +++ b/lib/chewie.dart @@ -1,4 +1,5 @@ library chewie; export 'src/chewie_player.dart'; +export 'src/chewie_controller.dart'; export 'src/chewie_progress_colors.dart'; diff --git a/lib/src/chewie_controller.dart b/lib/src/chewie_controller.dart index b5632bb9a..9062081fe 100644 --- a/lib/src/chewie_controller.dart +++ b/lib/src/chewie_controller.dart @@ -15,6 +15,7 @@ class ChewieController extends ChangeNotifier { this.materialProgressColors, this.placeholder, this.showControls = true, + this.customControls, this.allowedScreenSleep = true, this.isLive = false, }) : assert(videoPlayerController != null, @@ -40,6 +41,10 @@ class ChewieController extends ChangeNotifier { /// Whether or not to show the controls final bool showControls; + /// Defines customised controls. Check [MaterialControls] or + /// [CupertinoControls] for reference. + final Widget customControls; + /// The Aspect Ratio of the Video. Important to get the correct size of the /// video! /// diff --git a/lib/src/player_with_controls.dart b/lib/src/player_with_controls.dart index ce408ab41..36370084d 100644 --- a/lib/src/player_with_controls.dart +++ b/lib/src/player_with_controls.dart @@ -39,8 +39,7 @@ class PlayerWithControls extends StatelessWidget { child: AspectRatio( aspectRatio: chewieController.aspectRatio ?? _calculateAspectRatio(context), - child: - VideoPlayer(chewieController.videoPlayerController), + child: VideoPlayer(chewieController.videoPlayerController), ), ), ), @@ -55,12 +54,14 @@ class PlayerWithControls extends StatelessWidget { ChewieController chewieController, ) { return chewieController.showControls - ? Theme.of(context).platform == TargetPlatform.android - ? MaterialControls() - : CupertinoControls( - backgroundColor: Color.fromRGBO(41, 41, 41, 0.7), - iconColor: Color.fromARGB(255, 200, 200, 200), - ) + ? chewieController.customControls != null + ? chewieController.customControls + : Theme.of(context).platform == TargetPlatform.android + ? MaterialControls() + : CupertinoControls( + backgroundColor: Color.fromRGBO(41, 41, 41, 0.7), + iconColor: Color.fromARGB(255, 200, 200, 200), + ) : Container(); } From a16cabdcaf75dc7d6fb00cca2a5670fdc9622c45 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Sun, 20 Jan 2019 14:03:23 +0100 Subject: [PATCH 15/24] Do not initialize twice --- lib/src/chewie_controller.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/chewie_controller.dart b/lib/src/chewie_controller.dart index 9062081fe..042ec3d64 100644 --- a/lib/src/chewie_controller.dart +++ b/lib/src/chewie_controller.dart @@ -79,7 +79,8 @@ class ChewieController extends ChangeNotifier { Future _initialize() async { await videoPlayerController.setLooping(looping); - if (autoInitialize || autoPlay) { + if ((autoInitialize || autoPlay) && + !videoPlayerController.value.initialized) { await videoPlayerController.initialize(); } From f2e66aadf8d29aeda623c805ceac85eb8e4714a9 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Sun, 20 Jan 2019 15:50:30 +0100 Subject: [PATCH 16/24] Sort constructor declarations before other members --- example/lib/main.dart | 4 ++-- lib/src/chewie_progress_colors.dart | 10 +++++----- lib/src/cupertino_controls.dart | 6 +++--- lib/src/cupertino_progress_bar.dart | 23 +++++++++++------------ lib/src/material_progress_bar.dart | 23 +++++++++++------------ 5 files changed, 32 insertions(+), 34 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index b635d3d9d..b3474c4c8 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -11,10 +11,10 @@ void main() { } class ChewieDemo extends StatefulWidget { - final String title; - ChewieDemo({this.title = 'Chewie Demo'}); + final String title; + @override State createState() { return _ChewieDemoState(); diff --git a/lib/src/chewie_progress_colors.dart b/lib/src/chewie_progress_colors.dart index 3392ed57e..9f73717c4 100644 --- a/lib/src/chewie_progress_colors.dart +++ b/lib/src/chewie_progress_colors.dart @@ -1,11 +1,6 @@ import 'package:flutter/rendering.dart'; class ChewieProgressColors { - final Paint playedPaint; - final Paint bufferedPaint; - final Paint handlePaint; - final Paint backgroundPaint; - ChewieProgressColors({ Color playedColor: const Color.fromRGBO(255, 0, 0, 0.7), Color bufferedColor: const Color.fromRGBO(30, 30, 200, 0.2), @@ -15,4 +10,9 @@ class ChewieProgressColors { bufferedPaint = Paint()..color = bufferedColor, handlePaint = Paint()..color = handleColor, backgroundPaint = Paint()..color = backgroundColor; + + final Paint playedPaint; + final Paint bufferedPaint; + final Paint handlePaint; + final Paint backgroundPaint; } diff --git a/lib/src/cupertino_controls.dart b/lib/src/cupertino_controls.dart index d133a5662..83814d57e 100644 --- a/lib/src/cupertino_controls.dart +++ b/lib/src/cupertino_controls.dart @@ -12,14 +12,14 @@ import 'package:open_iconic_flutter/open_iconic_flutter.dart'; import 'package:video_player/video_player.dart'; class CupertinoControls extends StatefulWidget { - final Color backgroundColor; - final Color iconColor; - CupertinoControls({ @required this.backgroundColor, @required this.iconColor, }); + final Color backgroundColor; + final Color iconColor; + @override State createState() { return _CupertinoControlsState(); diff --git a/lib/src/cupertino_progress_bar.dart b/lib/src/cupertino_progress_bar.dart index 996f447f9..337488630 100644 --- a/lib/src/cupertino_progress_bar.dart +++ b/lib/src/cupertino_progress_bar.dart @@ -4,12 +4,6 @@ import 'package:flutter/widgets.dart'; import 'package:video_player/video_player.dart'; class CupertinoVideoProgressBar extends StatefulWidget { - final VideoPlayerController controller; - final ChewieProgressColors colors; - final Function() onDragStart; - final Function() onDragEnd; - final Function() onDragUpdate; - CupertinoVideoProgressBar( this.controller, { ChewieProgressColors colors, @@ -18,6 +12,12 @@ class CupertinoVideoProgressBar extends StatefulWidget { this.onDragUpdate, }) : colors = colors ?? ChewieProgressColors(); + final VideoPlayerController controller; + final ChewieProgressColors colors; + final Function() onDragStart; + final Function() onDragEnd; + final Function() onDragUpdate; + @override _VideoProgressBarState createState() { return _VideoProgressBarState(); @@ -25,16 +25,15 @@ class CupertinoVideoProgressBar extends StatefulWidget { } class _VideoProgressBarState extends State { - VoidCallback listener; - - bool _controllerWasPlaying = false; - _VideoProgressBarState() { listener = () { setState(() {}); }; } + VoidCallback listener; + bool _controllerWasPlaying = false; + VideoPlayerController get controller => widget.controller; @override @@ -118,11 +117,11 @@ class _VideoProgressBarState extends State { } class _ProgressBarPainter extends CustomPainter { + _ProgressBarPainter(this.value, this.colors); + VideoPlayerValue value; ChewieProgressColors colors; - _ProgressBarPainter(this.value, this.colors); - @override bool shouldRepaint(CustomPainter painter) { return true; diff --git a/lib/src/material_progress_bar.dart b/lib/src/material_progress_bar.dart index 13ef8c162..075b5ae11 100644 --- a/lib/src/material_progress_bar.dart +++ b/lib/src/material_progress_bar.dart @@ -4,12 +4,6 @@ import 'package:flutter/widgets.dart'; import 'package:video_player/video_player.dart'; class MaterialVideoProgressBar extends StatefulWidget { - final VideoPlayerController controller; - final ChewieProgressColors colors; - final Function() onDragStart; - final Function() onDragEnd; - final Function() onDragUpdate; - MaterialVideoProgressBar( this.controller, { ChewieProgressColors colors, @@ -18,6 +12,12 @@ class MaterialVideoProgressBar extends StatefulWidget { this.onDragUpdate, }) : colors = colors ?? ChewieProgressColors(); + final VideoPlayerController controller; + final ChewieProgressColors colors; + final Function() onDragStart; + final Function() onDragEnd; + final Function() onDragUpdate; + @override _VideoProgressBarState createState() { return _VideoProgressBarState(); @@ -25,16 +25,15 @@ class MaterialVideoProgressBar extends StatefulWidget { } class _VideoProgressBarState extends State { - VoidCallback listener; - - bool _controllerWasPlaying = false; - _VideoProgressBarState() { listener = () { setState(() {}); }; } + VoidCallback listener; + bool _controllerWasPlaying = false; + VideoPlayerController get controller => widget.controller; @override @@ -118,11 +117,11 @@ class _VideoProgressBarState extends State { } class _ProgressBarPainter extends CustomPainter { + _ProgressBarPainter(this.value, this.colors); + VideoPlayerValue value; ChewieProgressColors colors; - _ProgressBarPainter(this.value, this.colors); - @override bool shouldRepaint(CustomPainter painter) { return true; From bdb0278b573ef6c025afa4c279c3b9449e1360f7 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Sun, 20 Jan 2019 15:56:49 +0100 Subject: [PATCH 17/24] Add analysis options --- analysis_options.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/analysis_options.yaml b/analysis_options.yaml index 9fa4bab79..c79483957 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -10,6 +10,8 @@ linter: - hash_and_equals - iterable_contains_unrelated_type - list_remove_unrelated_type + - sort_constructors_first - test_types_in_equals + - unnecessary_new - unrelated_type_equality_checks - valid_regexps From b41d83d51f349bd7fc40e55d0ae5f0e698b771f2 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Sun, 20 Jan 2019 16:51:26 +0100 Subject: [PATCH 18/24] Update README and CHANGELOG --- CHANGELOG.md | 5 +++++ README.md | 50 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f57f18886..1a3097e60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 1.0.0 + + * **Breaking changes**: Add a `ChewieController` to make customizations and control from outside of the player easier. + Refer to the [README](README.md) for details on how to upgrade from previous versions. + ## 0.8.0 * Update to work with `video_player: ">=0.7.0 <0.8.0` - Thanks @Sub6Resources diff --git a/README.md b/README.md index 08bea3583..ec781ecbc 100644 --- a/README.md +++ b/README.md @@ -21,23 +21,63 @@ dependencies: ```dart import 'package:chewie/chewie.dart'; +final videoPlayerController = VideoPlayerController.network( + 'https://flutter.github.io/assets-for-api-docs/videos/butterfly.mp4'); -final playerWidget = new Chewie( - new VideoPlayerController.network( - 'https://flutter.github.io/assets-for-api-docs/videos/butterfly.mp4' - ), +final chewieController = ChewieController( + videoPlayerController: videoPlayerController, aspectRatio: 3 / 2, autoPlay: true, looping: true, ); + +final playerWidget = Chewie( + controller: chewieController, +); +``` + +Please make sure to dispose both controller widgets after use. For example by overriding the dispose method of the a `StatefulWidget`: +```dart +@override +void dispose() { +videoPlayerController.dispose(); +chewieController.dispose(); +super.dispose(); +} ``` ## Example Please run the app in the [`example/`](https://github.com/brianegan/chewie/tree/master/example) folder to start playing! +## Migrating from Chewie < 1.0.0 +Instead of passing the `VideoPlayerController` and your options to the `Chewie` widget you now pass them to the `ChewieController` and pass that latter to the `Chewie` widget. + +```dart +final playerWidget = Chewie( + videoPlayerController, + aspectRatio: 3 / 2, + autoPlay: true, + looping: true, +); +``` + +becomes + +```dart +final chewieController = ChewieController( + videoPlayerController: videoPlayerController, + aspectRatio: 3 / 2, + autoPlay: true, + looping: true, +); + +final playerWidget = Chewie( + controller: chewieController, +); +``` -## iOS Warning +## iOS warning The video player plugin used by chewie is not functional on iOS simulators. An iOS device must be used during development/testing. Please refer to this [issue](https://github.com/flutter/flutter/issues/14647). From 333cb2f534875c5b807c2d5b3331cee0b0a2d779 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Mon, 21 Jan 2019 17:52:28 +0100 Subject: [PATCH 19/24] Version 0.9.0 --- CHANGELOG.md | 2 +- README.md | 2 +- pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a3097e60..893c98c42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 1.0.0 +## 0.9.0 * **Breaking changes**: Add a `ChewieController` to make customizations and control from outside of the player easier. Refer to the [README](README.md) for details on how to upgrade from previous versions. diff --git a/README.md b/README.md index ec781ecbc..f44bf9965 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ super.dispose(); Please run the app in the [`example/`](https://github.com/brianegan/chewie/tree/master/example) folder to start playing! -## Migrating from Chewie < 1.0.0 +## Migrating from Chewie < 0.9.0 Instead of passing the `VideoPlayerController` and your options to the `Chewie` widget you now pass them to the `ChewieController` and pass that latter to the `Chewie` widget. ```dart diff --git a/pubspec.yaml b/pubspec.yaml index 785da5b9b..be8af2e11 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: chewie description: A video player for Flutter with Cupertino and Material play controls -version: 1.0.0 +version: 0.9.0 homepage: https://github.com/brianegan/chewie authors: - Brian Egan From bf58a0d6cbbb5f93360395c6ad97805e4c96fa0e Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Mon, 21 Jan 2019 17:56:01 +0100 Subject: [PATCH 20/24] Add documentation --- lib/src/chewie_controller.dart | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/src/chewie_controller.dart b/lib/src/chewie_controller.dart index 042ec3d64..dae372530 100644 --- a/lib/src/chewie_controller.dart +++ b/lib/src/chewie_controller.dart @@ -2,6 +2,16 @@ import 'package:chewie/src/chewie_progress_colors.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; +/// The ChewieController is used to configure and drive the Chewie Player +/// Widgets. It provides methods to control playback, such as [pause] and +/// [play], as well as methods that control the visual appearance of the player, +/// such as [enterFullScreen] or [exitFullScreen]. +/// +/// In addition, you can listen to the ChewieController for presentational +/// changes, such as entering and exiting full screen mode. To listen for +/// changes to the playback, such as a change to the seek position of the +/// player, please use the standard information provided by the +/// `VideoPlayerController`. class ChewieController extends ChangeNotifier { ChewieController({ this.videoPlayerController, From 2bd06b78f3f7492e768f5a43645fc9c634d45e6b Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Mon, 21 Jan 2019 18:20:49 +0100 Subject: [PATCH 21/24] Allow ChewieController.of And make the provider private --- example/lib/main.dart | 2 +- lib/chewie.dart | 1 - lib/src/chewie_controller.dart | 175 ----------------------------- lib/src/chewie_player.dart | 179 +++++++++++++++++++++++++++++- lib/src/cupertino_controls.dart | 6 +- lib/src/material_controls.dart | 4 +- lib/src/player_with_controls.dart | 5 +- 7 files changed, 184 insertions(+), 188 deletions(-) delete mode 100644 lib/src/chewie_controller.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index b3474c4c8..c6f2f3c80 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,5 +1,5 @@ import 'package:chewie/chewie.dart'; -import 'package:chewie/src/chewie_controller.dart'; +import 'package:chewie/src/chewie_player.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; diff --git a/lib/chewie.dart b/lib/chewie.dart index ce542ebc6..ed95928a7 100644 --- a/lib/chewie.dart +++ b/lib/chewie.dart @@ -1,5 +1,4 @@ library chewie; export 'src/chewie_player.dart'; -export 'src/chewie_controller.dart'; export 'src/chewie_progress_colors.dart'; diff --git a/lib/src/chewie_controller.dart b/lib/src/chewie_controller.dart deleted file mode 100644 index dae372530..000000000 --- a/lib/src/chewie_controller.dart +++ /dev/null @@ -1,175 +0,0 @@ -import 'package:chewie/src/chewie_progress_colors.dart'; -import 'package:flutter/material.dart'; -import 'package:video_player/video_player.dart'; - -/// The ChewieController is used to configure and drive the Chewie Player -/// Widgets. It provides methods to control playback, such as [pause] and -/// [play], as well as methods that control the visual appearance of the player, -/// such as [enterFullScreen] or [exitFullScreen]. -/// -/// In addition, you can listen to the ChewieController for presentational -/// changes, such as entering and exiting full screen mode. To listen for -/// changes to the playback, such as a change to the seek position of the -/// player, please use the standard information provided by the -/// `VideoPlayerController`. -class ChewieController extends ChangeNotifier { - ChewieController({ - this.videoPlayerController, - this.aspectRatio, - this.autoInitialize = false, - this.autoPlay = false, - this.startAt, - this.looping = false, - this.fullScreenByDefault = false, - this.cupertinoProgressColors, - this.materialProgressColors, - this.placeholder, - this.showControls = true, - this.customControls, - this.allowedScreenSleep = true, - this.isLive = false, - }) : assert(videoPlayerController != null, - 'You must provide a controller to play a video') { - _initialize(); - } - - /// The controller for the video you want to play - final VideoPlayerController videoPlayerController; - - /// Initialize the Video on Startup. This will prep the video for playback. - final bool autoInitialize; - - /// Play the video as soon as it's displayed - final bool autoPlay; - - /// Start video at a certain position - final Duration startAt; - - /// Whether or not the video should loop - final bool looping; - - /// Whether or not to show the controls - final bool showControls; - - /// Defines customised controls. Check [MaterialControls] or - /// [CupertinoControls] for reference. - final Widget customControls; - - /// The Aspect Ratio of the Video. Important to get the correct size of the - /// video! - /// - /// Will fallback to fitting within the space allowed. - final double aspectRatio; - - /// The colors to use for controls on iOS. By default, the iOS player uses - /// colors sampled from the original iOS 11 designs. - final ChewieProgressColors cupertinoProgressColors; - - /// The colors to use for the Material Progress Bar. By default, the Material - /// player uses the colors from your Theme. - final ChewieProgressColors materialProgressColors; - - /// The placeholder is displayed underneath the Video before it is initialized - /// or played. - final Widget placeholder; - - /// Defines if the player will start in fullscreen when play is pressed - final bool fullScreenByDefault; - - /// Defines if the player will sleep in fullscreen or not - final bool allowedScreenSleep; - - /// Defines if the controls should be for live stream video - final bool isLive; - - bool _isFullScreen = false; - - bool get isFullScreen => _isFullScreen; - - Future _initialize() async { - await videoPlayerController.setLooping(looping); - - if ((autoInitialize || autoPlay) && - !videoPlayerController.value.initialized) { - await videoPlayerController.initialize(); - } - - if (autoPlay) { - if (fullScreenByDefault) { - enterFullscreen(); - } - - await videoPlayerController.play(); - } - - if (startAt != null) { - await videoPlayerController.seekTo(startAt); - } - - if (fullScreenByDefault) { - videoPlayerController.addListener(() async { - if (await videoPlayerController.value.isPlaying && !_isFullScreen) { - enterFullscreen(); - } - }); - } - } - - void enterFullscreen() { - _isFullScreen = true; - notifyListeners(); - } - - void exitFullscreen() { - _isFullScreen = false; - notifyListeners(); - } - - void toggleFullscreen() { - _isFullScreen = !_isFullScreen; - notifyListeners(); - } - - Future play() async { - await videoPlayerController.play(); - } - - Future setLooping(bool looping) async { - await videoPlayerController.setLooping(looping); - } - - Future pause() async { - await videoPlayerController.pause(); - } - - Future seekTo(Duration moment) async { - await videoPlayerController.seekTo(moment); - } - - Future setVolume(double volume) async { - await videoPlayerController.setVolume(volume); - } -} - -class ChewieControllerProvider extends InheritedWidget { - const ChewieControllerProvider({ - Key key, - @required this.controller, - @required Widget child, - }) : assert(controller != null), - assert(child != null), - super(key: key, child: child); - - final ChewieController controller; - - static ChewieController of(BuildContext context) { - final ChewieControllerProvider chewieControllerProvider = - context.inheritFromWidgetOfExactType(ChewieControllerProvider); - - return chewieControllerProvider.controller; - } - - @override - bool updateShouldNotify(ChewieControllerProvider old) => - controller != old.controller; -} diff --git a/lib/src/chewie_player.dart b/lib/src/chewie_player.dart index 41c53fe47..d40d5d7df 100644 --- a/lib/src/chewie_player.dart +++ b/lib/src/chewie_player.dart @@ -1,11 +1,12 @@ import 'dart:async'; -import 'package:chewie/src/chewie_controller.dart'; +import 'package:chewie/src/chewie_progress_colors.dart'; import 'package:chewie/src/player_with_controls.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:screen/screen.dart'; +import 'package:video_player/video_player.dart'; /// A Video Player with Material and Cupertino skins. /// @@ -62,7 +63,7 @@ class ChewieState extends State { @override Widget build(BuildContext context) { - return ChewieControllerProvider( + return _ChewieControllerProvider( controller: widget.controller, child: PlayerWithControls(), ); @@ -75,7 +76,7 @@ class ChewieState extends State { body: Container( alignment: Alignment.center, color: Colors.black, - child: ChewieControllerProvider( + child: _ChewieControllerProvider( controller: widget.controller, child: PlayerWithControls(), ), @@ -131,3 +132,175 @@ class ChewieState extends State { ]); } } + +/// The ChewieController is used to configure and drive the Chewie Player +/// Widgets. It provides methods to control playback, such as [pause] and +/// [play], as well as methods that control the visual appearance of the player, +/// such as [enterFullScreen] or [exitFullScreen]. +/// +/// In addition, you can listen to the ChewieController for presentational +/// changes, such as entering and exiting full screen mode. To listen for +/// changes to the playback, such as a change to the seek position of the +/// player, please use the standard information provided by the +/// `VideoPlayerController`. +class ChewieController extends ChangeNotifier { + ChewieController({ + this.videoPlayerController, + this.aspectRatio, + this.autoInitialize = false, + this.autoPlay = false, + this.startAt, + this.looping = false, + this.fullScreenByDefault = false, + this.cupertinoProgressColors, + this.materialProgressColors, + this.placeholder, + this.showControls = true, + this.customControls, + this.allowedScreenSleep = true, + this.isLive = false, + }) : assert(videoPlayerController != null, + 'You must provide a controller to play a video') { + _initialize(); + } + + /// The controller for the video you want to play + final VideoPlayerController videoPlayerController; + + /// Initialize the Video on Startup. This will prep the video for playback. + final bool autoInitialize; + + /// Play the video as soon as it's displayed + final bool autoPlay; + + /// Start video at a certain position + final Duration startAt; + + /// Whether or not the video should loop + final bool looping; + + /// Whether or not to show the controls + final bool showControls; + + /// Defines customised controls. Check [MaterialControls] or + /// [CupertinoControls] for reference. + final Widget customControls; + + /// The Aspect Ratio of the Video. Important to get the correct size of the + /// video! + /// + /// Will fallback to fitting within the space allowed. + final double aspectRatio; + + /// The colors to use for controls on iOS. By default, the iOS player uses + /// colors sampled from the original iOS 11 designs. + final ChewieProgressColors cupertinoProgressColors; + + /// The colors to use for the Material Progress Bar. By default, the Material + /// player uses the colors from your Theme. + final ChewieProgressColors materialProgressColors; + + /// The placeholder is displayed underneath the Video before it is initialized + /// or played. + final Widget placeholder; + + /// Defines if the player will start in fullscreen when play is pressed + final bool fullScreenByDefault; + + /// Defines if the player will sleep in fullscreen or not + final bool allowedScreenSleep; + + /// Defines if the controls should be for live stream video + final bool isLive; + + static ChewieController of(BuildContext context) { + final _ChewieControllerProvider chewieControllerProvider = + context.inheritFromWidgetOfExactType(_ChewieControllerProvider); + + return chewieControllerProvider.controller; + } + + bool _isFullScreen = false; + + bool get isFullScreen => _isFullScreen; + + Future _initialize() async { + await videoPlayerController.setLooping(looping); + + if ((autoInitialize || autoPlay) && + !videoPlayerController.value.initialized) { + await videoPlayerController.initialize(); + } + + if (autoPlay) { + if (fullScreenByDefault) { + enterFullscreen(); + } + + await videoPlayerController.play(); + } + + if (startAt != null) { + await videoPlayerController.seekTo(startAt); + } + + if (fullScreenByDefault) { + videoPlayerController.addListener(() async { + if (await videoPlayerController.value.isPlaying && !_isFullScreen) { + enterFullscreen(); + } + }); + } + } + + void enterFullscreen() { + _isFullScreen = true; + notifyListeners(); + } + + void exitFullscreen() { + _isFullScreen = false; + notifyListeners(); + } + + void toggleFullscreen() { + _isFullScreen = !_isFullScreen; + notifyListeners(); + } + + Future play() async { + await videoPlayerController.play(); + } + + Future setLooping(bool looping) async { + await videoPlayerController.setLooping(looping); + } + + Future pause() async { + await videoPlayerController.pause(); + } + + Future seekTo(Duration moment) async { + await videoPlayerController.seekTo(moment); + } + + Future setVolume(double volume) async { + await videoPlayerController.setVolume(volume); + } +} + +class _ChewieControllerProvider extends InheritedWidget { + const _ChewieControllerProvider({ + Key key, + @required this.controller, + @required Widget child, + }) : assert(controller != null), + assert(child != null), + super(key: key, child: child); + + final ChewieController controller; + + @override + bool updateShouldNotify(_ChewieControllerProvider old) => + controller != old.controller; +} diff --git a/lib/src/cupertino_controls.dart b/lib/src/cupertino_controls.dart index 83814d57e..7d4a8afea 100644 --- a/lib/src/cupertino_controls.dart +++ b/lib/src/cupertino_controls.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:math' as math; import 'dart:ui' as ui; -import 'package:chewie/src/chewie_controller.dart'; +import 'package:chewie/src/chewie_player.dart'; import 'package:chewie/src/chewie_progress_colors.dart'; import 'package:chewie/src/cupertino_progress_bar.dart'; import 'package:chewie/src/utils.dart'; @@ -42,7 +42,7 @@ class _CupertinoControlsState extends State { Widget build(BuildContext context) { final backgroundColor = widget.backgroundColor; final iconColor = widget.iconColor; - chewieController = ChewieControllerProvider.of(context); + chewieController = ChewieController.of(context); controller = chewieController.videoPlayerController; final orientation = MediaQuery.of(context).orientation; final barHeight = orientation == Orientation.portrait ? 30.0 : 47.0; @@ -72,7 +72,7 @@ class _CupertinoControlsState extends State { @override void didChangeDependencies() { - chewieController = ChewieControllerProvider.of(context); + chewieController = ChewieController.of(context); controller = chewieController.videoPlayerController; _dispose(); diff --git a/lib/src/material_controls.dart b/lib/src/material_controls.dart index 201c130a8..0dc5ee1a7 100644 --- a/lib/src/material_controls.dart +++ b/lib/src/material_controls.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:chewie/src/chewie_controller.dart'; +import 'package:chewie/src/chewie_player.dart'; import 'package:chewie/src/chewie_progress_colors.dart'; import 'package:chewie/src/material_progress_bar.dart'; import 'package:chewie/src/utils.dart'; @@ -65,7 +65,7 @@ class _MaterialControlsState extends State { @override void didChangeDependencies() { - chewieController = ChewieControllerProvider.of(context); + chewieController = ChewieController.of(context); controller = chewieController.videoPlayerController; _dispose(); diff --git a/lib/src/player_with_controls.dart b/lib/src/player_with_controls.dart index 36370084d..bf6cb3a95 100644 --- a/lib/src/player_with_controls.dart +++ b/lib/src/player_with_controls.dart @@ -1,6 +1,6 @@ import 'dart:ui'; -import 'package:chewie/src/chewie_controller.dart'; +import 'package:chewie/src/chewie_player.dart'; import 'package:chewie/src/cupertino_controls.dart'; import 'package:chewie/src/material_controls.dart'; import 'package:flutter/foundation.dart'; @@ -12,8 +12,7 @@ class PlayerWithControls extends StatelessWidget { @override Widget build(BuildContext context) { - final ChewieController chewieController = - ChewieControllerProvider.of(context); + final ChewieController chewieController = ChewieController.of(context); return Center( child: Container( From fc1bc166a021a1ab4498a09779a0200ecaa12510 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Wed, 23 Jan 2019 11:49:07 +0100 Subject: [PATCH 22/24] Only reinitialize if ChewieController changed --- lib/src/cupertino_controls.dart | 7 +++++-- lib/src/material_controls.dart | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/src/cupertino_controls.dart b/lib/src/cupertino_controls.dart index 7d4a8afea..af1d690aa 100644 --- a/lib/src/cupertino_controls.dart +++ b/lib/src/cupertino_controls.dart @@ -72,11 +72,14 @@ class _CupertinoControlsState extends State { @override void didChangeDependencies() { + final _oldController = chewieController; chewieController = ChewieController.of(context); controller = chewieController.videoPlayerController; - _dispose(); - _initialize(); + if (_oldController != chewieController) { + _dispose(); + _initialize(); + } super.didChangeDependencies(); } diff --git a/lib/src/material_controls.dart b/lib/src/material_controls.dart index 0dc5ee1a7..eb03050ca 100644 --- a/lib/src/material_controls.dart +++ b/lib/src/material_controls.dart @@ -65,11 +65,14 @@ class _MaterialControlsState extends State { @override void didChangeDependencies() { + final _oldController = chewieController; chewieController = ChewieController.of(context); controller = chewieController.videoPlayerController; - _dispose(); - _initialize(); + if (_oldController != chewieController) { + _dispose(); + _initialize(); + } super.didChangeDependencies(); } From cd20458e8ea7359782a0665e1291694dd485d63c Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Wed, 23 Jan 2019 12:23:39 +0100 Subject: [PATCH 23/24] Properly set full screen state when exiting. --- lib/src/chewie_player.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/src/chewie_player.dart b/lib/src/chewie_player.dart index d40d5d7df..0f3496132 100644 --- a/lib/src/chewie_player.dart +++ b/lib/src/chewie_player.dart @@ -117,6 +117,8 @@ class ChewieState extends State { } await Navigator.of(context).push(route); + _isFullScreen = false; + widget.controller.exitFullscreen(); bool isKeptOn = await Screen.isKeptOn; if (isKeptOn) { From c5536969b5270af0683ed79b42a521b820361f71 Mon Sep 17 00:00:00 2001 From: Ben Hagen Date: Wed, 23 Jan 2019 12:25:21 +0100 Subject: [PATCH 24/24] Be consistent when naming methods and variables --- example/lib/main.dart | 2 +- lib/src/chewie_player.dart | 12 ++++++------ lib/src/cupertino_controls.dart | 2 +- lib/src/material_controls.dart | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index c6f2f3c80..ca4fa1960 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -85,7 +85,7 @@ class _ChewieDemoState extends State { ), FlatButton( onPressed: () { - _chewieController.enterFullscreen(); + _chewieController.enterFullScreen(); }, child: Text('Fullscreen'), ), diff --git a/lib/src/chewie_player.dart b/lib/src/chewie_player.dart index 0f3496132..ce8f3edd2 100644 --- a/lib/src/chewie_player.dart +++ b/lib/src/chewie_player.dart @@ -118,7 +118,7 @@ class ChewieState extends State { await Navigator.of(context).push(route); _isFullScreen = false; - widget.controller.exitFullscreen(); + widget.controller.exitFullScreen(); bool isKeptOn = await Screen.isKeptOn; if (isKeptOn) { @@ -236,7 +236,7 @@ class ChewieController extends ChangeNotifier { if (autoPlay) { if (fullScreenByDefault) { - enterFullscreen(); + enterFullScreen(); } await videoPlayerController.play(); @@ -249,23 +249,23 @@ class ChewieController extends ChangeNotifier { if (fullScreenByDefault) { videoPlayerController.addListener(() async { if (await videoPlayerController.value.isPlaying && !_isFullScreen) { - enterFullscreen(); + enterFullScreen(); } }); } } - void enterFullscreen() { + void enterFullScreen() { _isFullScreen = true; notifyListeners(); } - void exitFullscreen() { + void exitFullScreen() { _isFullScreen = false; notifyListeners(); } - void toggleFullscreen() { + void toggleFullScreen() { _isFullScreen = !_isFullScreen; notifyListeners(); } diff --git a/lib/src/cupertino_controls.dart b/lib/src/cupertino_controls.dart index af1d690aa..bbde20ecb 100644 --- a/lib/src/cupertino_controls.dart +++ b/lib/src/cupertino_controls.dart @@ -417,7 +417,7 @@ class _CupertinoControlsState extends State { setState(() { _hideStuff = true; - chewieController.toggleFullscreen(); + chewieController.toggleFullScreen(); _expandCollapseTimer = Timer(Duration(milliseconds: 300), () { setState(() { _cancelAndRestartTimer(); diff --git a/lib/src/material_controls.dart b/lib/src/material_controls.dart index eb03050ca..fdf2d5863 100644 --- a/lib/src/material_controls.dart +++ b/lib/src/material_controls.dart @@ -272,7 +272,7 @@ class _MaterialControlsState extends State { setState(() { _hideStuff = true; - chewieController.toggleFullscreen(); + chewieController.toggleFullScreen(); _showAfterExpandCollapseTimer = Timer(Duration(milliseconds: 300), () { setState(() { _cancelAndRestartTimer();