From 6660ee5cd148df6dc58949bf1fc49bf7fd69ce66 Mon Sep 17 00:00:00 2001 From: felixmo_trustMe Date: Wed, 3 Feb 2021 15:34:26 +0800 Subject: [PATCH 01/10] Implemented Chewie package --- example/ios/Flutter/Debug.xcconfig | 1 + example/ios/Flutter/Release.xcconfig | 1 + example/ios/Podfile | 41 ++++++ example/lib/main.dart | 2 +- example/lib/vimeoplayer.dart | 196 ++++++++++++++------------- example/pubspec.lock | 143 ++++++++++--------- example/pubspec.yaml | 3 +- pubspec.lock | 97 +++++-------- 8 files changed, 259 insertions(+), 225 deletions(-) create mode 100644 example/ios/Podfile diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig index 592ceee..e8efba1 100644 --- a/example/ios/Flutter/Debug.xcconfig +++ b/example/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig index 592ceee..399e934 100644 --- a/example/ios/Flutter/Release.xcconfig +++ b/example/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/example/ios/Podfile b/example/ios/Podfile new file mode 100644 index 0000000..1e8c3c9 --- /dev/null +++ b/example/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/example/lib/main.dart b/example/lib/main.dart index f2535f7..2d516cd 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -36,7 +36,7 @@ class VideoScreen extends StatelessWidget { preferredSize: Size(0.0, 0.0), ), body: ListView(children: [ - VimeoPlayer(id: '395212534', autoPlay: true), + VimeoPlayer(id: '505942118', autoPlay: true, fullScreen: true), ])); } } diff --git a/example/lib/vimeoplayer.dart b/example/lib/vimeoplayer.dart index 6c6d506..0da5cb3 100644 --- a/example/lib/vimeoplayer.dart +++ b/example/lib/vimeoplayer.dart @@ -1,5 +1,6 @@ library vimeoplayer; +import 'package:chewie/chewie.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; import 'package:flutter/services.dart'; @@ -13,18 +14,19 @@ class VimeoPlayer extends StatefulWidget { final bool autoPlay; final bool looping; final int position; + final bool fullScreen; VimeoPlayer({ @required this.id, this.autoPlay, this.looping, this.position, + this.fullScreen, Key key, }) : super(key: key); @override - _VimeoPlayerState createState() => - _VimeoPlayerState(id, autoPlay, looping, position); + _VimeoPlayerState createState() => _VimeoPlayerState(id, autoPlay, looping, position, fullScreen); } class _VimeoPlayerState extends State { @@ -35,10 +37,12 @@ class _VimeoPlayerState extends State { bool fullScreen = false; int position; - _VimeoPlayerState(this._id, this.autoPlay, this.looping, this.position); + _VimeoPlayerState(this._id, this.autoPlay, this.looping, this.position, this.fullScreen); //Custom controller - VideoPlayerController _controller; + VideoPlayerController _videoPlayerController; + ChewieController _chewieController; + Future initFuture; //Quality Class @@ -71,21 +75,41 @@ class _VimeoPlayerState extends State { _quality.getQualitiesSync().then((value) { _qualityValues = value; _qualityValue = value[value.lastKey()]; - _controller = VideoPlayerController.network(_qualityValue); - _controller.setLooping(looping); - if (autoPlay) _controller.play(); - initFuture = _controller.initialize(); + _videoPlayerController = VideoPlayerController.network(_qualityValue); + initFuture = _videoPlayerController.initialize().then((value) { + _chewieController = ChewieController( + videoPlayerController: _videoPlayerController, + // Prepare the video to be played and display the first frame + autoInitialize: true, + allowFullScreen: fullScreen, + deviceOrientationsOnEnterFullScreen: [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight], + systemOverlaysOnEnterFullScreen: [SystemUiOverlay.bottom], + deviceOrientationsAfterFullScreen: [DeviceOrientation.portraitDown, DeviceOrientation.portraitUp], + systemOverlaysAfterFullScreen: [SystemUiOverlay.top, SystemUiOverlay.bottom], + aspectRatio: _videoPlayerController.value.aspectRatio, + looping: looping, + autoPlay: autoPlay, + // Errors can occur for example when trying to play a video + // from a non-existent URL + errorBuilder: (context, errorMessage) { + return Center( + child: Text( + errorMessage, + style: TextStyle(color: Colors.white), + ), + ); + }, + ); + }); //Обновление состояние приложения и перерисовка setState(() { - SystemChrome.setPreferredOrientations( - [DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); }); }); //На странице видео преимущество за портретной ориентацией - SystemChrome.setPreferredOrientations( - [DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values); super.initState(); @@ -105,50 +129,49 @@ class _VimeoPlayerState extends State { if (snapshot.connectionState == ConnectionState.done) { //Управление шириной и высотой видео double delta = MediaQuery.of(context).size.width - - MediaQuery.of(context).size.height * - _controller.value.aspectRatio; + MediaQuery.of(context).size.height * _videoPlayerController.value.aspectRatio; //Рассчет ширины и высоты видео плеера относительно сторон // и ориентации устройства - if (MediaQuery.of(context).orientation == - Orientation.portrait || - delta < 0) { - videoHeight = MediaQuery.of(context).size.width / - _controller.value.aspectRatio; + if (MediaQuery.of(context).orientation == Orientation.portrait || delta < 0) { + videoHeight = MediaQuery.of(context).size.width / _videoPlayerController.value.aspectRatio; videoWidth = MediaQuery.of(context).size.width; videoMargin = 0; } else { videoHeight = MediaQuery.of(context).size.height; - videoWidth = videoHeight * _controller.value.aspectRatio; - videoMargin = - (MediaQuery.of(context).size.width - videoWidth) / 2; + videoWidth = videoHeight * _videoPlayerController.value.aspectRatio; + videoMargin = (MediaQuery.of(context).size.width - videoWidth) / 2; } //Начинаем с того же места, где и остановились при смене качества - if (_seek && _controller.value.duration.inSeconds > 2) { - _controller.seekTo(Duration(seconds: position)); + if (_seek && _videoPlayerController.value.duration.inSeconds > 2) { + _videoPlayerController.seekTo(Duration(seconds: position)); _seek = false; } - //Отрисовка элементов плеера - return Stack( - children: [ - Container( - height: videoHeight, - width: videoWidth, - margin: EdgeInsets.only(left: videoMargin), - child: VideoPlayer(_controller), - ), - _videoOverlay(), - ], + return Container( + margin: EdgeInsets.only(left: videoMargin), + child: Chewie(controller: _chewieController), ); + + //Отрисовка элементов плеера + // return Stack( + // children: [ + // Container( + // height: videoHeight, + // width: videoWidth, + // margin: EdgeInsets.only(left: videoMargin), + // child: Chewie(controller: _chewieController), + // ), + // _videoOverlay(), + // ], + // ); } else { return Center( heightFactor: 6, child: CircularProgressIndicator( strokeWidth: 4, - valueColor: - AlwaysStoppedAnimation(Color(0xFF22A3D2)), + valueColor: AlwaysStoppedAnimation(Color(0xFF22A3D2)), )); } }), @@ -176,11 +199,10 @@ class _VimeoPlayerState extends State { child: Container( width: doubleTapLWidth / 2 - 30, height: doubleTapLHeight - 46, - margin: EdgeInsets.fromLTRB( - 0, 10, doubleTapLWidth / 2 + 30, doubleTapLMargin + 20), + margin: EdgeInsets.fromLTRB(0, 10, doubleTapLWidth / 2 + 30, doubleTapLMargin + 20), decoration: BoxDecoration( - //color: Colors.red, - ), + //color: Colors.red, + ), ), // Изменение размера блоков дабл тапа. Нужно для открытия кнопок @@ -203,8 +225,7 @@ class _VimeoPlayerState extends State { }, onDoubleTap: () { setState(() { - _controller.seekTo(Duration( - seconds: _controller.value.position.inSeconds - 10)); + _videoPlayerController.seekTo(Duration(seconds: _videoPlayerController.value.position.inSeconds - 10)); }); }), GestureDetector( @@ -212,11 +233,10 @@ class _VimeoPlayerState extends State { //======= Перемотка вперед =======// width: doubleTapRWidth / 2 - 45, height: doubleTapRHeight - 60, - margin: EdgeInsets.fromLTRB(doubleTapRWidth / 2 + 45, - doubleTapRMargin, 0, doubleTapRMargin + 20), + margin: EdgeInsets.fromLTRB(doubleTapRWidth / 2 + 45, doubleTapRMargin, 0, doubleTapRMargin + 20), decoration: BoxDecoration( - //color: Colors.red, - ), + //color: Colors.red, + ), ), // Изменение размера блоков дабл тапа. Нужно для открытия кнопок // "Во весь экран" и "Качество" при включенном overlay @@ -238,8 +258,7 @@ class _VimeoPlayerState extends State { }, onDoubleTap: () { setState(() { - _controller.seekTo(Duration( - seconds: _controller.value.position.inSeconds + 10)); + _videoPlayerController.seekTo(Duration(seconds: _videoPlayerController.value.position.inSeconds + 10)); }); }), ], @@ -258,14 +277,13 @@ class _VimeoPlayerState extends State { onTap: () => { //Обновление состояние приложения и перерисовка setState(() { - _controller.pause(); + _videoPlayerController.pause(); _qualityValue = value; - _controller = - VideoPlayerController.network(_qualityValue); - _controller.setLooping(true); + _videoPlayerController = VideoPlayerController.network(_qualityValue); + _videoPlayerController.setLooping(true); _seek = true; - initFuture = _controller.initialize(); - _controller.play(); + initFuture = _videoPlayerController.initialize(); + _videoPlayerController.play(); }), })))); //Вывод элементов качество списком @@ -291,10 +309,7 @@ class _VimeoPlayerState extends State { gradient: LinearGradient( begin: Alignment.centerRight, end: Alignment.centerLeft, - colors: [ - const Color(0x662F2C47), - const Color(0x662F2C47) - ], + colors: [const Color(0x662F2C47), const Color(0x662F2C47)], ), ), ), @@ -302,29 +317,26 @@ class _VimeoPlayerState extends State { ), Center( child: IconButton( - padding: EdgeInsets.only( - top: videoHeight / 2 - 30, - bottom: videoHeight / 2 - 30), - icon: _controller.value.isPlaying + padding: EdgeInsets.only(top: videoHeight / 2 - 30, bottom: videoHeight / 2 - 30), + icon: _videoPlayerController.value.isPlaying ? Icon(Icons.pause, size: 60.0) : Icon(Icons.play_arrow, size: 60.0), onPressed: () { setState(() { - _controller.value.isPlaying - ? _controller.pause() - : _controller.play(); + _videoPlayerController.value.isPlaying + ? _videoPlayerController.pause() + : _videoPlayerController.play(); }); }), ), Container( - margin: EdgeInsets.only( - top: videoHeight - 70, left: videoWidth + videoMargin - 50), + margin: EdgeInsets.only(top: videoHeight - 70, left: videoWidth + videoMargin - 50), child: IconButton( alignment: AlignmentDirectional.center, icon: Icon(Icons.fullscreen, size: 30.0), onPressed: () async { setState(() { - _controller.pause(); + _videoPlayerController.pause(); }); //Создание новой страницы с плеером во весь экран, // предача данных в плеер и возвращение позиции при @@ -334,27 +346,21 @@ class _VimeoPlayerState extends State { context, PageRouteBuilder( opaque: false, - pageBuilder: (BuildContext context, _, __) => - FullscreenPlayer( - id: _id, - autoPlay: true, - controller: _controller, - position: - _controller.value.position.inSeconds, - initFuture: initFuture, - qualityValue: _qualityValue), - transitionsBuilder: (___, - Animation animation, - ____, - Widget child) { + pageBuilder: (BuildContext context, _, __) => FullscreenPlayer( + id: _id, + autoPlay: true, + controller: _videoPlayerController, + position: _videoPlayerController.value.position.inSeconds, + initFuture: initFuture, + qualityValue: _qualityValue), + transitionsBuilder: (___, Animation animation, ____, Widget child) { return FadeTransition( opacity: animation, - child: ScaleTransition( - scale: animation, child: child), + child: ScaleTransition(scale: animation, child: child), ); })); setState(() { - _controller.play(); + _videoPlayerController.play(); _seek = true; }); }), @@ -364,7 +370,7 @@ class _VimeoPlayerState extends State { child: IconButton( icon: Icon(Icons.settings, size: 26.0), onPressed: () { - position = _controller.value.position.inSeconds; + position = _videoPlayerController.value.position.inSeconds; _seek = true; _settingModalBottomSheet(context); setState(() {}); @@ -372,8 +378,7 @@ class _VimeoPlayerState extends State { ), Container( //===== Ползунок =====// - margin: EdgeInsets.only( - top: videoHeight - 26, left: videoMargin), //CHECK IT + margin: EdgeInsets.only(top: videoHeight - 26, left: videoMargin), //CHECK IT child: _videoOverlaySlider(), ) ], @@ -384,7 +389,7 @@ class _VimeoPlayerState extends State { width: videoWidth, margin: EdgeInsets.only(top: videoHeight - 5), child: VideoProgressIndicator( - _controller, + _videoPlayerController, allowScrubbing: true, colors: VideoProgressColors( playedColor: Color(0xFF22A3D2), @@ -400,7 +405,7 @@ class _VimeoPlayerState extends State { //=================== ПОЛЗУНОК ===================// Widget _videoOverlaySlider() { return ValueListenableBuilder( - valueListenable: _controller, + valueListenable: _videoPlayerController, builder: (context, VideoPlayerValue value, child) { if (!value.hasError && value.initialized) { return Row( @@ -410,14 +415,13 @@ class _VimeoPlayerState extends State { alignment: Alignment(0, 0), child: Text(value.position.inMinutes.toString() + ':' + - (value.position.inSeconds - value.position.inMinutes * 60) - .toString()), + (value.position.inSeconds - value.position.inMinutes * 60).toString()), ), Container( height: 20, width: videoWidth - 92, child: VideoProgressIndicator( - _controller, + _videoPlayerController, allowScrubbing: true, colors: VideoProgressColors( playedColor: Color(0xFF22A3D2), @@ -432,8 +436,7 @@ class _VimeoPlayerState extends State { alignment: Alignment(0, 0), child: Text(value.duration.inMinutes.toString() + ':' + - (value.duration.inSeconds - value.duration.inMinutes * 60) - .toString()), + (value.duration.inSeconds - value.duration.inMinutes * 60).toString()), ), ], ); @@ -446,7 +449,8 @@ class _VimeoPlayerState extends State { @override void dispose() { - _controller.dispose(); + _chewieController.dispose(); + _videoPlayerController.dispose(); super.dispose(); } } diff --git a/example/pubspec.lock b/example/pubspec.lock index ce010d6..aa48073 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -1,69 +1,76 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - archive: + async: dependency: transitive description: - name: archive + name: async url: "https://pub.dartlang.org" source: hosted - version: "2.0.13" - args: + version: "2.5.0-nullsafety.1" + boolean_selector: dependency: transitive description: - name: args + name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.6.0" - async: + version: "2.1.0-nullsafety.1" + characters: dependency: transitive description: - name: async + name: characters url: "https://pub.dartlang.org" source: hosted - version: "2.4.1" - boolean_selector: + version: "1.1.0-nullsafety.3" + charcode: dependency: transitive description: - name: boolean_selector + name: charcode url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" - charcode: - dependency: transitive + version: "1.2.0-nullsafety.1" + chewie: + dependency: "direct main" description: - name: charcode + name: chewie url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" - collection: + version: "0.12.2" + clock: dependency: transitive description: - name: collection + name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.14.12" - convert: + version: "1.1.0-nullsafety.1" + collection: dependency: transitive description: - name: convert + name: collection url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" - crypto: + version: "1.15.0-nullsafety.3" + csslib: dependency: transitive description: - name: crypto + name: csslib url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "0.16.2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted - version: "0.1.3" + version: "1.0.0" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0-nullsafety.1" flutter: dependency: "direct main" description: flutter @@ -79,6 +86,13 @@ packages: description: flutter source: sdk version: "0.0.0" + html: + dependency: transitive + description: + name: html + url: "https://pub.dartlang.org" + source: hosted + version: "0.14.0+4" http: dependency: transitive description: @@ -93,34 +107,41 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.4" - image: + import_js_library: + dependency: transitive + description: + name: import_js_library + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + js: dependency: transitive description: - name: image + name: js url: "https://pub.dartlang.org" source: hosted - version: "2.1.12" + version: "0.6.2" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.10-nullsafety.1" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.3" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.4" + version: "1.8.0-nullsafety.1" pedantic: dependency: transitive description: @@ -128,20 +149,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.0" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.0" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" sky_engine: dependency: transitive description: flutter @@ -153,63 +160,63 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.2" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0-nullsafety.1" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.1" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0-nullsafety.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.15" + version: "0.2.19-nullsafety.2" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0-nullsafety.3" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.3" video_player: dependency: transitive description: name: video_player url: "https://pub.dartlang.org" source: hosted - version: "0.11.1+2" + version: "1.0.1" video_player_platform_interface: dependency: transitive description: @@ -230,14 +237,28 @@ packages: name: vimeoplayer url: "https://pub.dartlang.org" source: hosted - version: "0.1.7" - xml: + version: "0.0.2" + wakelock: + dependency: transitive + description: + name: wakelock + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.1+1" + wakelock_platform_interface: + dependency: transitive + description: + name: wakelock_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0+1" + wakelock_web: dependency: transitive description: - name: xml + name: wakelock_web url: "https://pub.dartlang.org" source: hosted - version: "3.6.1" + version: "0.1.0+3" sdks: - dart: ">=2.8.0 <3.0.0" - flutter: ">=1.12.13+hotfix.5 <2.0.0" + dart: ">=2.10.0-110 <2.11.0" + flutter: ">=1.22.0 <2.0.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 92340a1..0ce2924 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -24,11 +24,12 @@ dependencies: flutter: sdk: flutter vimeoplayer: ^0.0.1 + chewie: ^0.12.2 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.3 + cupertino_icons: ^1.0.0 dev_dependencies: flutter_test: diff --git a/pubspec.lock b/pubspec.lock index 09a6a4d..0ec86d4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,62 +1,55 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.13" - args: - dependency: transitive - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "1.6.0" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.1" + version: "2.5.0-nullsafety.1" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.1" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0-nullsafety.3" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" - collection: + version: "1.2.0-nullsafety.1" + clock: dependency: transitive description: - name: collection + name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.14.12" - convert: + version: "1.1.0-nullsafety.1" + collection: dependency: transitive description: - name: convert + name: collection url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" - crypto: + version: "1.15.0-nullsafety.3" + fake_async: dependency: transitive description: - name: crypto + name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "1.2.0-nullsafety.1" flutter: dependency: "direct main" description: flutter @@ -86,34 +79,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.4" - image: - dependency: transitive - description: - name: image - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.12" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.10-nullsafety.1" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.3" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.4" + version: "1.8.0-nullsafety.1" pedantic: dependency: transitive description: @@ -121,20 +107,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.0" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.0" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" sky_engine: dependency: transitive description: flutter @@ -146,56 +118,56 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.2" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0-nullsafety.1" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.1" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0-nullsafety.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.15" + version: "0.2.19-nullsafety.2" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0-nullsafety.3" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.3" video_player: dependency: "direct main" description: @@ -217,13 +189,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.4" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "3.6.1" sdks: - dart: ">=2.8.0 <3.0.0" + dart: ">=2.10.0-110 <2.11.0" flutter: ">=1.12.13+hotfix.5 <2.0.0" From 658e2445a7be0f67751489365c5ec61cbdea17c7 Mon Sep 17 00:00:00 2001 From: felixmo_trustMe Date: Wed, 3 Feb 2021 15:47:25 +0800 Subject: [PATCH 02/10] Removed redundant logic and updated example --- example/lib/src/fullscreen_player.dart | 432 ------------------------- example/lib/vimeoplayer.dart | 196 ----------- lib/src/fullscreen_player.dart | 432 ------------------------- lib/vimeoplayer.dart | 287 +++------------- pubspec.lock | 67 +++- pubspec.yaml | 1 + 6 files changed, 113 insertions(+), 1302 deletions(-) delete mode 100644 example/lib/src/fullscreen_player.dart delete mode 100644 lib/src/fullscreen_player.dart diff --git a/example/lib/src/fullscreen_player.dart b/example/lib/src/fullscreen_player.dart deleted file mode 100644 index b674f18..0000000 --- a/example/lib/src/fullscreen_player.dart +++ /dev/null @@ -1,432 +0,0 @@ -library vimeoplayer; - -import 'package:flutter/material.dart'; -import 'package:video_player/video_player.dart'; -import 'package:flutter/services.dart'; -import 'quality_links.dart'; -import 'dart:async'; - -//Класс видео плеера во весь экран -class FullscreenPlayer extends StatefulWidget { - final String id; - final bool autoPlay; - final bool looping; - final VideoPlayerController controller; - final position; - final Future initFuture; - final String qualityValue; - - FullscreenPlayer({ - @required this.id, - this.autoPlay, - this.looping, - this.controller, - this.position, - this.initFuture, - this.qualityValue, - Key key, - }) : super(key: key); - - @override - _FullscreenPlayerState createState() => _FullscreenPlayerState( - id, autoPlay, looping, controller, position, initFuture, qualityValue); -} - -class _FullscreenPlayerState extends State { - String _id; - bool autoPlay = false; - bool looping = false; - bool _overlay = true; - bool fullScreen = true; - - VideoPlayerController controller; - VideoPlayerController _controller; - - int position; - - Future initFuture; - var qualityValue; - - _FullscreenPlayerState(this._id, this.autoPlay, this.looping, this.controller, - this.position, this.initFuture, this.qualityValue); - - // Quality Class - QualityLinks _quality; - Map _qualityValues; - - //Переменная перемотки - bool _seek = true; - - //Переменные видео - double videoHeight; - double videoWidth; - double videoMargin; - - //Переменные под зоны дабл-тапа - double doubleTapRMarginFS = 36; - double doubleTapRWidthFS = 700; - double doubleTapRHeightFS = 300; - double doubleTapLMarginFS = 10; - double doubleTapLWidthFS = 700; - double doubleTapLHeightFS = 400; - - @override - void initState() { - //Инициализация контроллеров видео при получении данных из Vimeo - _controller = controller; - if (autoPlay) _controller.play(); - - // Подгрузка списка качеств видео - _quality = QualityLinks(_id); //Create class - _quality.getQualitiesSync().then((value) { - _qualityValues = value; - }); - - setState(() { - SystemChrome.setPreferredOrientations( - [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); - SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]); - }); - - super.initState(); - } - - //Ослеживаем пользовательского нажатие назад и переводим - // на экран с плеером не в режиме фуллскрин, возвращаем ориентацию - Future _onWillPop() { - setState(() { - _controller.pause(); - SystemChrome.setPreferredOrientations( - [DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); - SystemChrome.setEnabledSystemUIOverlays( - [SystemUiOverlay.top, SystemUiOverlay.bottom]); - }); - Navigator.pop(context, _controller.value.position.inSeconds); - return Future.value(true); - } - - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: _onWillPop, - child: Scaffold( - body: Center( - child: Stack( - alignment: AlignmentDirectional.center, - children: [ - GestureDetector( - child: FutureBuilder( - future: initFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - //Управление шириной и высотой видео - double delta = MediaQuery.of(context).size.width - - MediaQuery.of(context).size.height * - _controller.value.aspectRatio; - if (MediaQuery.of(context).orientation == - Orientation.portrait || - delta < 0) { - videoHeight = MediaQuery.of(context).size.width / - _controller.value.aspectRatio; - videoWidth = MediaQuery.of(context).size.width; - videoMargin = 0; - } else { - videoHeight = MediaQuery.of(context).size.height; - videoWidth = - videoHeight * _controller.value.aspectRatio; - videoMargin = - (MediaQuery.of(context).size.width - videoWidth) / - 2; - } - //Переменные дабл тапа, зависимые от размеров видео - doubleTapRWidthFS = videoWidth; - doubleTapRHeightFS = videoHeight - 36; - doubleTapLWidthFS = videoWidth; - doubleTapLHeightFS = videoHeight; - - //Сразу при входе в режим фуллскрин перематываем - // на нужное место - if (_seek && fullScreen) { - _controller.seekTo(Duration(seconds: position)); - _seek = false; - } - - //Переходи на нужное место при смене качества - if (_seek && _controller.value.duration.inSeconds > 2) { - _controller.seekTo(Duration(seconds: position)); - _seek = false; - } - SystemChrome.setEnabledSystemUIOverlays( - [SystemUiOverlay.bottom]); - - //Отрисовка элементов плеера - return Stack( - children: [ - Container( - height: videoHeight, - width: videoWidth, - margin: EdgeInsets.only(left: videoMargin), - child: VideoPlayer(_controller), - ), - _videoOverlay(), - ], - ); - } else { - return Center( - heightFactor: 6, - child: CircularProgressIndicator( - strokeWidth: 4, - valueColor: AlwaysStoppedAnimation( - Color(0xFF22A3D2)), - )); - } - }), - //Редактируем размер области дабл тапа при показе оверлея. - // Сделано для открытия кнопок "Во весь экран" и "Качество" - onTap: () { - setState(() { - _overlay = !_overlay; - if (_overlay) { - doubleTapRHeightFS = videoHeight - 36; - doubleTapLHeightFS = videoHeight - 10; - doubleTapRMarginFS = 36; - doubleTapLMarginFS = 10; - } else if (!_overlay) { - doubleTapRHeightFS = videoHeight + 36; - doubleTapLHeightFS = videoHeight; - doubleTapRMarginFS = 0; - doubleTapLMarginFS = 0; - } - }); - }, - ), - GestureDetector( - child: Container( - width: doubleTapLWidthFS / 2 - 30, - height: doubleTapLHeightFS - 44, - margin: - EdgeInsets.fromLTRB(0, 0, doubleTapLWidthFS / 2 + 30, 40), - decoration: BoxDecoration( - //color: Colors.red, - ), - ), - //Редактируем размер области дабл тапа при показе оверлея. - // Сделано для открытия кнопок "Во весь экран" и "Качество" - onTap: () { - setState(() { - _overlay = !_overlay; - if (_overlay) { - doubleTapRHeightFS = videoHeight - 36; - doubleTapLHeightFS = videoHeight - 10; - doubleTapRMarginFS = 36; - doubleTapLMarginFS = 10; - } else if (!_overlay) { - doubleTapRHeightFS = videoHeight + 36; - doubleTapLHeightFS = videoHeight; - doubleTapRMarginFS = 0; - doubleTapLMarginFS = 0; - } - }); - }, - onDoubleTap: () { - setState(() { - _controller.seekTo(Duration( - seconds: _controller.value.position.inSeconds - 10)); - }); - }), - GestureDetector( - child: Container( - width: doubleTapRWidthFS / 2 - 45, - height: doubleTapRHeightFS - 80, - margin: EdgeInsets.fromLTRB(doubleTapRWidthFS / 2 + 45, 0, 0, - doubleTapLMarginFS + 20), - decoration: BoxDecoration( - //color: Colors.red, - ), - ), - //Редактируем размер области дабл тапа при показе оверлея. - // Сделано для открытия кнопок "Во весь экран" и "Качество" - onTap: () { - setState(() { - _overlay = !_overlay; - if (_overlay) { - doubleTapRHeightFS = videoHeight - 36; - doubleTapLHeightFS = videoHeight - 10; - doubleTapRMarginFS = 36; - doubleTapLMarginFS = 10; - } else if (!_overlay) { - doubleTapRHeightFS = videoHeight + 36; - doubleTapLHeightFS = videoHeight; - doubleTapRMarginFS = 0; - doubleTapLMarginFS = 0; - } - }); - }, - onDoubleTap: () { - setState(() { - _controller.seekTo(Duration( - seconds: _controller.value.position.inSeconds + 10)); - }); - }), - ], - )))); - } - - //================================ Quality ================================// - void _settingModalBottomSheet(context) { - showModalBottomSheet( - context: context, - builder: (BuildContext bc) { - final children = []; - _qualityValues.forEach((elem, value) => (children.add(new ListTile( - title: new Text(" ${elem.toString()} fps"), - onTap: () => { - //Обновление состояние приложения и перерисовка - setState(() { - _controller.pause(); - _controller = VideoPlayerController.network(value); - _controller.setLooping(true); - _seek = true; - initFuture = _controller.initialize(); - _controller.play(); - }), - })))); - - return Container( - height: videoHeight, - child: ListView( - children: children, - ), - ); - }); - } - - //================================ OVERLAY ================================// - Widget _videoOverlay() { - return _overlay - ? Stack( - children: [ - GestureDetector( - child: Center( - child: Container( - width: videoWidth, - height: videoHeight, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.centerRight, - end: Alignment.centerLeft, - colors: [ - const Color(0x662F2C47), - const Color(0x662F2C47) - ], - ), - ), - ), - ), - ), - Center( - child: IconButton( - padding: EdgeInsets.only( - top: videoHeight / 2 - 50, - bottom: videoHeight / 2 - 30, - ), - icon: _controller.value.isPlaying - ? Icon(Icons.pause, size: 60.0) - : Icon(Icons.play_arrow, size: 60.0), - onPressed: () { - setState(() { - _controller.value.isPlaying - ? _controller.pause() - : _controller.play(); - }); - }), - ), - Container( - margin: EdgeInsets.only( - top: videoHeight - 80, left: videoWidth + videoMargin - 50), - child: IconButton( - alignment: AlignmentDirectional.center, - icon: Icon(Icons.fullscreen, size: 30.0), - onPressed: () { - setState(() { - _controller.pause(); - SystemChrome.setPreferredOrientations([ - DeviceOrientation.portraitDown, - DeviceOrientation.portraitUp - ]); - SystemChrome.setEnabledSystemUIOverlays( - [SystemUiOverlay.top, SystemUiOverlay.bottom]); - }); - Navigator.pop( - context, _controller.value.position.inSeconds); - }), - ), - Container( - margin: EdgeInsets.only(left: videoWidth + videoMargin - 48), - child: IconButton( - icon: Icon(Icons.settings, size: 26.0), - onPressed: () { - position = _controller.value.position.inSeconds; - _seek = true; - _settingModalBottomSheet(context); - setState(() {}); - }), - ), - Container( - //===== Ползунок =====// - margin: EdgeInsets.only( - top: videoHeight - 40, left: videoMargin), //CHECK IT - child: _videoOverlaySlider(), - ) - ], - ) - : Center(); - } - - //=================== ПОЛЗУНОК ===================// - Widget _videoOverlaySlider() { - return ValueListenableBuilder( - valueListenable: _controller, - builder: (context, VideoPlayerValue value, child) { - if (!value.hasError && value.initialized) { - return Row( - children: [ - Container( - width: 46, - alignment: Alignment(0, 0), - child: Text(value.position.inMinutes.toString() + - ':' + - (value.position.inSeconds - value.position.inMinutes * 60) - .toString()), - ), - Container( - height: 20, - width: videoWidth - 92, - child: VideoProgressIndicator( - _controller, - allowScrubbing: true, - colors: VideoProgressColors( - playedColor: Color(0xFF22A3D2), - backgroundColor: Color(0x5515162B), - bufferedColor: Color(0x5583D8F7), - ), - padding: EdgeInsets.only(top: 8.0, bottom: 8.0), - ), - ), - Container( - width: 46, - alignment: Alignment(0, 0), - child: Text(value.duration.inMinutes.toString() + - ':' + - (value.duration.inSeconds - value.duration.inMinutes * 60) - .toString()), - ), - ], - ); - } else { - return Container(); - } - }, - ); - } -} diff --git a/example/lib/vimeoplayer.dart b/example/lib/vimeoplayer.dart index 0da5cb3..06ae3b8 100644 --- a/example/lib/vimeoplayer.dart +++ b/example/lib/vimeoplayer.dart @@ -6,7 +6,6 @@ import 'package:video_player/video_player.dart'; import 'package:flutter/services.dart'; import 'src/quality_links.dart'; import 'dart:async'; -import 'src/fullscreen_player.dart'; //Класс видео плеера class VimeoPlayer extends StatefulWidget { @@ -153,19 +152,6 @@ class _VimeoPlayerState extends State { margin: EdgeInsets.only(left: videoMargin), child: Chewie(controller: _chewieController), ); - - //Отрисовка элементов плеера - // return Stack( - // children: [ - // Container( - // height: videoHeight, - // width: videoWidth, - // margin: EdgeInsets.only(left: videoMargin), - // child: Chewie(controller: _chewieController), - // ), - // _videoOverlay(), - // ], - // ); } else { return Center( heightFactor: 6, @@ -265,188 +251,6 @@ class _VimeoPlayerState extends State { )); } - //================================ Quality ================================// - void _settingModalBottomSheet(context) { - showModalBottomSheet( - context: context, - builder: (BuildContext bc) { - //Формирования списка качества - final children = []; - _qualityValues.forEach((elem, value) => (children.add(new ListTile( - title: new Text(" ${elem.toString()} fps"), - onTap: () => { - //Обновление состояние приложения и перерисовка - setState(() { - _videoPlayerController.pause(); - _qualityValue = value; - _videoPlayerController = VideoPlayerController.network(_qualityValue); - _videoPlayerController.setLooping(true); - _seek = true; - initFuture = _videoPlayerController.initialize(); - _videoPlayerController.play(); - }), - })))); - //Вывод элементов качество списком - return Container( - child: Wrap( - children: children, - ), - ); - }); - } - - //================================ OVERLAY ================================// - Widget _videoOverlay() { - return _overlay - ? Stack( - children: [ - GestureDetector( - child: Center( - child: Container( - width: videoWidth, - height: videoHeight, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.centerRight, - end: Alignment.centerLeft, - colors: [const Color(0x662F2C47), const Color(0x662F2C47)], - ), - ), - ), - ), - ), - Center( - child: IconButton( - padding: EdgeInsets.only(top: videoHeight / 2 - 30, bottom: videoHeight / 2 - 30), - icon: _videoPlayerController.value.isPlaying - ? Icon(Icons.pause, size: 60.0) - : Icon(Icons.play_arrow, size: 60.0), - onPressed: () { - setState(() { - _videoPlayerController.value.isPlaying - ? _videoPlayerController.pause() - : _videoPlayerController.play(); - }); - }), - ), - Container( - margin: EdgeInsets.only(top: videoHeight - 70, left: videoWidth + videoMargin - 50), - child: IconButton( - alignment: AlignmentDirectional.center, - icon: Icon(Icons.fullscreen, size: 30.0), - onPressed: () async { - setState(() { - _videoPlayerController.pause(); - }); - //Создание новой страницы с плеером во весь экран, - // предача данных в плеер и возвращение позиции при - // возвращении обратно. Пока что мы не вернулись из - // фуллскрина - программа в ожидании - position = await Navigator.push( - context, - PageRouteBuilder( - opaque: false, - pageBuilder: (BuildContext context, _, __) => FullscreenPlayer( - id: _id, - autoPlay: true, - controller: _videoPlayerController, - position: _videoPlayerController.value.position.inSeconds, - initFuture: initFuture, - qualityValue: _qualityValue), - transitionsBuilder: (___, Animation animation, ____, Widget child) { - return FadeTransition( - opacity: animation, - child: ScaleTransition(scale: animation, child: child), - ); - })); - setState(() { - _videoPlayerController.play(); - _seek = true; - }); - }), - ), - Container( - margin: EdgeInsets.only(left: videoWidth + videoMargin - 48), - child: IconButton( - icon: Icon(Icons.settings, size: 26.0), - onPressed: () { - position = _videoPlayerController.value.position.inSeconds; - _seek = true; - _settingModalBottomSheet(context); - setState(() {}); - }), - ), - Container( - //===== Ползунок =====// - margin: EdgeInsets.only(top: videoHeight - 26, left: videoMargin), //CHECK IT - child: _videoOverlaySlider(), - ) - ], - ) - : Center( - child: Container( - height: 5, - width: videoWidth, - margin: EdgeInsets.only(top: videoHeight - 5), - child: VideoProgressIndicator( - _videoPlayerController, - allowScrubbing: true, - colors: VideoProgressColors( - playedColor: Color(0xFF22A3D2), - backgroundColor: Color(0x5515162B), - bufferedColor: Color(0x5583D8F7), - ), - padding: EdgeInsets.only(top: 2), - ), - ), - ); - } - - //=================== ПОЛЗУНОК ===================// - Widget _videoOverlaySlider() { - return ValueListenableBuilder( - valueListenable: _videoPlayerController, - builder: (context, VideoPlayerValue value, child) { - if (!value.hasError && value.initialized) { - return Row( - children: [ - Container( - width: 46, - alignment: Alignment(0, 0), - child: Text(value.position.inMinutes.toString() + - ':' + - (value.position.inSeconds - value.position.inMinutes * 60).toString()), - ), - Container( - height: 20, - width: videoWidth - 92, - child: VideoProgressIndicator( - _videoPlayerController, - allowScrubbing: true, - colors: VideoProgressColors( - playedColor: Color(0xFF22A3D2), - backgroundColor: Color(0x5515162B), - bufferedColor: Color(0x5583D8F7), - ), - padding: EdgeInsets.only(top: 8.0, bottom: 8.0), - ), - ), - Container( - width: 46, - alignment: Alignment(0, 0), - child: Text(value.duration.inMinutes.toString() + - ':' + - (value.duration.inSeconds - value.duration.inMinutes * 60).toString()), - ), - ], - ); - } else { - return Container(); - } - }, - ); - } - @override void dispose() { _chewieController.dispose(); diff --git a/lib/src/fullscreen_player.dart b/lib/src/fullscreen_player.dart deleted file mode 100644 index b674f18..0000000 --- a/lib/src/fullscreen_player.dart +++ /dev/null @@ -1,432 +0,0 @@ -library vimeoplayer; - -import 'package:flutter/material.dart'; -import 'package:video_player/video_player.dart'; -import 'package:flutter/services.dart'; -import 'quality_links.dart'; -import 'dart:async'; - -//Класс видео плеера во весь экран -class FullscreenPlayer extends StatefulWidget { - final String id; - final bool autoPlay; - final bool looping; - final VideoPlayerController controller; - final position; - final Future initFuture; - final String qualityValue; - - FullscreenPlayer({ - @required this.id, - this.autoPlay, - this.looping, - this.controller, - this.position, - this.initFuture, - this.qualityValue, - Key key, - }) : super(key: key); - - @override - _FullscreenPlayerState createState() => _FullscreenPlayerState( - id, autoPlay, looping, controller, position, initFuture, qualityValue); -} - -class _FullscreenPlayerState extends State { - String _id; - bool autoPlay = false; - bool looping = false; - bool _overlay = true; - bool fullScreen = true; - - VideoPlayerController controller; - VideoPlayerController _controller; - - int position; - - Future initFuture; - var qualityValue; - - _FullscreenPlayerState(this._id, this.autoPlay, this.looping, this.controller, - this.position, this.initFuture, this.qualityValue); - - // Quality Class - QualityLinks _quality; - Map _qualityValues; - - //Переменная перемотки - bool _seek = true; - - //Переменные видео - double videoHeight; - double videoWidth; - double videoMargin; - - //Переменные под зоны дабл-тапа - double doubleTapRMarginFS = 36; - double doubleTapRWidthFS = 700; - double doubleTapRHeightFS = 300; - double doubleTapLMarginFS = 10; - double doubleTapLWidthFS = 700; - double doubleTapLHeightFS = 400; - - @override - void initState() { - //Инициализация контроллеров видео при получении данных из Vimeo - _controller = controller; - if (autoPlay) _controller.play(); - - // Подгрузка списка качеств видео - _quality = QualityLinks(_id); //Create class - _quality.getQualitiesSync().then((value) { - _qualityValues = value; - }); - - setState(() { - SystemChrome.setPreferredOrientations( - [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); - SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]); - }); - - super.initState(); - } - - //Ослеживаем пользовательского нажатие назад и переводим - // на экран с плеером не в режиме фуллскрин, возвращаем ориентацию - Future _onWillPop() { - setState(() { - _controller.pause(); - SystemChrome.setPreferredOrientations( - [DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); - SystemChrome.setEnabledSystemUIOverlays( - [SystemUiOverlay.top, SystemUiOverlay.bottom]); - }); - Navigator.pop(context, _controller.value.position.inSeconds); - return Future.value(true); - } - - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: _onWillPop, - child: Scaffold( - body: Center( - child: Stack( - alignment: AlignmentDirectional.center, - children: [ - GestureDetector( - child: FutureBuilder( - future: initFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - //Управление шириной и высотой видео - double delta = MediaQuery.of(context).size.width - - MediaQuery.of(context).size.height * - _controller.value.aspectRatio; - if (MediaQuery.of(context).orientation == - Orientation.portrait || - delta < 0) { - videoHeight = MediaQuery.of(context).size.width / - _controller.value.aspectRatio; - videoWidth = MediaQuery.of(context).size.width; - videoMargin = 0; - } else { - videoHeight = MediaQuery.of(context).size.height; - videoWidth = - videoHeight * _controller.value.aspectRatio; - videoMargin = - (MediaQuery.of(context).size.width - videoWidth) / - 2; - } - //Переменные дабл тапа, зависимые от размеров видео - doubleTapRWidthFS = videoWidth; - doubleTapRHeightFS = videoHeight - 36; - doubleTapLWidthFS = videoWidth; - doubleTapLHeightFS = videoHeight; - - //Сразу при входе в режим фуллскрин перематываем - // на нужное место - if (_seek && fullScreen) { - _controller.seekTo(Duration(seconds: position)); - _seek = false; - } - - //Переходи на нужное место при смене качества - if (_seek && _controller.value.duration.inSeconds > 2) { - _controller.seekTo(Duration(seconds: position)); - _seek = false; - } - SystemChrome.setEnabledSystemUIOverlays( - [SystemUiOverlay.bottom]); - - //Отрисовка элементов плеера - return Stack( - children: [ - Container( - height: videoHeight, - width: videoWidth, - margin: EdgeInsets.only(left: videoMargin), - child: VideoPlayer(_controller), - ), - _videoOverlay(), - ], - ); - } else { - return Center( - heightFactor: 6, - child: CircularProgressIndicator( - strokeWidth: 4, - valueColor: AlwaysStoppedAnimation( - Color(0xFF22A3D2)), - )); - } - }), - //Редактируем размер области дабл тапа при показе оверлея. - // Сделано для открытия кнопок "Во весь экран" и "Качество" - onTap: () { - setState(() { - _overlay = !_overlay; - if (_overlay) { - doubleTapRHeightFS = videoHeight - 36; - doubleTapLHeightFS = videoHeight - 10; - doubleTapRMarginFS = 36; - doubleTapLMarginFS = 10; - } else if (!_overlay) { - doubleTapRHeightFS = videoHeight + 36; - doubleTapLHeightFS = videoHeight; - doubleTapRMarginFS = 0; - doubleTapLMarginFS = 0; - } - }); - }, - ), - GestureDetector( - child: Container( - width: doubleTapLWidthFS / 2 - 30, - height: doubleTapLHeightFS - 44, - margin: - EdgeInsets.fromLTRB(0, 0, doubleTapLWidthFS / 2 + 30, 40), - decoration: BoxDecoration( - //color: Colors.red, - ), - ), - //Редактируем размер области дабл тапа при показе оверлея. - // Сделано для открытия кнопок "Во весь экран" и "Качество" - onTap: () { - setState(() { - _overlay = !_overlay; - if (_overlay) { - doubleTapRHeightFS = videoHeight - 36; - doubleTapLHeightFS = videoHeight - 10; - doubleTapRMarginFS = 36; - doubleTapLMarginFS = 10; - } else if (!_overlay) { - doubleTapRHeightFS = videoHeight + 36; - doubleTapLHeightFS = videoHeight; - doubleTapRMarginFS = 0; - doubleTapLMarginFS = 0; - } - }); - }, - onDoubleTap: () { - setState(() { - _controller.seekTo(Duration( - seconds: _controller.value.position.inSeconds - 10)); - }); - }), - GestureDetector( - child: Container( - width: doubleTapRWidthFS / 2 - 45, - height: doubleTapRHeightFS - 80, - margin: EdgeInsets.fromLTRB(doubleTapRWidthFS / 2 + 45, 0, 0, - doubleTapLMarginFS + 20), - decoration: BoxDecoration( - //color: Colors.red, - ), - ), - //Редактируем размер области дабл тапа при показе оверлея. - // Сделано для открытия кнопок "Во весь экран" и "Качество" - onTap: () { - setState(() { - _overlay = !_overlay; - if (_overlay) { - doubleTapRHeightFS = videoHeight - 36; - doubleTapLHeightFS = videoHeight - 10; - doubleTapRMarginFS = 36; - doubleTapLMarginFS = 10; - } else if (!_overlay) { - doubleTapRHeightFS = videoHeight + 36; - doubleTapLHeightFS = videoHeight; - doubleTapRMarginFS = 0; - doubleTapLMarginFS = 0; - } - }); - }, - onDoubleTap: () { - setState(() { - _controller.seekTo(Duration( - seconds: _controller.value.position.inSeconds + 10)); - }); - }), - ], - )))); - } - - //================================ Quality ================================// - void _settingModalBottomSheet(context) { - showModalBottomSheet( - context: context, - builder: (BuildContext bc) { - final children = []; - _qualityValues.forEach((elem, value) => (children.add(new ListTile( - title: new Text(" ${elem.toString()} fps"), - onTap: () => { - //Обновление состояние приложения и перерисовка - setState(() { - _controller.pause(); - _controller = VideoPlayerController.network(value); - _controller.setLooping(true); - _seek = true; - initFuture = _controller.initialize(); - _controller.play(); - }), - })))); - - return Container( - height: videoHeight, - child: ListView( - children: children, - ), - ); - }); - } - - //================================ OVERLAY ================================// - Widget _videoOverlay() { - return _overlay - ? Stack( - children: [ - GestureDetector( - child: Center( - child: Container( - width: videoWidth, - height: videoHeight, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.centerRight, - end: Alignment.centerLeft, - colors: [ - const Color(0x662F2C47), - const Color(0x662F2C47) - ], - ), - ), - ), - ), - ), - Center( - child: IconButton( - padding: EdgeInsets.only( - top: videoHeight / 2 - 50, - bottom: videoHeight / 2 - 30, - ), - icon: _controller.value.isPlaying - ? Icon(Icons.pause, size: 60.0) - : Icon(Icons.play_arrow, size: 60.0), - onPressed: () { - setState(() { - _controller.value.isPlaying - ? _controller.pause() - : _controller.play(); - }); - }), - ), - Container( - margin: EdgeInsets.only( - top: videoHeight - 80, left: videoWidth + videoMargin - 50), - child: IconButton( - alignment: AlignmentDirectional.center, - icon: Icon(Icons.fullscreen, size: 30.0), - onPressed: () { - setState(() { - _controller.pause(); - SystemChrome.setPreferredOrientations([ - DeviceOrientation.portraitDown, - DeviceOrientation.portraitUp - ]); - SystemChrome.setEnabledSystemUIOverlays( - [SystemUiOverlay.top, SystemUiOverlay.bottom]); - }); - Navigator.pop( - context, _controller.value.position.inSeconds); - }), - ), - Container( - margin: EdgeInsets.only(left: videoWidth + videoMargin - 48), - child: IconButton( - icon: Icon(Icons.settings, size: 26.0), - onPressed: () { - position = _controller.value.position.inSeconds; - _seek = true; - _settingModalBottomSheet(context); - setState(() {}); - }), - ), - Container( - //===== Ползунок =====// - margin: EdgeInsets.only( - top: videoHeight - 40, left: videoMargin), //CHECK IT - child: _videoOverlaySlider(), - ) - ], - ) - : Center(); - } - - //=================== ПОЛЗУНОК ===================// - Widget _videoOverlaySlider() { - return ValueListenableBuilder( - valueListenable: _controller, - builder: (context, VideoPlayerValue value, child) { - if (!value.hasError && value.initialized) { - return Row( - children: [ - Container( - width: 46, - alignment: Alignment(0, 0), - child: Text(value.position.inMinutes.toString() + - ':' + - (value.position.inSeconds - value.position.inMinutes * 60) - .toString()), - ), - Container( - height: 20, - width: videoWidth - 92, - child: VideoProgressIndicator( - _controller, - allowScrubbing: true, - colors: VideoProgressColors( - playedColor: Color(0xFF22A3D2), - backgroundColor: Color(0x5515162B), - bufferedColor: Color(0x5583D8F7), - ), - padding: EdgeInsets.only(top: 8.0, bottom: 8.0), - ), - ), - Container( - width: 46, - alignment: Alignment(0, 0), - child: Text(value.duration.inMinutes.toString() + - ':' + - (value.duration.inSeconds - value.duration.inMinutes * 60) - .toString()), - ), - ], - ); - } else { - return Container(); - } - }, - ); - } -} diff --git a/lib/vimeoplayer.dart b/lib/vimeoplayer.dart index 6c6d506..0b18d2d 100644 --- a/lib/vimeoplayer.dart +++ b/lib/vimeoplayer.dart @@ -1,11 +1,11 @@ library vimeoplayer; +import 'package:chewie/chewie.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; import 'package:flutter/services.dart'; import 'src/quality_links.dart'; import 'dart:async'; -import 'src/fullscreen_player.dart'; //Класс видео плеера class VimeoPlayer extends StatefulWidget { @@ -23,8 +23,7 @@ class VimeoPlayer extends StatefulWidget { }) : super(key: key); @override - _VimeoPlayerState createState() => - _VimeoPlayerState(id, autoPlay, looping, position); + _VimeoPlayerState createState() => _VimeoPlayerState(id, autoPlay, looping, position); } class _VimeoPlayerState extends State { @@ -39,6 +38,8 @@ class _VimeoPlayerState extends State { //Custom controller VideoPlayerController _controller; + ChewieController _chewieController; + Future initFuture; //Quality Class @@ -74,18 +75,40 @@ class _VimeoPlayerState extends State { _controller = VideoPlayerController.network(_qualityValue); _controller.setLooping(looping); if (autoPlay) _controller.play(); - initFuture = _controller.initialize(); + initFuture = _controller.initialize().then((value) { + _chewieController = ChewieController( + videoPlayerController: _controller, + // Prepare the video to be played and display the first frame + autoInitialize: true, + allowFullScreen: fullScreen, + deviceOrientationsOnEnterFullScreen: [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight], + systemOverlaysOnEnterFullScreen: [SystemUiOverlay.bottom], + deviceOrientationsAfterFullScreen: [DeviceOrientation.portraitDown, DeviceOrientation.portraitUp], + systemOverlaysAfterFullScreen: [SystemUiOverlay.top, SystemUiOverlay.bottom], + aspectRatio: _controller.value.aspectRatio, + looping: looping, + autoPlay: autoPlay, + // Errors can occur for example when trying to play a video + // from a non-existent URL + errorBuilder: (context, errorMessage) { + return Center( + child: Text( + errorMessage, + style: TextStyle(color: Colors.white), + ), + ); + }, + ); + }); //Обновление состояние приложения и перерисовка setState(() { - SystemChrome.setPreferredOrientations( - [DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); }); }); //На странице видео преимущество за портретной ориентацией - SystemChrome.setPreferredOrientations( - [DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values); super.initState(); @@ -105,23 +128,18 @@ class _VimeoPlayerState extends State { if (snapshot.connectionState == ConnectionState.done) { //Управление шириной и высотой видео double delta = MediaQuery.of(context).size.width - - MediaQuery.of(context).size.height * - _controller.value.aspectRatio; + MediaQuery.of(context).size.height * _controller.value.aspectRatio; //Рассчет ширины и высоты видео плеера относительно сторон // и ориентации устройства - if (MediaQuery.of(context).orientation == - Orientation.portrait || - delta < 0) { - videoHeight = MediaQuery.of(context).size.width / - _controller.value.aspectRatio; + if (MediaQuery.of(context).orientation == Orientation.portrait || delta < 0) { + videoHeight = MediaQuery.of(context).size.width / _controller.value.aspectRatio; videoWidth = MediaQuery.of(context).size.width; videoMargin = 0; } else { videoHeight = MediaQuery.of(context).size.height; videoWidth = videoHeight * _controller.value.aspectRatio; - videoMargin = - (MediaQuery.of(context).size.width - videoWidth) / 2; + videoMargin = (MediaQuery.of(context).size.width - videoWidth) / 2; } //Начинаем с того же места, где и остановились при смене качества @@ -130,25 +148,16 @@ class _VimeoPlayerState extends State { _seek = false; } - //Отрисовка элементов плеера - return Stack( - children: [ - Container( - height: videoHeight, - width: videoWidth, - margin: EdgeInsets.only(left: videoMargin), - child: VideoPlayer(_controller), - ), - _videoOverlay(), - ], + return Container( + margin: EdgeInsets.only(left: videoMargin), + child: Chewie(controller: _chewieController), ); } else { return Center( heightFactor: 6, child: CircularProgressIndicator( strokeWidth: 4, - valueColor: - AlwaysStoppedAnimation(Color(0xFF22A3D2)), + valueColor: AlwaysStoppedAnimation(Color(0xFF22A3D2)), )); } }), @@ -176,11 +185,10 @@ class _VimeoPlayerState extends State { child: Container( width: doubleTapLWidth / 2 - 30, height: doubleTapLHeight - 46, - margin: EdgeInsets.fromLTRB( - 0, 10, doubleTapLWidth / 2 + 30, doubleTapLMargin + 20), + margin: EdgeInsets.fromLTRB(0, 10, doubleTapLWidth / 2 + 30, doubleTapLMargin + 20), decoration: BoxDecoration( - //color: Colors.red, - ), + //color: Colors.red, + ), ), // Изменение размера блоков дабл тапа. Нужно для открытия кнопок @@ -203,8 +211,7 @@ class _VimeoPlayerState extends State { }, onDoubleTap: () { setState(() { - _controller.seekTo(Duration( - seconds: _controller.value.position.inSeconds - 10)); + _controller.seekTo(Duration(seconds: _controller.value.position.inSeconds - 10)); }); }), GestureDetector( @@ -212,11 +219,10 @@ class _VimeoPlayerState extends State { //======= Перемотка вперед =======// width: doubleTapRWidth / 2 - 45, height: doubleTapRHeight - 60, - margin: EdgeInsets.fromLTRB(doubleTapRWidth / 2 + 45, - doubleTapRMargin, 0, doubleTapRMargin + 20), + margin: EdgeInsets.fromLTRB(doubleTapRWidth / 2 + 45, doubleTapRMargin, 0, doubleTapRMargin + 20), decoration: BoxDecoration( - //color: Colors.red, - ), + //color: Colors.red, + ), ), // Изменение размера блоков дабл тапа. Нужно для открытия кнопок // "Во весь экран" и "Качество" при включенном overlay @@ -238,212 +244,13 @@ class _VimeoPlayerState extends State { }, onDoubleTap: () { setState(() { - _controller.seekTo(Duration( - seconds: _controller.value.position.inSeconds + 10)); + _controller.seekTo(Duration(seconds: _controller.value.position.inSeconds + 10)); }); }), ], )); } - //================================ Quality ================================// - void _settingModalBottomSheet(context) { - showModalBottomSheet( - context: context, - builder: (BuildContext bc) { - //Формирования списка качества - final children = []; - _qualityValues.forEach((elem, value) => (children.add(new ListTile( - title: new Text(" ${elem.toString()} fps"), - onTap: () => { - //Обновление состояние приложения и перерисовка - setState(() { - _controller.pause(); - _qualityValue = value; - _controller = - VideoPlayerController.network(_qualityValue); - _controller.setLooping(true); - _seek = true; - initFuture = _controller.initialize(); - _controller.play(); - }), - })))); - //Вывод элементов качество списком - return Container( - child: Wrap( - children: children, - ), - ); - }); - } - - //================================ OVERLAY ================================// - Widget _videoOverlay() { - return _overlay - ? Stack( - children: [ - GestureDetector( - child: Center( - child: Container( - width: videoWidth, - height: videoHeight, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.centerRight, - end: Alignment.centerLeft, - colors: [ - const Color(0x662F2C47), - const Color(0x662F2C47) - ], - ), - ), - ), - ), - ), - Center( - child: IconButton( - padding: EdgeInsets.only( - top: videoHeight / 2 - 30, - bottom: videoHeight / 2 - 30), - icon: _controller.value.isPlaying - ? Icon(Icons.pause, size: 60.0) - : Icon(Icons.play_arrow, size: 60.0), - onPressed: () { - setState(() { - _controller.value.isPlaying - ? _controller.pause() - : _controller.play(); - }); - }), - ), - Container( - margin: EdgeInsets.only( - top: videoHeight - 70, left: videoWidth + videoMargin - 50), - child: IconButton( - alignment: AlignmentDirectional.center, - icon: Icon(Icons.fullscreen, size: 30.0), - onPressed: () async { - setState(() { - _controller.pause(); - }); - //Создание новой страницы с плеером во весь экран, - // предача данных в плеер и возвращение позиции при - // возвращении обратно. Пока что мы не вернулись из - // фуллскрина - программа в ожидании - position = await Navigator.push( - context, - PageRouteBuilder( - opaque: false, - pageBuilder: (BuildContext context, _, __) => - FullscreenPlayer( - id: _id, - autoPlay: true, - controller: _controller, - position: - _controller.value.position.inSeconds, - initFuture: initFuture, - qualityValue: _qualityValue), - transitionsBuilder: (___, - Animation animation, - ____, - Widget child) { - return FadeTransition( - opacity: animation, - child: ScaleTransition( - scale: animation, child: child), - ); - })); - setState(() { - _controller.play(); - _seek = true; - }); - }), - ), - Container( - margin: EdgeInsets.only(left: videoWidth + videoMargin - 48), - child: IconButton( - icon: Icon(Icons.settings, size: 26.0), - onPressed: () { - position = _controller.value.position.inSeconds; - _seek = true; - _settingModalBottomSheet(context); - setState(() {}); - }), - ), - Container( - //===== Ползунок =====// - margin: EdgeInsets.only( - top: videoHeight - 26, left: videoMargin), //CHECK IT - child: _videoOverlaySlider(), - ) - ], - ) - : Center( - child: Container( - height: 5, - width: videoWidth, - margin: EdgeInsets.only(top: videoHeight - 5), - child: VideoProgressIndicator( - _controller, - allowScrubbing: true, - colors: VideoProgressColors( - playedColor: Color(0xFF22A3D2), - backgroundColor: Color(0x5515162B), - bufferedColor: Color(0x5583D8F7), - ), - padding: EdgeInsets.only(top: 2), - ), - ), - ); - } - - //=================== ПОЛЗУНОК ===================// - Widget _videoOverlaySlider() { - return ValueListenableBuilder( - valueListenable: _controller, - builder: (context, VideoPlayerValue value, child) { - if (!value.hasError && value.initialized) { - return Row( - children: [ - Container( - width: 46, - alignment: Alignment(0, 0), - child: Text(value.position.inMinutes.toString() + - ':' + - (value.position.inSeconds - value.position.inMinutes * 60) - .toString()), - ), - Container( - height: 20, - width: videoWidth - 92, - child: VideoProgressIndicator( - _controller, - allowScrubbing: true, - colors: VideoProgressColors( - playedColor: Color(0xFF22A3D2), - backgroundColor: Color(0x5515162B), - bufferedColor: Color(0x5583D8F7), - ), - padding: EdgeInsets.only(top: 8.0, bottom: 8.0), - ), - ), - Container( - width: 46, - alignment: Alignment(0, 0), - child: Text(value.duration.inMinutes.toString() + - ':' + - (value.duration.inSeconds - value.duration.inMinutes * 60) - .toString()), - ), - ], - ); - } else { - return Container(); - } - }, - ); - } - @override void dispose() { _controller.dispose(); diff --git a/pubspec.lock b/pubspec.lock index 0ec86d4..03f5977 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -29,6 +29,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0-nullsafety.1" + chewie: + dependency: "direct main" + description: + name: chewie + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.2" clock: dependency: transitive description: @@ -43,6 +50,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0-nullsafety.3" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.2" + cupertino_icons: + dependency: transitive + description: + name: cupertino_icons + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" fake_async: dependency: transitive description: @@ -65,6 +86,13 @@ packages: description: flutter source: sdk version: "0.0.0" + html: + dependency: transitive + description: + name: html + url: "https://pub.dartlang.org" + source: hosted + version: "0.14.0+4" http: dependency: "direct main" description: @@ -79,6 +107,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.4" + import_js_library: + dependency: transitive + description: + name: import_js_library + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.2" matcher: dependency: transitive description: @@ -174,7 +216,7 @@ packages: name: video_player url: "https://pub.dartlang.org" source: hosted - version: "0.11.1+2" + version: "1.0.1" video_player_platform_interface: dependency: transitive description: @@ -189,6 +231,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.4" + wakelock: + dependency: transitive + description: + name: wakelock + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.1+1" + wakelock_platform_interface: + dependency: transitive + description: + name: wakelock_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0+1" + wakelock_web: + dependency: transitive + description: + name: wakelock_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0+3" sdks: dart: ">=2.10.0-110 <2.11.0" - flutter: ">=1.12.13+hotfix.5 <2.0.0" + flutter: ">=1.22.0 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 9922afe..9c4b103 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,6 +11,7 @@ dependencies: sdk: flutter video_player: '>=0.10.0 <2.0.0' http: ^0.12.1 + chewie: ^0.12.2 dev_dependencies: flutter_test: From 32f946fc5e8e6308bc26bfc638d365bdeae7040d Mon Sep 17 00:00:00 2001 From: felixmo_trustMe Date: Wed, 3 Feb 2021 15:55:20 +0800 Subject: [PATCH 03/10] Added fullScreen variable on vimeoplayer --- lib/vimeoplayer.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/vimeoplayer.dart b/lib/vimeoplayer.dart index 0b18d2d..6920cae 100644 --- a/lib/vimeoplayer.dart +++ b/lib/vimeoplayer.dart @@ -13,17 +13,19 @@ class VimeoPlayer extends StatefulWidget { final bool autoPlay; final bool looping; final int position; + final bool fullScreen; VimeoPlayer({ @required this.id, this.autoPlay, this.looping, this.position, + this.fullScreen, Key key, }) : super(key: key); @override - _VimeoPlayerState createState() => _VimeoPlayerState(id, autoPlay, looping, position); + _VimeoPlayerState createState() => _VimeoPlayerState(id, autoPlay, looping, position, fullScreen); } class _VimeoPlayerState extends State { @@ -34,7 +36,7 @@ class _VimeoPlayerState extends State { bool fullScreen = false; int position; - _VimeoPlayerState(this._id, this.autoPlay, this.looping, this.position); + _VimeoPlayerState(this._id, this.autoPlay, this.looping, this.position, this.fullScreen); //Custom controller VideoPlayerController _controller; From 9d34ac83899053d829b557b0f5140c3ddc1bda6e Mon Sep 17 00:00:00 2001 From: felixmo_trustMe Date: Wed, 3 Feb 2021 17:21:52 +0800 Subject: [PATCH 04/10] Changed name of fullScreen to allowFullScreen --- example/lib/main.dart | 2 +- example/lib/vimeoplayer.dart | 14 +++++++++----- lib/vimeoplayer.dart | 14 +++++++++----- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 2d516cd..09ecb15 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -36,7 +36,7 @@ class VideoScreen extends StatelessWidget { preferredSize: Size(0.0, 0.0), ), body: ListView(children: [ - VimeoPlayer(id: '505942118', autoPlay: true, fullScreen: true), + VimeoPlayer(id: '505942118', autoPlay: true, allowFullScreen: true), ])); } } diff --git a/example/lib/vimeoplayer.dart b/example/lib/vimeoplayer.dart index 06ae3b8..b6d798f 100644 --- a/example/lib/vimeoplayer.dart +++ b/example/lib/vimeoplayer.dart @@ -13,19 +13,20 @@ class VimeoPlayer extends StatefulWidget { final bool autoPlay; final bool looping; final int position; - final bool fullScreen; + final bool allowFullScreen; VimeoPlayer({ @required this.id, this.autoPlay, this.looping, this.position, - this.fullScreen, + @required this.allowFullScreen, Key key, - }) : super(key: key); + }) : assert(id != null && allowFullScreen != null), + super(key: key); @override - _VimeoPlayerState createState() => _VimeoPlayerState(id, autoPlay, looping, position, fullScreen); + _VimeoPlayerState createState() => _VimeoPlayerState(id, autoPlay, looping, position, allowFullScreen); } class _VimeoPlayerState extends State { @@ -34,9 +35,10 @@ class _VimeoPlayerState extends State { bool looping = false; bool _overlay = true; bool fullScreen = false; + bool allowFullScreen = false; int position; - _VimeoPlayerState(this._id, this.autoPlay, this.looping, this.position, this.fullScreen); + _VimeoPlayerState(this._id, this.autoPlay, this.looping, this.position, this.allowFullScreen); //Custom controller VideoPlayerController _videoPlayerController; @@ -67,6 +69,8 @@ class _VimeoPlayerState extends State { @override void initState() { + fullScreen = allowFullScreen; + //Create class _quality = QualityLinks(_id); diff --git a/lib/vimeoplayer.dart b/lib/vimeoplayer.dart index 6920cae..f22a54c 100644 --- a/lib/vimeoplayer.dart +++ b/lib/vimeoplayer.dart @@ -13,19 +13,20 @@ class VimeoPlayer extends StatefulWidget { final bool autoPlay; final bool looping; final int position; - final bool fullScreen; + final bool allowFullScreen; VimeoPlayer({ @required this.id, this.autoPlay, this.looping, this.position, - this.fullScreen, + @required this.allowFullScreen, Key key, - }) : super(key: key); + }) : assert(id != null && allowFullScreen != null), + super(key: key); @override - _VimeoPlayerState createState() => _VimeoPlayerState(id, autoPlay, looping, position, fullScreen); + _VimeoPlayerState createState() => _VimeoPlayerState(id, autoPlay, looping, position, allowFullScreen); } class _VimeoPlayerState extends State { @@ -34,9 +35,10 @@ class _VimeoPlayerState extends State { bool looping = false; bool _overlay = true; bool fullScreen = false; + bool allowFullScreen = false; int position; - _VimeoPlayerState(this._id, this.autoPlay, this.looping, this.position, this.fullScreen); + _VimeoPlayerState(this._id, this.autoPlay, this.looping, this.position, this.allowFullScreen); //Custom controller VideoPlayerController _controller; @@ -67,6 +69,8 @@ class _VimeoPlayerState extends State { @override void initState() { + fullScreen = allowFullScreen; + //Create class _quality = QualityLinks(_id); From c6ebc136c037058535312f5e60fd9d560cda443e Mon Sep 17 00:00:00 2001 From: felixmo_trustMe Date: Thu, 4 Feb 2021 11:44:07 +0800 Subject: [PATCH 05/10] Reset future function --- example/lib/vimeoplayer.dart | 1 + lib/vimeoplayer.dart | 1 + 2 files changed, 2 insertions(+) diff --git a/example/lib/vimeoplayer.dart b/example/lib/vimeoplayer.dart index b6d798f..6a7a874 100644 --- a/example/lib/vimeoplayer.dart +++ b/example/lib/vimeoplayer.dart @@ -259,6 +259,7 @@ class _VimeoPlayerState extends State { void dispose() { _chewieController.dispose(); _videoPlayerController.dispose(); + initFuture = null; super.dispose(); } } diff --git a/lib/vimeoplayer.dart b/lib/vimeoplayer.dart index f22a54c..19b6fe2 100644 --- a/lib/vimeoplayer.dart +++ b/lib/vimeoplayer.dart @@ -260,6 +260,7 @@ class _VimeoPlayerState extends State { @override void dispose() { _controller.dispose(); + initFuture = null; super.dispose(); } } From ff2834c85aba58f6a98fed1686da3ce5a5f1d8ac Mon Sep 17 00:00:00 2001 From: felixmo_trustMe Date: Fri, 5 Feb 2021 16:54:03 +0800 Subject: [PATCH 06/10] Updated comments --- lib/vimeoplayer.dart | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/lib/vimeoplayer.dart b/lib/vimeoplayer.dart index 19b6fe2..d782c49 100644 --- a/lib/vimeoplayer.dart +++ b/lib/vimeoplayer.dart @@ -7,7 +7,7 @@ import 'package:flutter/services.dart'; import 'src/quality_links.dart'; import 'dart:async'; -//Класс видео плеера +//Video player class class VimeoPlayer extends StatefulWidget { final String id; final bool autoPlay; @@ -48,18 +48,17 @@ class _VimeoPlayerState extends State { //Quality Class QualityLinks _quality; - Map _qualityValues; var _qualityValue; - //Переменная перемотки + //Variable rewind bool _seek = false; - //Переменные видео + //Video variables double videoHeight; double videoWidth; double videoMargin; - //Переменные под зоны дабл-тапа + //Variables for double-tap zones double doubleTapRMargin = 36; double doubleTapRWidth = 400; double doubleTapRHeight = 160; @@ -74,9 +73,8 @@ class _VimeoPlayerState extends State { //Create class _quality = QualityLinks(_id); - //Инициализация контроллеров видео при получении данных из Vimeo + //Initializing video controllers when receiving data from Vimeo _quality.getQualitiesSync().then((value) { - _qualityValues = value; _qualityValue = value[value.lastKey()]; _controller = VideoPlayerController.network(_qualityValue); _controller.setLooping(looping); @@ -107,20 +105,20 @@ class _VimeoPlayerState extends State { ); }); - //Обновление состояние приложения и перерисовка + //Update orientation and rebuilding page setState(() { SystemChrome.setPreferredOrientations([DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); }); }); - //На странице видео преимущество за портретной ориентацией + //The video page takes precedence over portrait orientation SystemChrome.setPreferredOrientations([DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values); super.initState(); } - //Отрисовываем элементы плеера + //Build player element @override Widget build(BuildContext context) { return Center( @@ -132,12 +130,12 @@ class _VimeoPlayerState extends State { future: initFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { - //Управление шириной и высотой видео + //Controlling width and height double delta = MediaQuery.of(context).size.width - MediaQuery.of(context).size.height * _controller.value.aspectRatio; - //Рассчет ширины и высоты видео плеера относительно сторон - // и ориентации устройства + //Calculating the width and height of the video player relative to the sides + // and orientation of the device if (MediaQuery.of(context).orientation == Orientation.portrait || delta < 0) { videoHeight = MediaQuery.of(context).size.width / _controller.value.aspectRatio; videoWidth = MediaQuery.of(context).size.width; @@ -148,7 +146,7 @@ class _VimeoPlayerState extends State { videoMargin = (MediaQuery.of(context).size.width - videoWidth) / 2; } - //Начинаем с того же места, где и остановились при смене качества + //We start from the same place where we left off when changing quality if (_seek && _controller.value.duration.inSeconds > 2) { _controller.seekTo(Duration(seconds: position)); _seek = false; @@ -168,8 +166,8 @@ class _VimeoPlayerState extends State { } }), onTap: () { - //Редактируем размер области дабл тапа при показе оверлея. - // Сделано для открытия кнопок "Во весь экран" и "Качество" + //Editing the size of the double tap area when showing the overlay. + // Made to open the "Full Screen" and "Quality" buttons setState(() { _overlay = !_overlay; if (_overlay) { @@ -187,7 +185,7 @@ class _VimeoPlayerState extends State { }, ), GestureDetector( - //======= Перемотка назад =======// + //======= Rewind =======// child: Container( width: doubleTapLWidth / 2 - 30, height: doubleTapLHeight - 46, @@ -197,8 +195,8 @@ class _VimeoPlayerState extends State { ), ), - // Изменение размера блоков дабл тапа. Нужно для открытия кнопок - // "Во весь экран" и "Качество" при включенном overlay + // Resize double tap blocks. Needed to open the + // "Full Screen" and "Quality" buttons when overlay is enabled onTap: () { setState(() { _overlay = !_overlay; @@ -222,7 +220,7 @@ class _VimeoPlayerState extends State { }), GestureDetector( child: Container( - //======= Перемотка вперед =======// + //======= Flash forward =======// width: doubleTapRWidth / 2 - 45, height: doubleTapRHeight - 60, margin: EdgeInsets.fromLTRB(doubleTapRWidth / 2 + 45, doubleTapRMargin, 0, doubleTapRMargin + 20), @@ -230,8 +228,8 @@ class _VimeoPlayerState extends State { //color: Colors.red, ), ), - // Изменение размера блоков дабл тапа. Нужно для открытия кнопок - // "Во весь экран" и "Качество" при включенном overlay + // Resize double tap blocks. Needed to open the + // "Full Screen" and "Quality" buttons when overlay is enabled onTap: () { setState(() { _overlay = !_overlay; From bb4d2522aabadcd9e5bfcf98e8a194e68daff2bd Mon Sep 17 00:00:00 2001 From: felixmo_trustMe Date: Mon, 8 Feb 2021 17:40:52 +0800 Subject: [PATCH 07/10] Added controller variable on vimeoplayer --- example/lib/main.dart | 5 ++++- example/lib/vimeoplayer.dart | 35 ++++++++++++++++++++++++++--------- lib/vimeoplayer.dart | 33 +++++++++++++++++++++++++-------- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 09ecb15..ac38a23 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:video_player/video_player.dart'; import 'vimeoplayer.dart'; void main() => runApp(MyApp()); @@ -18,6 +19,8 @@ class MyApp extends StatelessWidget { } class VideoScreen extends StatelessWidget { + VideoPlayerController _controller; + @override Widget build(BuildContext context) { return Scaffold( @@ -36,7 +39,7 @@ class VideoScreen extends StatelessWidget { preferredSize: Size(0.0, 0.0), ), body: ListView(children: [ - VimeoPlayer(id: '505942118', autoPlay: true, allowFullScreen: true), + VimeoPlayer(id: '505942118', controller: _controller, autoPlay: true, allowFullScreen: true), ])); } } diff --git a/example/lib/vimeoplayer.dart b/example/lib/vimeoplayer.dart index 6a7a874..d5cac37 100644 --- a/example/lib/vimeoplayer.dart +++ b/example/lib/vimeoplayer.dart @@ -10,23 +10,35 @@ import 'dart:async'; //Класс видео плеера class VimeoPlayer extends StatefulWidget { final String id; + final VideoPlayerController controller; final bool autoPlay; final bool looping; final int position; final bool allowFullScreen; + final bool allowPlaybackSpeedChanging; VimeoPlayer({ @required this.id, + @required this.controller, this.autoPlay, this.looping, this.position, @required this.allowFullScreen, + this.allowPlaybackSpeedChanging = false, Key key, }) : assert(id != null && allowFullScreen != null), super(key: key); @override - _VimeoPlayerState createState() => _VimeoPlayerState(id, autoPlay, looping, position, allowFullScreen); + _VimeoPlayerState createState() => _VimeoPlayerState( + id, + controller, + autoPlay, + looping, + position, + allowFullScreen, + allowPlaybackSpeedChanging, + ); } class _VimeoPlayerState extends State { @@ -36,9 +48,18 @@ class _VimeoPlayerState extends State { bool _overlay = true; bool fullScreen = false; bool allowFullScreen = false; + bool allowPlaybackSpeedChanging = false; int position; - _VimeoPlayerState(this._id, this.autoPlay, this.looping, this.position, this.allowFullScreen); + _VimeoPlayerState( + this._id, + this._videoPlayerController, + this.autoPlay, + this.looping, + this.position, + this.allowFullScreen, + this.allowPlaybackSpeedChanging, + ); //Custom controller VideoPlayerController _videoPlayerController; @@ -92,15 +113,11 @@ class _VimeoPlayerState extends State { aspectRatio: _videoPlayerController.value.aspectRatio, looping: looping, autoPlay: autoPlay, - // Errors can occur for example when trying to play a video + allowPlaybackSpeedChanging: allowPlaybackSpeedChanging, + // Errors can occur for example when trying to play a videos // from a non-existent URL errorBuilder: (context, errorMessage) { - return Center( - child: Text( - errorMessage, - style: TextStyle(color: Colors.white), - ), - ); + return Center(child: Text(errorMessage, style: TextStyle(color: Colors.white))); }, ); }); diff --git a/lib/vimeoplayer.dart b/lib/vimeoplayer.dart index d782c49..1eda233 100644 --- a/lib/vimeoplayer.dart +++ b/lib/vimeoplayer.dart @@ -10,23 +10,35 @@ import 'dart:async'; //Video player class class VimeoPlayer extends StatefulWidget { final String id; + final VideoPlayerController controller; final bool autoPlay; final bool looping; final int position; final bool allowFullScreen; + final bool allowPlaybackSpeedChanging; VimeoPlayer({ @required this.id, + @required this.controller, this.autoPlay, this.looping, this.position, @required this.allowFullScreen, + this.allowPlaybackSpeedChanging, Key key, }) : assert(id != null && allowFullScreen != null), super(key: key); @override - _VimeoPlayerState createState() => _VimeoPlayerState(id, autoPlay, looping, position, allowFullScreen); + _VimeoPlayerState createState() => _VimeoPlayerState( + id, + controller, + autoPlay, + looping, + position, + allowFullScreen, + allowPlaybackSpeedChanging, + ); } class _VimeoPlayerState extends State { @@ -36,9 +48,18 @@ class _VimeoPlayerState extends State { bool _overlay = true; bool fullScreen = false; bool allowFullScreen = false; + bool allowPlaybackSpeedChanging = false; int position; - _VimeoPlayerState(this._id, this.autoPlay, this.looping, this.position, this.allowFullScreen); + _VimeoPlayerState( + this._id, + this._controller, + this.autoPlay, + this.looping, + this.position, + this.allowFullScreen, + this.allowPlaybackSpeedChanging, + ); //Custom controller VideoPlayerController _controller; @@ -92,15 +113,11 @@ class _VimeoPlayerState extends State { aspectRatio: _controller.value.aspectRatio, looping: looping, autoPlay: autoPlay, + allowPlaybackSpeedChanging: allowPlaybackSpeedChanging, // Errors can occur for example when trying to play a video // from a non-existent URL errorBuilder: (context, errorMessage) { - return Center( - child: Text( - errorMessage, - style: TextStyle(color: Colors.white), - ), - ); + return Center(child: Text(errorMessage, style: TextStyle(color: Colors.white))); }, ); }); From 3a6ef0b0b5f8cd7bed48bc91442fbc0c54c23d2f Mon Sep 17 00:00:00 2001 From: felixmo_trustMe Date: Mon, 8 Feb 2021 17:41:29 +0800 Subject: [PATCH 08/10] Set default value of allowPlaybackSpeedChanging --- lib/vimeoplayer.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vimeoplayer.dart b/lib/vimeoplayer.dart index 1eda233..5ec1d71 100644 --- a/lib/vimeoplayer.dart +++ b/lib/vimeoplayer.dart @@ -24,7 +24,7 @@ class VimeoPlayer extends StatefulWidget { this.looping, this.position, @required this.allowFullScreen, - this.allowPlaybackSpeedChanging, + this.allowPlaybackSpeedChanging = false, Key key, }) : assert(id != null && allowFullScreen != null), super(key: key); From ea7abe1bce564c0e2ec9aacc180da32a8cef97f1 Mon Sep 17 00:00:00 2001 From: felixmo_trustMe Date: Mon, 22 Feb 2021 09:55:13 +0800 Subject: [PATCH 09/10] Removed VideoPlayerController parameter --- example/lib/main.dart | 5 +---- example/lib/vimeoplayer.dart | 4 ---- lib/vimeoplayer.dart | 4 ---- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index ac38a23..09ecb15 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:video_player/video_player.dart'; import 'vimeoplayer.dart'; void main() => runApp(MyApp()); @@ -19,8 +18,6 @@ class MyApp extends StatelessWidget { } class VideoScreen extends StatelessWidget { - VideoPlayerController _controller; - @override Widget build(BuildContext context) { return Scaffold( @@ -39,7 +36,7 @@ class VideoScreen extends StatelessWidget { preferredSize: Size(0.0, 0.0), ), body: ListView(children: [ - VimeoPlayer(id: '505942118', controller: _controller, autoPlay: true, allowFullScreen: true), + VimeoPlayer(id: '505942118', autoPlay: true, allowFullScreen: true), ])); } } diff --git a/example/lib/vimeoplayer.dart b/example/lib/vimeoplayer.dart index d5cac37..313dbcb 100644 --- a/example/lib/vimeoplayer.dart +++ b/example/lib/vimeoplayer.dart @@ -10,7 +10,6 @@ import 'dart:async'; //Класс видео плеера class VimeoPlayer extends StatefulWidget { final String id; - final VideoPlayerController controller; final bool autoPlay; final bool looping; final int position; @@ -19,7 +18,6 @@ class VimeoPlayer extends StatefulWidget { VimeoPlayer({ @required this.id, - @required this.controller, this.autoPlay, this.looping, this.position, @@ -32,7 +30,6 @@ class VimeoPlayer extends StatefulWidget { @override _VimeoPlayerState createState() => _VimeoPlayerState( id, - controller, autoPlay, looping, position, @@ -53,7 +50,6 @@ class _VimeoPlayerState extends State { _VimeoPlayerState( this._id, - this._videoPlayerController, this.autoPlay, this.looping, this.position, diff --git a/lib/vimeoplayer.dart b/lib/vimeoplayer.dart index 5ec1d71..e0f0998 100644 --- a/lib/vimeoplayer.dart +++ b/lib/vimeoplayer.dart @@ -10,7 +10,6 @@ import 'dart:async'; //Video player class class VimeoPlayer extends StatefulWidget { final String id; - final VideoPlayerController controller; final bool autoPlay; final bool looping; final int position; @@ -19,7 +18,6 @@ class VimeoPlayer extends StatefulWidget { VimeoPlayer({ @required this.id, - @required this.controller, this.autoPlay, this.looping, this.position, @@ -32,7 +30,6 @@ class VimeoPlayer extends StatefulWidget { @override _VimeoPlayerState createState() => _VimeoPlayerState( id, - controller, autoPlay, looping, position, @@ -53,7 +50,6 @@ class _VimeoPlayerState extends State { _VimeoPlayerState( this._id, - this._controller, this.autoPlay, this.looping, this.position, From a9123bc8fe088bee140891c590f8df30504b94ed Mon Sep 17 00:00:00 2001 From: felixmo_trustMe Date: Fri, 19 Mar 2021 11:18:41 +0800 Subject: [PATCH 10/10] Prevent exception if it fails when initialising the vimeo video player --- example/lib/vimeoplayer.dart | 12 ++++++++---- lib/vimeoplayer.dart | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/example/lib/vimeoplayer.dart b/example/lib/vimeoplayer.dart index 313dbcb..44ae212 100644 --- a/example/lib/vimeoplayer.dart +++ b/example/lib/vimeoplayer.dart @@ -165,10 +165,14 @@ class _VimeoPlayerState extends State { _seek = false; } - return Container( - margin: EdgeInsets.only(left: videoMargin), - child: Chewie(controller: _chewieController), - ); + //Prevent exception if it failes when initialising the vimeo video player + if (_chewieController != null) { + return Container( + margin: EdgeInsets.only(left: videoMargin), + child: Chewie(controller: _chewieController), + ); + } + return Container(); } else { return Center( heightFactor: 6, diff --git a/lib/vimeoplayer.dart b/lib/vimeoplayer.dart index e0f0998..0b664e4 100644 --- a/lib/vimeoplayer.dart +++ b/lib/vimeoplayer.dart @@ -165,10 +165,14 @@ class _VimeoPlayerState extends State { _seek = false; } - return Container( - margin: EdgeInsets.only(left: videoMargin), - child: Chewie(controller: _chewieController), - ); + //Prevent exception if it failes when initialising the vimeo video player + if(_chewieController != null) { + return Container( + margin: EdgeInsets.only(left: videoMargin), + child: Chewie(controller: _chewieController), + ); + } + return Container(); } else { return Center( heightFactor: 6,