From cea616b224487b2bba4f81d3ae92ea8b1633a89d Mon Sep 17 00:00:00 2001 From: Rafael Alves Feliciano Date: Mon, 3 Apr 2023 17:11:05 -0300 Subject: [PATCH 01/24] Update package to support unlisted vimeo videos --- README.md | 47 ++++++++++++++++++- example/lib/screens/from_vimeo_id.dart | 19 +++++++- .../pod_getx_video_controller.dart | 5 +- .../controllers/pod_player_controller.dart | 7 ++- .../pod_video_quality_controller.dart | 10 +++- lib/src/models/play_video_from.dart | 4 ++ lib/src/utils/video_apis.dart | 18 +++++-- 7 files changed, 99 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b30edfe0..a1517bbd 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,8 @@ This plugin built upon flutter's official [`video_player`](https://pub.dartlang. ## Features - Play `youtube` videos (using video URL or ID) -- Play `vimeo` videos (using video ID) -- Play `vimeo` private videos (using video ID, access token) +- Play `vimeo` videos (using video ID [with ou without hash]) +- Play `vimeo` private videos (using video ID [with ou without hash], access token) - Video overlay similar to youtube - `Double tap` to seek video. - On video tap show/hide video overlay. @@ -380,6 +380,49 @@ class _PlayVideoFromVimeoState extends State { } ``` + +## How to play video from vimeo with hash + +--- + +```dart +import 'package:pod_player/pod_player.dart'; +import 'package:flutter/material.dart'; + +class PlayVideoFromVimeo extends StatefulWidget { + const PlayVideoFromVimeo({Key? key}) : super(key: key); + + @override + State createState() => _PlayVideoFromVimeoState(); +} + +class _PlayVideoFromVimeoState extends State { + late final PodPlayerController controller; + + @override + void initState() { + controller = PodPlayerController( + playVideoFrom: PlayVideoFrom.vimeo('518228118', hash: '7cc595e1f8'), + )..initialise(); + super.initState(); + } + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: PodVideoPlayer(controller: controller), + ); + } +} + +``` + ## How to play video from vimeo private videos --- diff --git a/example/lib/screens/from_vimeo_id.dart b/example/lib/screens/from_vimeo_id.dart index d803eb95..93a67efb 100644 --- a/example/lib/screens/from_vimeo_id.dart +++ b/example/lib/screens/from_vimeo_id.dart @@ -11,6 +11,7 @@ class PlayVideoFromVimeoId extends StatefulWidget { class _PlayVideoFromVimeoIdState extends State { late final PodPlayerController controller; final videoTextFieldCtr = TextEditingController(); + final hashTextFieldCtr = TextEditingController(); @override void initState() { @@ -60,6 +61,18 @@ class _PlayVideoFromVimeoIdState extends State { ), ), ), + Expanded( + flex: 2, + child: TextField( + controller: hashTextFieldCtr, + decoration: const InputDecoration( + labelText: 'Enter vimeo hash', + floatingLabelBehavior: FloatingLabelBehavior.always, + hintText: 'ex: ddefbc', + border: OutlineInputBorder(), + ), + ), + ), const SizedBox(width: 10), FocusScope( canRequestFocus: false, @@ -72,8 +85,12 @@ class _PlayVideoFromVimeoIdState extends State { try { snackBar('Loading....'); FocusScope.of(context).unfocus(); + final vimeoHash = hashTextFieldCtr.text; await controller.changeVideo( - playVideoFrom: PlayVideoFrom.vimeo(videoTextFieldCtr.text), + playVideoFrom: PlayVideoFrom.vimeo( + videoTextFieldCtr.text, + hash: vimeoHash.isNotEmpty ? vimeoHash : null, + ), ); if (!mounted) return; ScaffoldMessenger.of(context).hideCurrentSnackBar(); diff --git a/lib/src/controllers/pod_getx_video_controller.dart b/lib/src/controllers/pod_getx_video_controller.dart index 1197369b..33c5d3fc 100644 --- a/lib/src/controllers/pod_getx_video_controller.dart +++ b/lib/src/controllers/pod_getx_video_controller.dart @@ -133,7 +133,10 @@ class PodGetXVideoController extends _PodGesturesController { break; case PodVideoPlayerType.vimeo: - await getQualityUrlsFromVimeoId(playVideoFrom.dataSource!); + await getQualityUrlsFromVimeoId( + playVideoFrom.dataSource!, + hash: playVideoFrom.hash, + ); final _url = await getUrlFromVideoQualityUrls( qualityList: podPlayerConfig.videoQualityPriority, videoUrls: vimeoOrVideoUrls, diff --git a/lib/src/controllers/pod_player_controller.dart b/lib/src/controllers/pod_player_controller.dart index 9734e9cc..a9c17b3c 100644 --- a/lib/src/controllers/pod_player_controller.dart +++ b/lib/src/controllers/pod_player_controller.dart @@ -256,8 +256,11 @@ class PodPlayerController { return VideoApis.getYoutubeVideoQualityUrls(youtubeIdOrUrl, live); } - static Future?> getVimeoUrls(String videoId) { - return VideoApis.getVimeoVideoQualityUrls(videoId); + static Future?> getVimeoUrls( + String videoId, { + String? hash, + }) { + return VideoApis.getVimeoVideoQualityUrls(videoId, hash); } /// Hide overlay of video diff --git a/lib/src/controllers/pod_video_quality_controller.dart b/lib/src/controllers/pod_video_quality_controller.dart index 9f4b8dee..b9ca7086 100644 --- a/lib/src/controllers/pod_video_quality_controller.dart +++ b/lib/src/controllers/pod_video_quality_controller.dart @@ -14,10 +14,16 @@ class _PodVideoQualityController extends _PodVideoController { ///*vimeo player configs /// ///get all `quality urls` - Future getQualityUrlsFromVimeoId(String videoId) async { + Future getQualityUrlsFromVimeoId( + String videoId, { + String? hash, + }) async { try { podVideoStateChanger(PodVideoState.loading); - final _vimeoVideoUrls = await VideoApis.getVimeoVideoQualityUrls(videoId); + final _vimeoVideoUrls = await VideoApis.getVimeoVideoQualityUrls( + videoId, + hash, + ); /// vimeoOrVideoUrls = _vimeoVideoUrls ?? []; diff --git a/lib/src/models/play_video_from.dart b/lib/src/models/play_video_from.dart index 87849a61..272efcdc 100644 --- a/lib/src/models/play_video_from.dart +++ b/lib/src/models/play_video_from.dart @@ -2,6 +2,7 @@ import '../../pod_player.dart'; class PlayVideoFrom { final String? dataSource; + final String? hash; final PodVideoPlayerType playerType; final VideoFormat? formatHint; final String? package; @@ -15,6 +16,7 @@ class PlayVideoFrom { const PlayVideoFrom._({ this.live = false, this.dataSource, + this.hash, required this.playerType, this.formatHint, this.package, @@ -74,6 +76,7 @@ class PlayVideoFrom { factory PlayVideoFrom.vimeo( String dataSource, { + String? hash, VideoFormat? formatHint, Future? closedCaptionFile, VideoPlayerOptions? videoPlayerOptions, @@ -82,6 +85,7 @@ class PlayVideoFrom { return PlayVideoFrom._( playerType: PodVideoPlayerType.vimeo, dataSource: dataSource, + hash: hash, formatHint: formatHint, closedCaptionFile: closedCaptionFile, videoPlayerOptions: videoPlayerOptions, diff --git a/lib/src/utils/video_apis.dart b/lib/src/utils/video_apis.dart index e319469e..cf01a627 100644 --- a/lib/src/utils/video_apis.dart +++ b/lib/src/utils/video_apis.dart @@ -3,6 +3,7 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; +import 'package:http/http.dart'; import 'package:youtube_explode_dart/youtube_explode_dart.dart'; import '../models/vimeo_models.dart'; @@ -11,13 +12,24 @@ String podErrorString(String val) { } class VideoApis { + static Future _makeRequestHash(String videoId, String? hash) { + if (hash == null) { + return http.get( + Uri.parse('https://player.vimeo.com/video/$videoId/config'), + ); + } else { + return http.get( + Uri.parse('https://player.vimeo.com/video/$videoId/config?h=$hash'), + ); + } + } + static Future?> getVimeoVideoQualityUrls( String videoId, + String? hash, ) async { try { - final response = await http.get( - Uri.parse('https://player.vimeo.com/video/$videoId/config'), - ); + final response = await _makeRequestHash(videoId, hash); final jsonData = jsonDecode(response.body)['request']['files']['progressive']; return List.generate( From efdb24bfefdb29fa305197c5aeebb751d4fc1570 Mon Sep 17 00:00:00 2001 From: newtaDev Date: Sun, 7 May 2023 17:33:29 +0530 Subject: [PATCH 02/24] chore: upgraded dependencies --- example/ios/Flutter/AppFrameworkInfo.plist | 2 +- example/ios/Podfile | 2 +- example/ios/Podfile.lock | 6 +++--- example/ios/Runner.xcodeproj/project.pbxproj | 13 +++++++------ example/ios/Runner/Info.plist | 6 ++++-- pubspec.yaml | 10 +++++----- 6 files changed, 21 insertions(+), 18 deletions(-) diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 8d4492f9..9625e105 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 11.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index 1e8c3c90..88359b22 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '9.0' +# platform :ios, '11.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 5292f26f..7cadee30 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -19,10 +19,10 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/wakelock/ios" SPEC CHECKSUMS: - Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a - video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + video_player_avfoundation: 81e49bb3d9fb63dccf9fa0f6d877dc3ddbeac126 wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f -PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c +PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 COCOAPODS: 1.11.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index c94fba36..ee49c1b2 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -68,7 +68,6 @@ 6E25F060E308BC4D125ED336 /* Pods-Runner.release.xcconfig */, 0B108E1AF19EC89726150E55 /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -200,6 +199,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -214,6 +214,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -340,7 +341,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -418,7 +419,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -467,7 +468,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -492,7 +493,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_BUNDLE_IDENTIFIER = com.podplayer.podexample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index 967bc738..736f2968 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -2,6 +2,8 @@ + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName @@ -29,6 +31,8 @@ NSAllowsArbitraryLoads + UIApplicationSupportsIndirectInputEvents + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile @@ -48,7 +52,5 @@ UIViewControllerBasedStatusBarAppearance - CADisableMinimumFrameDurationOnPhone - diff --git a/pubspec.yaml b/pubspec.yaml index 42fdd23e..1e75757d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,12 +13,12 @@ dependencies: # ui lottie: ^1.3.0 # services - video_player: ^2.4.5 - http: ^0.13.4 + video_player: ^2.6.1 + http: ^0.13.6 get: ^4.6.5 - wakelock: ^0.6.1+2 - universal_html: ^2.0.8 - youtube_explode_dart: ^1.11.0 + wakelock: ^0.6.2 + universal_html: ^2.2.1 + youtube_explode_dart: ^1.12.4 dev_dependencies: flutter_test: sdk: flutter From f095026b608c6b51b158747121de49a0729ec643 Mon Sep 17 00:00:00 2001 From: newtaDev Date: Sun, 7 May 2023 17:39:19 +0530 Subject: [PATCH 03/24] fix: auto play/pause listner issue --- lib/src/controllers/pod_base_controller.dart | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/src/controllers/pod_base_controller.dart b/lib/src/controllers/pod_base_controller.dart index a0ef656f..5917c3fc 100644 --- a/lib/src/controllers/pod_base_controller.dart +++ b/lib/src/controllers/pod_base_controller.dart @@ -44,7 +44,7 @@ class _PodBaseController extends GetxController { await _videoCtr!.initialize(); } if (_videoCtr!.value.isInitialized) { - _listneToVideoState(); + // _listneToVideoState(); _listneToVideoPosition(); _listneToVolume(); if (kIsWeb && autoPlay && isMute && !_isWebAutoPlayDone) _webAutoPlay(); @@ -69,15 +69,15 @@ class _PodBaseController extends GetxController { } } - void _listneToVideoState() { - podVideoStateChanger( - _videoCtr!.value.isBuffering || !_videoCtr!.value.isInitialized - ? PodVideoState.loading - : _videoCtr!.value.isPlaying - ? PodVideoState.playing - : PodVideoState.paused, - ); - } + // void _listneToVideoState() { + // podVideoStateChanger( + // _videoCtr!.value.isBuffering || !_videoCtr!.value.isInitialized + // ? PodVideoState.loading + // : _videoCtr!.value.isPlaying + // ? PodVideoState.playing + // : PodVideoState.paused, + // ); + // } ///updates state with id `_podVideoState` void podVideoStateChanger(PodVideoState? _val, {bool updateUi = true}) { From 3231e3abcafb3433bcf736435047324b27cafa3e Mon Sep 17 00:00:00 2001 From: newtaDev Date: Sun, 7 May 2023 19:46:37 +0530 Subject: [PATCH 04/24] refactor: lottie icon to custom doubleTap icon --- assets/forward_left.json | 347 ------------------ assets/forward_right.json | 347 ------------------ .../controllers/pod_gestures_controller.dart | 12 +- lib/src/pod_player.dart | 2 +- .../widgets/core/overlays/mobile_overlay.dart | 113 ++---- .../widgets/core/overlays/web_overlay.dart | 44 ++- lib/src/widgets/doubble_tap_effect.dart | 238 ++++++++++++ lib/src/widgets/double_tap_icon.dart | 186 ++++++++++ pubspec.yaml | 2 - 9 files changed, 485 insertions(+), 806 deletions(-) delete mode 100644 assets/forward_left.json delete mode 100644 assets/forward_right.json create mode 100644 lib/src/widgets/doubble_tap_effect.dart create mode 100644 lib/src/widgets/double_tap_icon.dart diff --git a/assets/forward_left.json b/assets/forward_left.json deleted file mode 100644 index 13c8a66e..00000000 --- a/assets/forward_left.json +++ /dev/null @@ -1,347 +0,0 @@ -{ - "v": "5.5.7", - "fr": 30, - "ip": 0, - "op": 31, - "w": 360, - "h": 360, - "nm": "Comp 20", - "ddd": 0, - "assets": [], - "layers": [ - { - "ddd": 0, - "ind": 1, - "ty": 4, - "nm": "Layer 3", - "sr": 1, - "ks": { - "o": { - "a": 1, - "k": [ - { - "i": { "x": [0.667], "y": [1] }, - "o": { "x": [0.333], "y": [0] }, - "t": 10, - "s": [0] - }, - { - "i": { "x": [0.667], "y": [1] }, - "o": { "x": [0.333], "y": [0] }, - "t": 20, - "s": [100] - }, - { "t": 30, "s": [0] } - ], - "ix": 11 - }, - "r": { "a": 0, "k": 0, "ix": 10 }, - "p": { "a": 0, "k": [161.086, 180, 0], "ix": 2 }, - "a": { "a": 0, "k": [-18.914, 0, 0], "ix": 1 }, - "s": { "a": 0, "k": [100, 100, 100], "ix": 6 } - }, - "ao": 0, - "shapes": [ - { - "ty": "gr", - "it": [ - { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ - [0, -0.923], - [0, 0], - [0.777, 0.499], - [0, 0], - [-0.714, 0.459], - [0, 0] - ], - "o": [ - [0, 0], - [0, 0.923], - [0, 0], - [-0.714, -0.459], - [0, 0], - [0.777, -0.499] - ], - "v": [ - [-11.243, -8.363], - [-11.243, 8.363], - [-13.041, 9.344], - [-26.05, 0.981], - [-26.05, -0.981], - [-13.041, -9.344] - ], - "c": true - }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "fl", - "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, - "o": { "a": 0, "k": 100, "ix": 5 }, - "r": 1, - "bm": 0, - "nm": "Fill 1", - "mn": "ADBE Vector Graphic - Fill", - "hd": false - }, - { - "ty": "tr", - "p": { "a": 0, "k": [0, 0], "ix": 2 }, - "a": { "a": 0, "k": [0, 0], "ix": 1 }, - "s": { "a": 0, "k": [100, 100], "ix": 3 }, - "r": { "a": 0, "k": 0, "ix": 6 }, - "o": { "a": 0, "k": 100, "ix": 7 }, - "sk": { "a": 0, "k": 0, "ix": 4 }, - "sa": { "a": 0, "k": 0, "ix": 5 }, - "nm": "Transform" - } - ], - "nm": "Group 1", - "np": 2, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false - } - ], - "ip": 0, - "op": 300, - "st": 0, - "bm": 0 - }, - { - "ddd": 0, - "ind": 2, - "ty": 4, - "nm": "Layer 1", - "sr": 1, - "ks": { - "o": { - "a": 1, - "k": [ - { - "i": { "x": [0.667], "y": [1] }, - "o": { "x": [0.333], "y": [0] }, - "t": 5, - "s": [0] - }, - { - "i": { "x": [0.667], "y": [1] }, - "o": { "x": [0.333], "y": [0] }, - "t": 15, - "s": [100] - }, - { "t": 25, "s": [0] } - ], - "ix": 11 - }, - "r": { "a": 0, "k": 0, "ix": 10 }, - "p": { "a": 0, "k": [180.086, 180, 0], "ix": 2 }, - "a": { "a": 0, "k": [0.086, 0, 0], "ix": 1 }, - "s": { "a": 0, "k": [100, 100, 100], "ix": 6 } - }, - "ao": 0, - "shapes": [ - { - "ty": "gr", - "it": [ - { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ - [0, -0.923], - [0, 0], - [0.777, 0.499], - [0, 0], - [-0.714, 0.459], - [0, 0] - ], - "o": [ - [0, 0], - [0, 0.923], - [0, 0], - [-0.714, -0.459], - [0, 0], - [0.777, -0.499] - ], - "v": [ - [7.757, -8.363], - [7.757, 8.363], - [5.959, 9.344], - [-7.05, 0.981], - [-7.05, -0.981], - [5.959, -9.344] - ], - "c": true - }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "fl", - "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, - "o": { "a": 0, "k": 100, "ix": 5 }, - "r": 1, - "bm": 0, - "nm": "Fill 1", - "mn": "ADBE Vector Graphic - Fill", - "hd": false - }, - { - "ty": "tr", - "p": { "a": 0, "k": [0, 0], "ix": 2 }, - "a": { "a": 0, "k": [0, 0], "ix": 1 }, - "s": { "a": 0, "k": [100, 100], "ix": 3 }, - "r": { "a": 0, "k": 0, "ix": 6 }, - "o": { "a": 0, "k": 100, "ix": 7 }, - "sk": { "a": 0, "k": 0, "ix": 4 }, - "sa": { "a": 0, "k": 0, "ix": 5 }, - "nm": "Transform" - } - ], - "nm": "Group 1", - "np": 2, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false - } - ], - "ip": 0, - "op": 300, - "st": 0, - "bm": 0 - }, - { - "ddd": 0, - "ind": 3, - "ty": 4, - "nm": "Layer 2", - "sr": 1, - "ks": { - "o": { - "a": 1, - "k": [ - { - "i": { "x": [0.667], "y": [1] }, - "o": { "x": [0.333], "y": [0] }, - "t": 0, - "s": [0] - }, - { - "i": { "x": [0.667], "y": [1] }, - "o": { "x": [0.333], "y": [0] }, - "t": 10, - "s": [100] - }, - { "t": 20, "s": [0] } - ], - "ix": 11 - }, - "r": { "a": 0, "k": 0, "ix": 10 }, - "p": { "a": 0, "k": [198.914, 180, 0], "ix": 2 }, - "a": { "a": 0, "k": [18.914, 0, 0], "ix": 1 }, - "s": { "a": 0, "k": [100, 100, 100], "ix": 6 } - }, - "ao": 0, - "shapes": [ - { - "ty": "gr", - "it": [ - { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ - [0, -0.923], - [0, 0], - [0.777, 0.499], - [0, 0], - [-0.714, 0.459], - [0, 0] - ], - "o": [ - [0, 0], - [0, 0.923], - [0, 0], - [-0.714, -0.459], - [0, 0], - [0.777, -0.499] - ], - "v": [ - [26.586, -8.363], - [26.586, 8.363], - [24.788, 9.344], - [11.779, 0.981], - [11.779, -0.981], - [24.788, -9.344] - ], - "c": true - }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "fl", - "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, - "o": { "a": 0, "k": 100, "ix": 5 }, - "r": 1, - "bm": 0, - "nm": "Fill 1", - "mn": "ADBE Vector Graphic - Fill", - "hd": false - }, - { - "ty": "tr", - "p": { "a": 0, "k": [0, 0], "ix": 2 }, - "a": { "a": 0, "k": [0, 0], "ix": 1 }, - "s": { "a": 0, "k": [100, 100], "ix": 3 }, - "r": { "a": 0, "k": 0, "ix": 6 }, - "o": { "a": 0, "k": 100, "ix": 7 }, - "sk": { "a": 0, "k": 0, "ix": 4 }, - "sa": { "a": 0, "k": 0, "ix": 5 }, - "nm": "Transform" - } - ], - "nm": "Group 1", - "np": 2, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false - } - ], - "ip": 0, - "op": 300, - "st": 0, - "bm": 0 - } - ], - "markers": [] -} diff --git a/assets/forward_right.json b/assets/forward_right.json deleted file mode 100644 index 90928280..00000000 --- a/assets/forward_right.json +++ /dev/null @@ -1,347 +0,0 @@ -{ - "v": "5.5.7", - "fr": 30, - "ip": 0, - "op": 31, - "w": 360, - "h": 360, - "nm": "forward right", - "ddd": 0, - "assets": [], - "layers": [ - { - "ddd": 0, - "ind": 1, - "ty": 4, - "nm": "Layer 2", - "sr": 1, - "ks": { - "o": { - "a": 1, - "k": [ - { - "i": { "x": [0.667], "y": [1] }, - "o": { "x": [0.333], "y": [0] }, - "t": 0, - "s": [0] - }, - { - "i": { "x": [0.667], "y": [1] }, - "o": { "x": [0.333], "y": [0] }, - "t": 10, - "s": [100] - }, - { "t": 20, "s": [0] } - ], - "ix": 11 - }, - "r": { "a": 0, "k": 0, "ix": 10 }, - "p": { "a": 0, "k": [161.086, 180, 0], "ix": 2 }, - "a": { "a": 0, "k": [-18.914, 0, 0], "ix": 1 }, - "s": { "a": 0, "k": [100, 100, 100], "ix": 6 } - }, - "ao": 0, - "shapes": [ - { - "ty": "gr", - "it": [ - { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ - [0, 0.923], - [0, 0], - [-0.777, -0.499], - [0, 0], - [0.714, -0.459], - [0, 0] - ], - "o": [ - [0, 0], - [0, -0.923], - [0, 0], - [0.714, 0.459], - [0, 0], - [-0.777, 0.499] - ], - "v": [ - [-26.586, 8.363], - [-26.586, -8.363], - [-24.788, -9.344], - [-11.779, -0.981], - [-11.779, 0.981], - [-24.788, 9.344] - ], - "c": true - }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "fl", - "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, - "o": { "a": 0, "k": 100, "ix": 5 }, - "r": 1, - "bm": 0, - "nm": "Fill 1", - "mn": "ADBE Vector Graphic - Fill", - "hd": false - }, - { - "ty": "tr", - "p": { "a": 0, "k": [0, 0], "ix": 2 }, - "a": { "a": 0, "k": [0, 0], "ix": 1 }, - "s": { "a": 0, "k": [100, 100], "ix": 3 }, - "r": { "a": 0, "k": 0, "ix": 6 }, - "o": { "a": 0, "k": 100, "ix": 7 }, - "sk": { "a": 0, "k": 0, "ix": 4 }, - "sa": { "a": 0, "k": 0, "ix": 5 }, - "nm": "Transform" - } - ], - "nm": "Group 1", - "np": 2, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false - } - ], - "ip": 0, - "op": 300, - "st": 0, - "bm": 0 - }, - { - "ddd": 0, - "ind": 2, - "ty": 4, - "nm": "Layer 1", - "sr": 1, - "ks": { - "o": { - "a": 1, - "k": [ - { - "i": { "x": [0.667], "y": [1] }, - "o": { "x": [0.333], "y": [0] }, - "t": 5, - "s": [0] - }, - { - "i": { "x": [0.667], "y": [1] }, - "o": { "x": [0.333], "y": [0] }, - "t": 15, - "s": [100] - }, - { "t": 25, "s": [0] } - ], - "ix": 11 - }, - "r": { "a": 0, "k": 0, "ix": 10 }, - "p": { "a": 0, "k": [179.914, 180, 0], "ix": 2 }, - "a": { "a": 0, "k": [-0.086, 0, 0], "ix": 1 }, - "s": { "a": 0, "k": [100, 100, 100], "ix": 6 } - }, - "ao": 0, - "shapes": [ - { - "ty": "gr", - "it": [ - { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ - [0, 0.923], - [0, 0], - [-0.777, -0.499], - [0, 0], - [0.714, -0.459], - [0, 0] - ], - "o": [ - [0, 0], - [0, -0.923], - [0, 0], - [0.714, 0.459], - [0, 0], - [-0.777, 0.499] - ], - "v": [ - [-7.757, 8.363], - [-7.757, -8.363], - [-5.959, -9.344], - [7.05, -0.981], - [7.05, 0.981], - [-5.959, 9.344] - ], - "c": true - }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "fl", - "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, - "o": { "a": 0, "k": 100, "ix": 5 }, - "r": 1, - "bm": 0, - "nm": "Fill 1", - "mn": "ADBE Vector Graphic - Fill", - "hd": false - }, - { - "ty": "tr", - "p": { "a": 0, "k": [0, 0], "ix": 2 }, - "a": { "a": 0, "k": [0, 0], "ix": 1 }, - "s": { "a": 0, "k": [100, 100], "ix": 3 }, - "r": { "a": 0, "k": 0, "ix": 6 }, - "o": { "a": 0, "k": 100, "ix": 7 }, - "sk": { "a": 0, "k": 0, "ix": 4 }, - "sa": { "a": 0, "k": 0, "ix": 5 }, - "nm": "Transform" - } - ], - "nm": "Group 1", - "np": 2, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false - } - ], - "ip": 0, - "op": 300, - "st": 0, - "bm": 0 - }, - { - "ddd": 0, - "ind": 3, - "ty": 4, - "nm": "Layer 3", - "sr": 1, - "ks": { - "o": { - "a": 1, - "k": [ - { - "i": { "x": [0.667], "y": [1] }, - "o": { "x": [0.333], "y": [0] }, - "t": 10, - "s": [0] - }, - { - "i": { "x": [0.667], "y": [1] }, - "o": { "x": [0.333], "y": [0] }, - "t": 20, - "s": [100] - }, - { "t": 30, "s": [0] } - ], - "ix": 11 - }, - "r": { "a": 0, "k": 0, "ix": 10 }, - "p": { "a": 0, "k": [198.914, 180, 0], "ix": 2 }, - "a": { "a": 0, "k": [18.914, 0, 0], "ix": 1 }, - "s": { "a": 0, "k": [100, 100, 100], "ix": 6 } - }, - "ao": 0, - "shapes": [ - { - "ty": "gr", - "it": [ - { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ - [0, 0.923], - [0, 0], - [-0.777, -0.499], - [0, 0], - [0.714, -0.459], - [0, 0] - ], - "o": [ - [0, 0], - [0, -0.923], - [0, 0], - [0.714, 0.459], - [0, 0], - [-0.777, 0.499] - ], - "v": [ - [11.243, 8.363], - [11.243, -8.363], - [13.041, -9.344], - [26.05, -0.981], - [26.05, 0.981], - [13.041, 9.344] - ], - "c": true - }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "fl", - "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, - "o": { "a": 0, "k": 100, "ix": 5 }, - "r": 1, - "bm": 0, - "nm": "Fill 1", - "mn": "ADBE Vector Graphic - Fill", - "hd": false - }, - { - "ty": "tr", - "p": { "a": 0, "k": [0, 0], "ix": 2 }, - "a": { "a": 0, "k": [0, 0], "ix": 1 }, - "s": { "a": 0, "k": [100, 100], "ix": 3 }, - "r": { "a": 0, "k": 0, "ix": 6 }, - "o": { "a": 0, "k": 100, "ix": 7 }, - "sk": { "a": 0, "k": 0, "ix": 4 }, - "sa": { "a": 0, "k": 0, "ix": 5 }, - "nm": "Transform" - } - ], - "nm": "Group 1", - "np": 2, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false - } - ], - "ip": 0, - "op": 300, - "st": 0, - "bm": 0 - } - ], - "markers": [] -} diff --git a/lib/src/controllers/pod_gestures_controller.dart b/lib/src/controllers/pod_gestures_controller.dart index 7dfa1269..5438034a 100644 --- a/lib/src/controllers/pod_gestures_controller.dart +++ b/lib/src/controllers/pod_gestures_controller.dart @@ -24,10 +24,14 @@ class _PodGesturesController extends _PodVideoQualityController { leftDoubleTapduration += seconds ?? doubleTapForwardSeconds, ); seekBackward(Duration(seconds: seconds ?? doubleTapForwardSeconds)); - leftDoubleTapTimer = Timer(const Duration(milliseconds: 1500), () { + update(['double-tap-left']); + leftDoubleTapTimer = Timer(const Duration(milliseconds: 500), () { isLeftDbTapIconVisible = false; updateLeftTapDuration(0); leftDoubleTapTimer?.cancel(); + if (isvideoPlaying) { + playVideo(true); + } isShowOverlay(false); }); } @@ -43,10 +47,14 @@ class _PodGesturesController extends _PodVideoQualityController { rightDubleTapduration += seconds ?? doubleTapForwardSeconds, ); seekForward(Duration(seconds: seconds ?? doubleTapForwardSeconds)); - rightDoubleTapTimer = Timer(const Duration(milliseconds: 1500), () { + update(['double-tap-right']); + rightDoubleTapTimer = Timer(const Duration(milliseconds: 500), () { isRightDbTapIconVisible = false; updateRightTapDuration(0); rightDoubleTapTimer?.cancel(); + if (isvideoPlaying) { + playVideo(true); + } isShowOverlay(false); }); } diff --git a/lib/src/pod_player.dart b/lib/src/pod_player.dart index 1148d485..f799523d 100644 --- a/lib/src/pod_player.dart +++ b/lib/src/pod_player.dart @@ -5,12 +5,12 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import 'package:lottie/lottie.dart'; import 'package:universal_html/html.dart' as _html; import '../pod_player.dart'; import 'controllers/pod_getx_video_controller.dart'; import 'utils/logger.dart'; +import 'widgets/double_tap_icon.dart'; import 'widgets/material_icon_button.dart'; part 'widgets/animated_play_pause_icon.dart'; diff --git a/lib/src/widgets/core/overlays/mobile_overlay.dart b/lib/src/widgets/core/overlays/mobile_overlay.dart index d38bb3d5..e5bc3749 100644 --- a/lib/src/widgets/core/overlays/mobile_overlay.dart +++ b/lib/src/widgets/core/overlays/mobile_overlay.dart @@ -16,51 +16,41 @@ class _MobileOverlay extends StatelessWidget { return Stack( alignment: Alignment.center, children: [ - Row( - children: [ - Expanded( - child: _VideoGestureDetector( - tag: tag, - onDoubleTap: _isRtl() - ? _podCtr.onRightDoubleTap - : _podCtr.onLeftDoubleTap, - child: ColoredBox( - color: overlayColor, - child: _LeftRightDoubleTapBox( + _VideoGestureDetector( + tag: tag, + child: ColoredBox( + color: overlayColor, + child: Row( + children: [ + Expanded( + child: DoubleTapIcon( tag: tag, - isLeft: !_isRtl(), + isForward: false, + height: double.maxFinite, + onDoubleTap: _isRtl() + ? _podCtr.onRightDoubleTap + : _podCtr.onLeftDoubleTap, ), ), - ), - ), - _VideoGestureDetector( - tag: tag, - child: ColoredBox( - color: overlayColor, - child: SizedBox( + SizedBox( height: double.infinity, child: Center( child: _AnimatedPlayPauseIcon(tag: tag, size: 42), ), ), - ), - ), - Expanded( - child: _VideoGestureDetector( - tag: tag, - onDoubleTap: _isRtl() - ? _podCtr.onLeftDoubleTap - : _podCtr.onRightDoubleTap, - child: ColoredBox( - color: overlayColor, - child: _LeftRightDoubleTapBox( + Expanded( + child: DoubleTapIcon( + isForward: true, tag: tag, - isLeft: _isRtl(), + height: double.maxFinite, + onDoubleTap: _isRtl() + ? _podCtr.onLeftDoubleTap + : _podCtr.onRightDoubleTap, ), ), - ), + ], ), - ], + ), ), Align( alignment: Alignment.topCenter, @@ -122,60 +112,3 @@ class _MobileOverlay extends StatelessWidget { ); } } - -class _LeftRightDoubleTapBox extends StatelessWidget { - final String tag; - final bool isLeft; - const _LeftRightDoubleTapBox({ - Key? key, - required this.tag, - required this.isLeft, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return GetBuilder( - tag: tag, - id: 'double-tap', - builder: (_podCtr) { - return SizedBox( - width: double.infinity, - height: double.infinity, - child: AnimatedOpacity( - duration: const Duration(milliseconds: 200), - opacity: _podCtr.isLeftDbTapIconVisible && isLeft - ? 1 - : _podCtr.isRightDbTapIconVisible && !isLeft - ? 1 - : 0, - child: Center( - child: Stack( - alignment: Alignment.center, - children: [ - Lottie.asset( - isLeft - ? 'packages/pod_player/assets/forward_left.json' - : 'packages/pod_player/assets/forward_right.json', - ), - if (isLeft - ? _podCtr.isLeftDbTapIconVisible - : _podCtr.isRightDbTapIconVisible) - Transform.translate( - offset: const Offset(0, 40), - child: Text( - '${_podCtr.isLeftDbTapIconVisible ? _podCtr.leftDoubleTapduration : _podCtr.rightDubleTapduration} Sec', - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - ), - ), - ) - ], - ), - ), - ), - ); - }, - ); - } -} diff --git a/lib/src/widgets/core/overlays/web_overlay.dart b/lib/src/widgets/core/overlays/web_overlay.dart index cce58a60..508aab34 100644 --- a/lib/src/widgets/core/overlays/web_overlay.dart +++ b/lib/src/widgets/core/overlays/web_overlay.dart @@ -31,25 +31,35 @@ class _WebOverlay extends StatelessWidget { ), ), Positioned.fill( - child: Row( - children: [ - Expanded( - child: IgnorePointer( - child: _LeftRightDoubleTapBox( - tag: tag, - isLeft: true, + child: GetBuilder( + tag: tag, + id: 'double-tap', + builder: (_podCtr) { + return Row( + children: [ + Expanded( + child: IgnorePointer( + child: DoubleTapIcon( + onDoubleTap: () {}, + tag: tag, + isForward: false, + iconOnly: true, + ), + ), ), - ), - ), - Expanded( - child: IgnorePointer( - child: _LeftRightDoubleTapBox( - tag: tag, - isLeft: false, + Expanded( + child: IgnorePointer( + child: DoubleTapIcon( + onDoubleTap: () {}, + tag: tag, + isForward: true, + iconOnly: true, + ), + ), ), - ), - ), - ], + ], + ); + }, ), ), IgnorePointer(child: _podCtr.videoTitle ?? const SizedBox()), diff --git a/lib/src/widgets/doubble_tap_effect.dart b/lib/src/widgets/doubble_tap_effect.dart new file mode 100644 index 00000000..e68370e6 --- /dev/null +++ b/lib/src/widgets/doubble_tap_effect.dart @@ -0,0 +1,238 @@ +import 'package:flutter/material.dart'; + +class DoubleTapRippleEffect extends StatefulWidget { + /// child widget [child] + final Widget? child; + + /// Helps to wrap child widget inside a parent widget + final Widget Function(Widget parentWidget, double curveRadius)? wrapper; + + /// touch effect color of widget [rippleColor] + final Color? rippleColor; + + /// TouchRippleEffect widget background color [backgroundColor] + final Color? backgroundColor; + + /// if you have border of child widget then you should apply [borderRadius] + final BorderRadius? borderRadius; + + /// animation duration of touch effect. [rippleDuration] + final Duration? rippleDuration; + + /// duration to stay the frame. [rippleEndingDuraiton] + final Duration? rippleEndingDuraiton; + + /// user click or tap handle [onDoubleTap]. + final void Function()? onDoubleTap; + + /// TouchRippleEffect widget width size [width] + final double? width; + + /// TouchRippleEffect widget height size [height] + final double? height; + + const DoubleTapRippleEffect({ + Key? key, + this.child, + this.wrapper, + this.rippleColor, + this.backgroundColor, + this.borderRadius, + this.rippleDuration, + this.rippleEndingDuraiton, + this.onDoubleTap, + this.width, + this.height, + }) : super(key: key); + + @override + State createState() => _DoubleTapRippleEffectState(); +} + +class _DoubleTapRippleEffectState extends State + with SingleTickerProviderStateMixin { + // by default offset will be 0,0 + // it will be set when user tap on widget + Offset _tapOffset = Offset.zero; + + // globalKey variable decleared + final GlobalKey _globalKey = GlobalKey(); + + // animation global variable decleared and + // type cast is double + late Animation _anim; + + // animation controller global variable decleared + late AnimationController _animationController; + + /// width of user child widget + double _mWidth = 0; + + // height of user child widget + double _mHeight = 0; + + // tween animation global variable decleared and + // type cast is double + late Tween _tweenAnim; + + // animation count of Tween anim. + // by default value is 0. + double _animRadiusValue = 0; + + @override + void initState() { + super.initState(); + // animation controller initialized + _animationController = AnimationController( + vsync: this, + duration: widget.rippleDuration ?? const Duration(milliseconds: 300), + ); + // animation controller listener added or iitialized + _animationController.addListener(_update); + } + + // update animation when started + + void _update() { + setState(() { + // [_anim.value] setting to [_animRadiusValue] global variable + _animRadiusValue = _anim.value; + }); + // animation status function calling + _animStatus(); + } + + // checking animation status is completed + void _animStatus() { + if (_anim.status == AnimationStatus.completed) { + Future.delayed( + widget.rippleEndingDuraiton ?? const Duration(milliseconds: 600), + ).then((value) { + setState(() { + _animRadiusValue = 0; + }); + // stoping animation after completed + _animationController.stop(); + }); + } + } + + @override + void dispose() { + // disposing [_animationController] when parent exist of close + _animationController.dispose(); + super.dispose(); + } + + // animation initialize reset and start + void _animate() { + final width = widget.width ?? _mWidth; + final height = widget.height ?? _mHeight; + // [Tween] animation initialize to global variable + _tweenAnim = Tween(begin: 0, end: (width + height) / 1.5); + + // adding [_animationController] to [_tweenanim] to animate + _anim = _tweenAnim.animate(_animationController); + + _animationController + // resetting [_animationController] before start + ..reset() + // starting [_animationController] to start animation + ..forward(); + } + + @override + Widget build(BuildContext context) { + final curveRadius = (_mWidth + _mHeight) / 2; + if (widget.wrapper != null) return widget.wrapper!(_builder(), curveRadius); + return _builder(); + } + + Widget _builder() { + return GestureDetector( + onDoubleTap: widget.onDoubleTap, + onDoubleTapDown: (details) { + // getting tap [localPostion] of user + final lp = details.localPosition; + setState(() { + /// setting [Offset] of user tap to [_tapOffset] global variable + _tapOffset = Offset(lp.dx, lp.dy); + }); + + // getting [size] of child widget + final size = _globalKey.currentContext!.size!; + + // child widget [width] initialize to [_width] global variable + _mWidth = size.width; + + // child widget [height] initialize to [_height] global variable + _mHeight = size.height; + + // starting animation + _animate(); + }, + child: Container( + width: widget.width, + height: widget.height, + + // added globalKey for getting child widget size + key: _globalKey, + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration( + // when color == null then color will be transpatent otherwise color will be backgroundColor + color: widget.backgroundColor ?? Colors.transparent, + + // boderRadius of container if user passed + borderRadius: widget.borderRadius, + ), + child: Stack( + children: [ + // added child widget of user + widget.child!, + Opacity( + opacity: 0.3, + child: CustomPaint( + // ripplePainter is CustomPainer for circular ripple draw + painter: RipplePainer( + offset: _tapOffset, + circleRadius: _animRadiusValue, + fillColor: widget.rippleColor, + ), + ), + ) + ], + ), + ), + ); + } +} + +class RipplePainer extends CustomPainter { + // user tap locations [Offset] + final Offset? offset; + + // radius of circle which will be ripple color size [circleRadius] + final double? circleRadius; + + // fill color of ripple [fillColor] + final Color? fillColor; + RipplePainer({this.offset, this.circleRadius, this.fillColor}); + + @override + void paint(Canvas canvas, Size size) { + // throw an [rippleColor == null error] if ripple color is null + final paint = Paint() + ..color = fillColor == null + ? throw Exception('rippleColor of TouchRippleEffect == null') + : fillColor! + ..isAntiAlias = true; + + // drawing canvas based on user click offset,radius and paint + canvas.drawCircle(offset!, circleRadius!, paint); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) { + return true; + } +} diff --git a/lib/src/widgets/double_tap_icon.dart b/lib/src/widgets/double_tap_icon.dart new file mode 100644 index 00000000..2f2ae9ee --- /dev/null +++ b/lib/src/widgets/double_tap_icon.dart @@ -0,0 +1,186 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../controllers/pod_getx_video_controller.dart'; +import 'doubble_tap_effect.dart'; + +class DoubleTapIcon extends StatefulWidget { + final void Function() onDoubleTap; + final String tag; + final bool iconOnly; + final bool isForward; + final double height; + final double? width; + + const DoubleTapIcon({ + Key? key, + required this.onDoubleTap, + required this.tag, + this.iconOnly = false, + required this.isForward, + this.height = 50, + this.width, + }) : super(key: key); + + @override + State createState() => _DoubleTapIconState(); +} + +class _DoubleTapIconState extends State + with SingleTickerProviderStateMixin { + late final AnimationController _animationController; + late final Animation opacityCtr; + + @override + void initState() { + super.initState(); + _animationController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 200), + ); + opacityCtr = Tween(begin: 0, end: 1).animate( + CurvedAnimation( + parent: _animationController, + curve: Curves.easeInOut, + ), + ); + final podCtr = Get.find(tag: widget.tag); + if (widget.iconOnly && !widget.isForward) { + podCtr.addListenerId('double-tap-left', _onDoubleTap); + } + if (widget.iconOnly && widget.isForward) { + podCtr.addListenerId('double-tap-right', _onDoubleTap); + } + } + + @override + void dispose() { + final podCtr = Get.find(tag: widget.tag); + + if (widget.iconOnly && !widget.isForward) { + podCtr.removeListenerId('double-tap-left', _onDoubleTap); + } + if (widget.iconOnly && widget.isForward) { + podCtr.removeListenerId('double-tap-right', _onDoubleTap); + } + _animationController.dispose(); + super.dispose(); + } + + void _onDoubleTap() { + widget.onDoubleTap(); + _animationController.forward().then((_) { + _animationController.reverse(); + }); + } + + @override + Widget build(BuildContext context) { + if (widget.iconOnly) return iconWithText(); + return DoubleTapRippleEffect( + onDoubleTap: _onDoubleTap, + rippleColor: Colors.white, + wrapper: (parentWidget, curveRadius) { + final forwardRadius = + !widget.isForward ? Radius.zero : Radius.circular(curveRadius); + final backwardRadius = + widget.isForward ? Radius.zero : Radius.circular(curveRadius); + return ClipRRect( + borderRadius: BorderRadius.only( + bottomLeft: forwardRadius, + topLeft: forwardRadius, + bottomRight: backwardRadius, + topRight: backwardRadius, + ), + child: parentWidget, + ); + }, + child: iconWithText(), + ); + } + + SizedBox iconWithText() { + return SizedBox( + height: widget.height, + width: widget.width, + child: AnimatedBuilder( + animation: _animationController, + builder: (context, child) { + const icon = Icon( + Icons.play_arrow_sharp, + size: 32, + color: Colors.white, + ); + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + RotatedBox( + quarterTurns: widget.isForward ? 0 : 2, + child: Stack( + children: [ + AnimatedOpacity( + duration: const Duration(milliseconds: 200), + opacity: opacityCtr.value, + child: icon, + ), + Padding( + padding: const EdgeInsets.only(left: 20), + child: AnimatedOpacity( + duration: const Duration(milliseconds: 300), + opacity: opacityCtr.value, + child: icon, + ), + ), + Padding( + padding: const EdgeInsets.only(left: 40), + child: AnimatedOpacity( + duration: const Duration(milliseconds: 600), + opacity: opacityCtr.value, + child: icon, + ), + ), + ], + ), + ), + GetBuilder( + tag: widget.tag, + id: 'double-tap', + builder: (_podCtr) { + if (widget.isForward && _podCtr.isRightDbTapIconVisible) { + return AnimatedOpacity( + duration: const Duration(milliseconds: 300), + opacity: opacityCtr.value, + child: Text( + '${_podCtr.isLeftDbTapIconVisible ? _podCtr.leftDoubleTapduration : _podCtr.rightDubleTapduration} Sec', + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ); + } + if (!widget.isForward && _podCtr.isLeftDbTapIconVisible) { + return AnimatedOpacity( + duration: const Duration(milliseconds: 300), + opacity: opacityCtr.value, + child: Text( + '${_podCtr.isLeftDbTapIconVisible ? _podCtr.leftDoubleTapduration : _podCtr.rightDubleTapduration} Sec', + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ); + } + return const SizedBox(); + }, + ), + ], + ), + ); + }, + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 1e75757d..f1e1cc00 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -10,8 +10,6 @@ environment: dependencies: flutter: sdk: flutter - # ui - lottie: ^1.3.0 # services video_player: ^2.6.1 http: ^0.13.6 From ee7a49b52110fc58d5a33e03e36419ac5e96e351 Mon Sep 17 00:00:00 2001 From: newtaDev Date: Sun, 7 May 2023 19:58:36 +0530 Subject: [PATCH 05/24] chore: imrove pub score --- analysis_options.yaml | 2 -- lib/src/widgets/core/overlays/web_dropdown_menu.dart | 1 - 2 files changed, 3 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index a547bf2a..bc17491f 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -13,7 +13,6 @@ analyzer: linter: rules: omit_local_variable_types: false - missing_required_param: true prefer_const_declarations: true prefer_const_constructors: true public_member_api_docs: false @@ -22,7 +21,6 @@ linter: lines_longer_than_80_chars: false prefer_relative_imports: true always_use_package_imports: false - import_of_legacy_library_into_null_safe: true avoid_print: true prefer_single_quotes: true avoid_redundant_argument_values: true diff --git a/lib/src/widgets/core/overlays/web_dropdown_menu.dart b/lib/src/widgets/core/overlays/web_dropdown_menu.dart index 0d62564f..6faee487 100644 --- a/lib/src/widgets/core/overlays/web_dropdown_menu.dart +++ b/lib/src/widgets/core/overlays/web_dropdown_menu.dart @@ -18,7 +18,6 @@ class _WebSettingsDropdownState extends State<_WebSettingsDropdown> { return Theme( data: Theme.of(context).copyWith( focusColor: Colors.white, - selectedRowColor: Colors.white, ), child: GetBuilder( tag: widget.tag, From 3c7f2c01daf3f9dcf73c5f889797f52724b7cb4e Mon Sep 17 00:00:00 2001 From: newtaDev Date: Sun, 7 May 2023 20:39:16 +0530 Subject: [PATCH 06/24] =?UTF-8?q?=F0=9F=9A=80=20pub=20-v=200.1.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 ++++++ README.md | 11 ++++++----- pubspec.yaml | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26acffa1..28072166 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.1.1 + - Feature + - support vimeo private video [ref](https://github.com/newtaDev/pod_player#how-to-play-video-from-vimeo-private-videos) + - double tap ripple effect added + - upgraded dependencies + - merged PR #66 #77 #78 ## 0.1.0 - Breaking change: diff --git a/README.md b/README.md index b30edfe0..0ff06886 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,14 @@ This plugin built upon flutter's official [`video_player`](https://pub.dartlang. pod_player +- Video player on web --- +

+ pod_player +

+ + - Vimeo player and custom video player --- @@ -116,11 +122,6 @@ This plugin built upon flutter's official [`video_player`](https://pub.dartlang. --- ---- - -

- pod_player -

## Usage diff --git a/pubspec.yaml b/pubspec.yaml index f1e1cc00..09d58a34 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pod_player description: Vimeo and youtube player for flutter, Pod player provides customizable video player controls that support android, ios and web. -version: 0.1.0 +version: 0.1.1 homepage: https://github.com/newtaDev/pod_player environment: From bc4d30b20991c1ba524f50d242f2fb2a099d9885 Mon Sep 17 00:00:00 2001 From: newtaDev Date: Tue, 9 May 2023 09:27:00 +0530 Subject: [PATCH 07/24] fix: videoQuality cannot be empty #82 --- lib/src/utils/video_apis.dart | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/src/utils/video_apis.dart b/lib/src/utils/video_apis.dart index e319469e..cec731d7 100644 --- a/lib/src/utils/video_apis.dart +++ b/lib/src/utils/video_apis.dart @@ -20,7 +20,7 @@ class VideoApis { ); final jsonData = jsonDecode(response.body)['request']['files']['progressive']; - return List.generate( + final progressiveUrls = List.generate( jsonData.length, (index) => VideoQalityUrls( quality: int.parse( @@ -29,6 +29,20 @@ class VideoApis { url: jsonData[index]['url'], ), ); + if (progressiveUrls.isEmpty) { + final jsonRes = + jsonDecode(response.body)['request']['files']['hls']['cdns']; + for (final element in (jsonRes as Map).entries.toList()) { + progressiveUrls.add( + VideoQalityUrls( + quality: 720, + url: element.value['url'], + ), + ); + break; + } + } + return progressiveUrls; } catch (error) { if (error.toString().contains('XMLHttpRequest')) { log( From e6a4a6a403d9d284b1b9df165369f99af31d6a7c Mon Sep 17 00:00:00 2001 From: newtaDev Date: Tue, 9 May 2023 09:32:27 +0530 Subject: [PATCH 08/24] =?UTF-8?q?=F0=9F=9A=80=20pub=20-v=200.1.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 ++ pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28072166..a55d7fdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.1.2 + - fixed #82 ## 0.1.1 - Feature - support vimeo private video [ref](https://github.com/newtaDev/pod_player#how-to-play-video-from-vimeo-private-videos) diff --git a/pubspec.yaml b/pubspec.yaml index 09d58a34..09db1fe4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pod_player description: Vimeo and youtube player for flutter, Pod player provides customizable video player controls that support android, ios and web. -version: 0.1.1 +version: 0.1.2 homepage: https://github.com/newtaDev/pod_player environment: From 4009fd85ed3517a01b5c8d830389d489fd55351c Mon Sep 17 00:00:00 2001 From: sybrands-place <60786797+sybrands-place@users.noreply.github.com> Date: Wed, 10 May 2023 11:00:31 +0200 Subject: [PATCH 09/24] Update pubspec.yaml Remove assets folder, because does not exist in project --- pubspec.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 09db1fe4..c52663f2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -22,6 +22,3 @@ dev_dependencies: sdk: flutter very_good_analysis: ^2.4.0 -flutter: - assets: - - assets/ From 8160108e22b5707aa0f36d8a92f4d7e44cc21b0c Mon Sep 17 00:00:00 2001 From: newtaDev Date: Mon, 22 May 2023 22:44:49 +0530 Subject: [PATCH 10/24] feat: improved pub sccore, fixed: window depricated issue feat: added logo to pub migrated: flutter format script --- lib/src/pod_player.dart | 1 - .../widgets/core/overlays/mobile_overlay.dart | 2 +- screenshots/logo.png | Bin 0 -> 12500 bytes scripts/verify_pub.sh | 2 +- 4 files changed, 2 insertions(+), 3 deletions(-) create mode 100644 screenshots/logo.png diff --git a/lib/src/pod_player.dart b/lib/src/pod_player.dart index f799523d..d714e21d 100644 --- a/lib/src/pod_player.dart +++ b/lib/src/pod_player.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:ui'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/lib/src/widgets/core/overlays/mobile_overlay.dart b/lib/src/widgets/core/overlays/mobile_overlay.dart index e5bc3749..72123f59 100644 --- a/lib/src/widgets/core/overlays/mobile_overlay.dart +++ b/lib/src/widgets/core/overlays/mobile_overlay.dart @@ -88,7 +88,7 @@ class _MobileOverlay extends StatelessWidget { } bool _isRtl() { - final Locale locale = window.locale; + final Locale locale = WidgetsBinding.instance.platformDispatcher.locale; final langs = [ 'ar', // Arabic 'fa', // Farsi diff --git a/screenshots/logo.png b/screenshots/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ab58ee62844d7323b0c0e5fa74276ec8393c0040 GIT binary patch literal 12500 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 e6HM?ThkpU7tv~SnwkOp90000 Date: Mon, 22 May 2023 22:47:02 +0530 Subject: [PATCH 11/24] =?UTF-8?q?=F0=9F=9A=80=20pub=20-v=200.1.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 5 +++++ pubspec.yaml | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a55d7fdb..dca4c206 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.1.4 + - added pod player logo to pub.dev +## 0.1.3 + - fix: unable to find directory entry in pubspec.yaml #114 + - merged PR #109 ## 0.1.2 - fixed #82 ## 0.1.1 diff --git a/pubspec.yaml b/pubspec.yaml index c52663f2..5c5204f4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,10 @@ name: pod_player description: Vimeo and youtube player for flutter, Pod player provides customizable video player controls that support android, ios and web. -version: 0.1.2 +version: 0.1.4 homepage: https://github.com/newtaDev/pod_player environment: - sdk: ">=2.17.0 <3.0.0" + sdk: ">=2.17.0 <4.0.0" flutter: ">=1.17.0" dependencies: @@ -22,3 +22,6 @@ dev_dependencies: sdk: flutter very_good_analysis: ^2.4.0 +screenshots: + - description: Pod video player logo + path: screenshots/logo.png \ No newline at end of file From d59ba9dd3517f5ca098c8bad4678ec9a506eb8bf Mon Sep 17 00:00:00 2001 From: newtaDev Date: Tue, 6 Jun 2023 18:51:37 +0530 Subject: [PATCH 12/24] =?UTF-8?q?=F0=9F=9A=80=20pub=20-v=200.1.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 5 +++++ README.md | 17 ++++++++--------- example/android/build.gradle | 2 +- example/ios/Runner.xcodeproj/project.pbxproj | 1 + .../widgets/core/overlays/mobile_overlay.dart | 2 +- pubspec.yaml | 4 ++-- 6 files changed, 18 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dca4c206..e8163f83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.1.5 + - merged PR #103 + - support unlisted vimeo videos + - upgraded dependencies + - Updated Readme file ## 0.1.4 - added pod player logo to pub.dev ## 0.1.3 diff --git a/README.md b/README.md index e1cc8279..ea8b1e19 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,10 @@

- pub likes - pub version - popularity - pub points + pub likes + pub version + score + pub points

Video player for flutter web & mobile devices, pod player supports playing video from `Youtube` and `Vimeo` @@ -69,13 +69,13 @@ This plugin built upon flutter's official [`video_player`](https://pub.dartlang. - Video player on web + ---

pod_player

- - Vimeo player and custom video player --- @@ -122,7 +122,6 @@ This plugin built upon flutter's official [`video_player`](https://pub.dartlang. --- - ## Usage - [Installation](#installation) @@ -440,14 +439,14 @@ class PlayVideoFromVimeoPrivateVideo extends StatefulWidget { _PlayVideoFromVimeoPrivateVideoState(); } -class _PlayVideoFromVimeoPrivateVideoState +class _PlayVideoFromVimeoPrivateVideoState extends State { late final PodPlayerController controller; @override void initState() { - String videoId = 'your private video id'; - String token = 'your access token'; + String videoId = 'your private video id'; + String token = 'your access token'; final Map headers = {}; headers['Authorization'] = 'Bearer ${token}'; diff --git a/example/android/build.gradle b/example/android/build.gradle index 83ae2200..3cdaac95 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -26,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index ee49c1b2..5b1c9f9c 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -204,6 +204,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( diff --git a/lib/src/widgets/core/overlays/mobile_overlay.dart b/lib/src/widgets/core/overlays/mobile_overlay.dart index 72123f59..2d4f713d 100644 --- a/lib/src/widgets/core/overlays/mobile_overlay.dart +++ b/lib/src/widgets/core/overlays/mobile_overlay.dart @@ -88,7 +88,7 @@ class _MobileOverlay extends StatelessWidget { } bool _isRtl() { - final Locale locale = WidgetsBinding.instance.platformDispatcher.locale; + final Locale locale = WidgetsBinding.instance.platformDispatcher.locale; final langs = [ 'ar', // Arabic 'fa', // Farsi diff --git a/pubspec.yaml b/pubspec.yaml index 5c5204f4..cb885ef8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pod_player description: Vimeo and youtube player for flutter, Pod player provides customizable video player controls that support android, ios and web. -version: 0.1.4 +version: 0.1.5 homepage: https://github.com/newtaDev/pod_player environment: @@ -15,7 +15,7 @@ dependencies: http: ^0.13.6 get: ^4.6.5 wakelock: ^0.6.2 - universal_html: ^2.2.1 + universal_html: ^2.2.3 youtube_explode_dart: ^1.12.4 dev_dependencies: flutter_test: From dfa3bb384f24d1a952bcf5c178c9594c27552780 Mon Sep 17 00:00:00 2001 From: oplik0 Date: Wed, 5 Jul 2023 01:48:32 +0200 Subject: [PATCH 13/24] feat: move to wakelock plus --- example/macos/Flutter/GeneratedPluginRegistrant.swift | 6 ++++-- lib/src/controllers/pod_getx_video_controller.dart | 8 ++++---- lib/src/controllers/pod_player_controller.dart | 4 ++-- pubspec.yaml | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift index 1c2c9b07..f26940ad 100644 --- a/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,8 +5,10 @@ import FlutterMacOS import Foundation -import wakelock_macos +import package_info_plus +import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - WakelockMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockMacosPlugin")) + FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) + WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) } diff --git a/lib/src/controllers/pod_getx_video_controller.dart b/lib/src/controllers/pod_getx_video_controller.dart index 33c5d3fc..efbf1f37 100644 --- a/lib/src/controllers/pod_getx_video_controller.dart +++ b/lib/src/controllers/pod_getx_video_controller.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:universal_html/html.dart' as _html; -import 'package:wakelock/wakelock.dart'; +import 'package:wakelock_plus/wakelock_plus.dart'; import '../../pod_player.dart'; import '../utils/logger.dart'; @@ -257,18 +257,18 @@ class PodGetXVideoController extends _PodGesturesController { podLog(_podVideoState.toString()); switch (_podVideoState) { case PodVideoState.playing: - if (podPlayerConfig.wakelockEnabled) Wakelock.enable(); + if (podPlayerConfig.wakelockEnabled) WakelockPlus.enable(); playVideo(true); break; case PodVideoState.paused: - if (podPlayerConfig.wakelockEnabled) Wakelock.disable(); + if (podPlayerConfig.wakelockEnabled) WakelockPlus.disable(); playVideo(false); break; case PodVideoState.loading: isShowOverlay(true); break; case PodVideoState.error: - if (podPlayerConfig.wakelockEnabled) Wakelock.disable(); + if (podPlayerConfig.wakelockEnabled) WakelockPlus.disable(); playVideo(false); break; } diff --git a/lib/src/controllers/pod_player_controller.dart b/lib/src/controllers/pod_player_controller.dart index a9c17b3c..dc6f0f05 100644 --- a/lib/src/controllers/pod_player_controller.dart +++ b/lib/src/controllers/pod_player_controller.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import 'package:universal_html/html.dart' as _html; -import 'package:wakelock/wakelock.dart'; +import 'package:wakelock_plus/wakelock_plus.dart'; import '../../pod_player.dart'; import '../utils/logger.dart'; @@ -166,7 +166,7 @@ class PodPlayerController { _ctr.videoCtr?.removeListener(_ctr.videoListner); _ctr.videoCtr?.dispose(); _ctr.removeListenerId('podVideoState', _ctr.podStateListner); - if (podPlayerConfig.wakelockEnabled) Wakelock.disable(); + if (podPlayerConfig.wakelockEnabled) WakelockPlus.disable(); Get.delete( force: true, tag: getTag, diff --git a/pubspec.yaml b/pubspec.yaml index cb885ef8..93871ad2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: video_player: ^2.6.1 http: ^0.13.6 get: ^4.6.5 - wakelock: ^0.6.2 + wakelock_plus: ^1.0.0 universal_html: ^2.2.3 youtube_explode_dart: ^1.12.4 dev_dependencies: From c863193487a1c73069d4c43926b4af07afaff07b Mon Sep 17 00:00:00 2001 From: oplik0 Date: Wed, 5 Jul 2023 01:54:58 +0200 Subject: [PATCH 14/24] chore: ensure the latest version is specified --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 93871ad2..2673138d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: video_player: ^2.6.1 http: ^0.13.6 get: ^4.6.5 - wakelock_plus: ^1.0.0 + wakelock_plus: ^1.0.0+3 universal_html: ^2.2.3 youtube_explode_dart: ^1.12.4 dev_dependencies: From 26907da1bee51ba072d8525030d014629468d9f9 Mon Sep 17 00:00:00 2001 From: newtaDev Date: Sat, 8 Jul 2023 12:00:34 +0530 Subject: [PATCH 15/24] - upgraded dependencies - changes in CI - migrate from `wakelock` to `wakelock_plus` - fixed all lint rules - migrated `VideoPlayerController.network` to `VideoPlayerController.networkUrl` - In `PlayVideoFrom.file` [file] param datatype changed from [dynamic] to [File] --- .github/workflows/ci.yml | 2 + analysis_options.yaml | 9 +- example/android/app/build.gradle | 2 +- example/ios/Podfile.lock | 16 ++-- lib/pod_player.dart | 1 + lib/src/controllers/pod_base_controller.dart | 6 +- .../pod_getx_video_controller.dart | 52 +++++------ .../controllers/pod_player_controller.dart | 16 ++-- lib/src/controllers/pod_video_controller.dart | 24 +++--- .../pod_video_quality_controller.dart | 20 ++--- lib/src/models/play_video_from.dart | 8 +- lib/src/pod_player.dart | 30 +++---- lib/src/utils/video_apis.dart | 18 ++-- lib/src/widgets/animated_play_pause_icon.dart | 29 +++---- .../core/overlays/mobile_bottomsheet.dart | 86 +++++++++---------- .../widgets/core/overlays/mobile_overlay.dart | 23 +++-- lib/src/widgets/core/overlays/overlays.dart | 43 +++++----- .../core/overlays/web_dropdown_menu.dart | 69 ++++++++------- .../widgets/core/overlays/web_overlay.dart | 77 ++++++++--------- lib/src/widgets/core/pod_core_player.dart | 39 ++++----- .../widgets/core/video_gesture_detector.dart | 13 ++- lib/src/widgets/doubble_tap_effect.dart | 6 +- lib/src/widgets/double_tap_icon.dart | 16 ++-- lib/src/widgets/full_screen_view.dart | 14 +-- lib/src/widgets/material_icon_button.dart | 8 +- lib/src/widgets/pod_progress_bar.dart | 33 ++++--- pubspec.yaml | 6 +- 27 files changed, 334 insertions(+), 332 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b1a9f80..2090a0d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,9 @@ name: CI on: push: + branches: [master] pull_request: + branches: [master] jobs: check-format: diff --git a/analysis_options.yaml b/analysis_options.yaml index bc17491f..18aea978 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,15 +1,14 @@ include: package:very_good_analysis/analysis_options.yaml analyzer: - strong-mode: - implicit-casts: true - implicit-dynamic: true errors: missing_required_param: error prefer_const_declarations: warning prefer_const_constructors: warning import_of_legacy_library_into_null_safe: warning public_member_api_docs: ignore - + language: + strict-casts: true + strict-raw-types: true linter: rules: omit_local_variable_types: false @@ -32,4 +31,4 @@ linter: avoid_positional_boolean_parameters: false use_build_context_synchronously: false use_setters_to_change_properties: false - avoid_bool_literals_in_conditional_expressions: false \ No newline at end of file + avoid_bool_literals_in_conditional_expressions: false diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 0833ecfc..7f0f1a52 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -47,7 +47,7 @@ android { applicationId "com.example.example" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. - minSdkVersion flutter.minSdkVersion + minSdkVersion 19 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 7cadee30..2d8232cd 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,27 +1,33 @@ PODS: - Flutter (1.0.0) + - package_info_plus (0.4.5): + - Flutter - video_player_avfoundation (0.0.1): - Flutter - - wakelock (0.0.1): + - wakelock_plus (0.0.1): - Flutter DEPENDENCIES: - Flutter (from `Flutter`) + - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`) - - wakelock (from `.symlinks/plugins/wakelock/ios`) + - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`) EXTERNAL SOURCES: Flutter: :path: Flutter + package_info_plus: + :path: ".symlinks/plugins/package_info_plus/ios" video_player_avfoundation: :path: ".symlinks/plugins/video_player_avfoundation/ios" - wakelock: - :path: ".symlinks/plugins/wakelock/ios" + wakelock_plus: + :path: ".symlinks/plugins/wakelock_plus/ios" SPEC CHECKSUMS: Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7 video_player_avfoundation: 81e49bb3d9fb63dccf9fa0f6d877dc3ddbeac126 - wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f + wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 diff --git a/lib/pod_player.dart b/lib/pod_player.dart index 566e146a..e7a0d631 100644 --- a/lib/pod_player.dart +++ b/lib/pod_player.dart @@ -1,3 +1,4 @@ +/// Pod Player library library pod_player; export 'package:video_player/video_player.dart'; diff --git a/lib/src/controllers/pod_base_controller.dart b/lib/src/controllers/pod_base_controller.dart index 5917c3fc..4edc604c 100644 --- a/lib/src/controllers/pod_base_controller.dart +++ b/lib/src/controllers/pod_base_controller.dart @@ -80,9 +80,9 @@ class _PodBaseController extends GetxController { // } ///updates state with id `_podVideoState` - void podVideoStateChanger(PodVideoState? _val, {bool updateUi = true}) { - if (_podVideoState != (_val ?? _podVideoState)) { - _podVideoState = _val ?? _podVideoState; + void podVideoStateChanger(PodVideoState? val, {bool updateUi = true}) { + if (_podVideoState != (val ?? _podVideoState)) { + _podVideoState = val ?? _podVideoState; if (updateUi) { update(['podVideoState']); update(['update-all']); diff --git a/lib/src/controllers/pod_getx_video_controller.dart b/lib/src/controllers/pod_getx_video_controller.dart index efbf1f37..7a46d30d 100644 --- a/lib/src/controllers/pod_getx_video_controller.dart +++ b/lib/src/controllers/pod_getx_video_controller.dart @@ -5,7 +5,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import 'package:universal_html/html.dart' as _html; +import 'package:universal_html/html.dart' as uni_html; import 'package:wakelock_plus/wakelock_plus.dart'; import '../../pod_player.dart'; @@ -69,8 +69,8 @@ class PodGetXVideoController extends _PodGesturesController { update(['update-all']); // ignore: unawaited_futures - Future.delayed(const Duration(milliseconds: 600)) - .then((value) => _isWebAutoPlayDone = true); + Future.delayed(const Duration(milliseconds: 600)) + .then((_) => _isWebAutoPlayDone = true); } catch (e) { podVideoStateChanger(PodVideoState.error); update(['errorState']); @@ -85,8 +85,8 @@ class PodGetXVideoController extends _PodGesturesController { case PodVideoPlayerType.network: /// - _videoCtr = VideoPlayerController.network( - playVideoFrom.dataSource!, + _videoCtr = VideoPlayerController.networkUrl( + Uri.parse(playVideoFrom.dataSource!), closedCaptionFile: playVideoFrom.closedCaptionFile, formatHint: playVideoFrom.formatHint, videoPlayerOptions: playVideoFrom.videoPlayerOptions, @@ -95,41 +95,41 @@ class PodGetXVideoController extends _PodGesturesController { playingVideoUrl = playVideoFrom.dataSource; break; case PodVideoPlayerType.networkQualityUrls: - final _url = await getUrlFromVideoQualityUrls( + final url = await getUrlFromVideoQualityUrls( qualityList: podPlayerConfig.videoQualityPriority, videoUrls: playVideoFrom.videoQualityUrls!, ); /// - _videoCtr = VideoPlayerController.network( - _url, + _videoCtr = VideoPlayerController.networkUrl( + Uri.parse(url), closedCaptionFile: playVideoFrom.closedCaptionFile, formatHint: playVideoFrom.formatHint, videoPlayerOptions: playVideoFrom.videoPlayerOptions, httpHeaders: playVideoFrom.httpHeaders, ); - playingVideoUrl = _url; + playingVideoUrl = url; break; case PodVideoPlayerType.youtube: - final _urls = await getVideoQualityUrlsFromYoutube( + final urls = await getVideoQualityUrlsFromYoutube( playVideoFrom.dataSource!, playVideoFrom.live, ); - final _url = await getUrlFromVideoQualityUrls( + final url = await getUrlFromVideoQualityUrls( qualityList: podPlayerConfig.videoQualityPriority, - videoUrls: _urls, + videoUrls: urls, ); /// - _videoCtr = VideoPlayerController.network( - _url, + _videoCtr = VideoPlayerController.networkUrl( + Uri.parse(url), closedCaptionFile: playVideoFrom.closedCaptionFile, formatHint: playVideoFrom.formatHint, videoPlayerOptions: playVideoFrom.videoPlayerOptions, httpHeaders: playVideoFrom.httpHeaders, ); - playingVideoUrl = _url; + playingVideoUrl = url; break; case PodVideoPlayerType.vimeo: @@ -137,19 +137,19 @@ class PodGetXVideoController extends _PodGesturesController { playVideoFrom.dataSource!, hash: playVideoFrom.hash, ); - final _url = await getUrlFromVideoQualityUrls( + final url = await getUrlFromVideoQualityUrls( qualityList: podPlayerConfig.videoQualityPriority, videoUrls: vimeoOrVideoUrls, ); - _videoCtr = VideoPlayerController.network( - _url, + _videoCtr = VideoPlayerController.networkUrl( + Uri.parse(url), closedCaptionFile: playVideoFrom.closedCaptionFile, formatHint: playVideoFrom.formatHint, videoPlayerOptions: playVideoFrom.videoPlayerOptions, httpHeaders: playVideoFrom.httpHeaders, ); - playingVideoUrl = _url; + playingVideoUrl = url; break; case PodVideoPlayerType.asset: @@ -182,19 +182,19 @@ class PodGetXVideoController extends _PodGesturesController { playVideoFrom.dataSource!, playVideoFrom.httpHeaders, ); - final _url = await getUrlFromVideoQualityUrls( + final url = await getUrlFromVideoQualityUrls( qualityList: podPlayerConfig.videoQualityPriority, videoUrls: vimeoOrVideoUrls, ); - _videoCtr = VideoPlayerController.network( - _url, + _videoCtr = VideoPlayerController.networkUrl( + Uri.parse(url), closedCaptionFile: playVideoFrom.closedCaptionFile, formatHint: playVideoFrom.formatHint, videoPlayerOptions: playVideoFrom.videoPlayerOptions, httpHeaders: playVideoFrom.httpHeaders, ); - playingVideoUrl = _url; + playingVideoUrl = url; break; } @@ -229,7 +229,7 @@ class PodGetXVideoController extends _PodGesturesController { } if (event.isKeyPressed(LogicalKeyboardKey.escape)) { if (isFullScreen) { - _html.document.exitFullscreen(); + uni_html.document.exitFullscreen(); if (!isWebPopupOverlayOpen) { disableFullScreen(appContext, tag); } @@ -242,12 +242,12 @@ class PodGetXVideoController extends _PodGesturesController { void toggleFullScreenOnWeb(BuildContext context, String tag) { if (isFullScreen) { - _html.document.exitFullscreen(); + uni_html.document.exitFullscreen(); if (!isWebPopupOverlayOpen) { disableFullScreen(context, tag); } } else { - _html.document.documentElement?.requestFullscreen(); + uni_html.document.documentElement?.requestFullscreen(); enableFullScreen(tag); } } diff --git a/lib/src/controllers/pod_player_controller.dart b/lib/src/controllers/pod_player_controller.dart index dc6f0f05..229ce884 100644 --- a/lib/src/controllers/pod_player_controller.dart +++ b/lib/src/controllers/pod_player_controller.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; -import 'package:universal_html/html.dart' as _html; +import 'package:universal_html/html.dart' as uni_html; import 'package:wakelock_plus/wakelock_plus.dart'; import '../../pod_player.dart'; @@ -78,7 +78,7 @@ class PodPlayerController { throw Exception(_initializationError.toString()); } - await Future.delayed(const Duration(milliseconds: 500)); + await Future.delayed(const Duration(milliseconds: 500)); await _checkAndWaitTillInitialized(); } @@ -196,17 +196,17 @@ class PodPlayerController { } ///Moves video forward from current duration to `_duration` - Future videoSeekForward(Duration _duration) async { + Future videoSeekForward(Duration duration) async { await _checkAndWaitTillInitialized(); if (!_isCtrInitialised) return; - return _ctr.seekForward(_duration); + return _ctr.seekForward(duration); } ///Moves video backward from current duration to `_duration` - Future videoSeekBackward(Duration _duration) async { + Future videoSeekBackward(Duration duration) async { await _checkAndWaitTillInitialized(); if (!_isCtrInitialised) return; - return _ctr.seekBackward(_duration); + return _ctr.seekBackward(duration); } ///on right double tap @@ -228,7 +228,7 @@ class PodPlayerController { /// If onToggleFullScreen is set, you must handle the device /// orientation by yourself. void enableFullScreen() { - _html.document.documentElement?.requestFullscreen(); + uni_html.document.documentElement?.requestFullscreen(); _ctr.enableFullScreen(getTag); } @@ -237,7 +237,7 @@ class PodPlayerController { /// If onToggleFullScreen is set, you must handle the device /// orientation by yourself. void disableFullScreen(BuildContext context) { - _html.document.exitFullscreen(); + uni_html.document.exitFullscreen(); if (!_ctr.isWebPopupOverlayOpen) { _ctr.disableFullScreen(context, getTag); diff --git a/lib/src/controllers/pod_video_controller.dart b/lib/src/controllers/pod_video_controller.dart index e9586162..345ad5cc 100644 --- a/lib/src/controllers/pod_video_controller.dart +++ b/lib/src/controllers/pod_video_controller.dart @@ -134,21 +134,21 @@ class _PodVideoController extends _PodUiController { } } - void setVideoPlayBack(String _speed) { + void setVideoPlayBack(String speed) { late double pickedSpeed; - if (_speed == 'Normal') { + if (speed == 'Normal') { pickedSpeed = 1.0; _currentPaybackSpeed = 'Normal'; } else { - pickedSpeed = double.parse(_speed.split('x').first); - _currentPaybackSpeed = _speed; + pickedSpeed = double.parse(speed.split('x').first); + _currentPaybackSpeed = speed; } _videoCtr?.setPlaybackSpeed(pickedSpeed); } - Future setLooping(bool _isLooped) async { - isLooping = _isLooped; + Future setLooping(bool isLooped) async { + isLooping = isLooped; await _videoCtr?.setLooping(isLooping); } @@ -226,7 +226,7 @@ class _PodVideoController extends _PodUiController { Navigator.push( mainContext, - PageRouteBuilder( + PageRouteBuilder( fullscreenDialog: true, pageBuilder: (BuildContext context, _, __) => FullScreenView( tag: tag, @@ -243,14 +243,14 @@ class _PodVideoController extends _PodUiController { } /// Calculates video `position` or `duration` - String calculateVideoDuration(Duration _duration) { - final _totalHour = _duration.inHours == 0 ? '' : '${_duration.inHours}:'; - final _totalMinute = _duration.toString().split(':')[1]; - final _totalSeconds = (_duration - Duration(minutes: _duration.inMinutes)) + String calculateVideoDuration(Duration duration) { + final totalHour = duration.inHours == 0 ? '' : '${duration.inHours}:'; + final totalMinute = duration.toString().split(':')[1]; + final totalSeconds = (duration - Duration(minutes: duration.inMinutes)) .inSeconds .toString() .padLeft(2, '0'); - final String videoLength = '$_totalHour$_totalMinute:$_totalSeconds'; + final String videoLength = '$totalHour$totalMinute:$totalSeconds'; return videoLength; } } diff --git a/lib/src/controllers/pod_video_quality_controller.dart b/lib/src/controllers/pod_video_quality_controller.dart index b9ca7086..f841e018 100644 --- a/lib/src/controllers/pod_video_quality_controller.dart +++ b/lib/src/controllers/pod_video_quality_controller.dart @@ -20,13 +20,13 @@ class _PodVideoQualityController extends _PodVideoController { }) async { try { podVideoStateChanger(PodVideoState.loading); - final _vimeoVideoUrls = await VideoApis.getVimeoVideoQualityUrls( + final vimeoVideoUrls = await VideoApis.getVimeoVideoQualityUrls( videoId, hash, ); /// - vimeoOrVideoUrls = _vimeoVideoUrls ?? []; + vimeoOrVideoUrls = vimeoVideoUrls ?? []; } catch (e) { rethrow; } @@ -38,11 +38,11 @@ class _PodVideoQualityController extends _PodVideoController { ) async { try { podVideoStateChanger(PodVideoState.loading); - final _vimeoVideoUrls = + final vimeoVideoUrls = await VideoApis.getVimeoPrivateVideoQualityUrls(videoId, httpHeader); /// - vimeoOrVideoUrls = _vimeoVideoUrls ?? []; + vimeoOrVideoUrls = vimeoVideoUrls ?? []; } catch (e) { rethrow; } @@ -51,21 +51,21 @@ class _PodVideoQualityController extends _PodVideoController { void sortQualityVideoUrls( List? urls, ) { - final _urls = urls; + final urls0 = urls; ///has issues with 240p - _urls?.removeWhere((element) => element.quality == 240); + urls0?.removeWhere((element) => element.quality == 240); ///has issues with 144p in web if (kIsWeb) { - _urls?.removeWhere((element) => element.quality == 144); + urls0?.removeWhere((element) => element.quality == 144); } ///sort - _urls?.sort((a, b) => a.quality.compareTo(b.quality)); + urls0?.sort((a, b) => a.quality.compareTo(b.quality)); /// - vimeoOrVideoUrls = _urls ?? []; + vimeoOrVideoUrls = urls0 ?? []; } ///get vimeo quality `ex: 1080p` url @@ -127,7 +127,7 @@ class _PodVideoQualityController extends _PodVideoController { podVideoStateChanger(PodVideoState.paused); podVideoStateChanger(PodVideoState.loading); playingVideoUrl = _videoQualityUrl; - _videoCtr = VideoPlayerController.network(_videoQualityUrl); + _videoCtr = VideoPlayerController.networkUrl(Uri.parse(_videoQualityUrl)); await _videoCtr?.initialize(); _videoDuration = _videoCtr?.value.duration ?? Duration.zero; _videoCtr?.addListener(videoListner); diff --git a/lib/src/models/play_video_from.dart b/lib/src/models/play_video_from.dart index 272efcdc..d3927bbb 100644 --- a/lib/src/models/play_video_from.dart +++ b/lib/src/models/play_video_from.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import '../../pod_player.dart'; class PlayVideoFrom { @@ -6,7 +8,7 @@ class PlayVideoFrom { final PodVideoPlayerType playerType; final VideoFormat? formatHint; final String? package; - final dynamic file; + final File? file; final List? videoQualityUrls; final Future? closedCaptionFile; final VideoPlayerOptions? videoPlayerOptions; @@ -14,10 +16,10 @@ class PlayVideoFrom { final bool live; const PlayVideoFrom._({ + required this.playerType, this.live = false, this.dataSource, this.hash, - required this.playerType, this.formatHint, this.package, this.file, @@ -62,7 +64,7 @@ class PlayVideoFrom { ///File Doesnot support web apps ///[file] is `File` Datatype import it from `dart:io` factory PlayVideoFrom.file( - dynamic file, { + File file, { Future? closedCaptionFile, VideoPlayerOptions? videoPlayerOptions, }) { diff --git a/lib/src/pod_player.dart b/lib/src/pod_player.dart index d714e21d..82f451f8 100644 --- a/lib/src/pod_player.dart +++ b/lib/src/pod_player.dart @@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import 'package:universal_html/html.dart' as _html; +import 'package:universal_html/html.dart' as uni_html; import '../pod_player.dart'; import 'controllers/pod_getx_video_controller.dart'; @@ -56,8 +56,8 @@ class PodVideoPlayer extends StatefulWidget { final WidgetBuilder? onLoading; PodVideoPlayer({ - Key? key, required this.controller, + super.key, this.frameAspectRatio = 16 / 9, this.videoAspectRatio = 16 / 9, this.alwaysShowProgressBar = true, @@ -72,7 +72,7 @@ class PodVideoPlayer extends StatefulWidget { this.videoThumbnail, this.onToggleFullScreen, this.onLoading, - }) : super(key: key) { + }) { addToUiController(); } @@ -120,7 +120,7 @@ class _PodVideoPlayerState extends State _podCtr.keyboardFocusWeb?.addListener(_podCtr.keyboadListner); } //to disable mouse right click - _html.document.onContextMenu.listen((event) => event.preventDefault()); + uni_html.document.onContextMenu.listen((event) => event.preventDefault()); } } @@ -158,7 +158,7 @@ class _PodVideoPlayerState extends State final circularProgressIndicator = _thumbnailAndLoadingWidget(); _podCtr.mainContext = context; - final _videoErrorWidget = AspectRatio( + final videoErrorWidget = AspectRatio( aspectRatio: _frameAspectRatio, child: Center( child: Column( @@ -190,15 +190,15 @@ class _PodVideoPlayerState extends State child: GetBuilder( tag: widget.controller.getTag, id: 'errorState', - builder: (_podCtr) { + builder: (podCtr) { /// Check if has any error - if (_podCtr.podVideoState == PodVideoState.error) { - return widget.onVideoError?.call() ?? _videoErrorWidget; + if (podCtr.podVideoState == PodVideoState.error) { + return widget.onVideoError?.call() ?? videoErrorWidget; } return AspectRatio( aspectRatio: _frameAspectRatio, - child: _podCtr.videoCtr?.value.isInitialized ?? false + child: podCtr.videoCtr?.value.isInitialized ?? false ? _buildPlayer() : Center(child: circularProgressIndicator), ); @@ -243,18 +243,18 @@ class _PodVideoPlayerState extends State } Widget _buildPlayer() { - final _videoAspectRatio = widget.matchVideoAspectRatioToFrame + final videoAspectRatio = widget.matchVideoAspectRatioToFrame ? _podCtr.videoCtr?.value.aspectRatio ?? widget.videoAspectRatio : widget.videoAspectRatio; if (kIsWeb) { return GetBuilder( tag: widget.controller.getTag, id: 'full-screen', - builder: (_podCtr) { - if (_podCtr.isFullScreen) return _thumbnailAndLoadingWidget(); + builder: (podCtr) { + if (podCtr.isFullScreen) return _thumbnailAndLoadingWidget(); return _PodCoreVideoPlayer( - videoPlayerCtr: _podCtr.videoCtr!, - videoAspectRatio: _videoAspectRatio, + videoPlayerCtr: podCtr.videoCtr!, + videoAspectRatio: videoAspectRatio, tag: widget.controller.getTag, ); }, @@ -262,7 +262,7 @@ class _PodVideoPlayerState extends State } else { return _PodCoreVideoPlayer( videoPlayerCtr: _podCtr.videoCtr!, - videoAspectRatio: _videoAspectRatio, + videoAspectRatio: videoAspectRatio, tag: widget.controller.getTag, ); } diff --git a/lib/src/utils/video_apis.dart b/lib/src/utils/video_apis.dart index 13cee8cb..d5507828 100644 --- a/lib/src/utils/video_apis.dart +++ b/lib/src/utils/video_apis.dart @@ -30,15 +30,15 @@ class VideoApis { ) async { try { final response = await _makeRequestHash(videoId, hash); - final jsonData = - jsonDecode(response.body)['request']['files']['progressive']; + final jsonData = jsonDecode(response.body)['request']['files'] + ['progressive'] as List; final progressiveUrls = List.generate( jsonData.length, (index) => VideoQalityUrls( quality: int.parse( (jsonData[index]['quality'] as String?)?.split('p').first ?? '0', ), - url: jsonData[index]['url'], + url: jsonData[index]['url'] as String, ), ); if (progressiveUrls.isEmpty) { @@ -48,7 +48,7 @@ class VideoApis { progressiveUrls.add( VideoQalityUrls( quality: 720, - url: element.value['url'], + url: element.value['url'] as String, ), ); break; @@ -77,7 +77,8 @@ class VideoApis { Uri.parse('https://api.vimeo.com/videos/$videoId'), headers: httpHeader, ); - final jsonData = jsonDecode(response.body)['files']; + final jsonData = + jsonDecode(response.body)['files'] as List; final List list = []; for (int i = 0; i < jsonData.length; i++) { @@ -85,7 +86,12 @@ class VideoApis { (jsonData[i]['rendition'] as String?)?.split('p').first ?? '0'; final int? number = int.tryParse(quality); if (number != null && number != 0) { - list.add(VideoQalityUrls(quality: number, url: jsonData[i]['link'])); + list.add( + VideoQalityUrls( + quality: number, + url: jsonData[i]['link'] as String, + ), + ); } } return list; diff --git a/lib/src/widgets/animated_play_pause_icon.dart b/lib/src/widgets/animated_play_pause_icon.dart index 7c032ccd..0aabdd3a 100644 --- a/lib/src/widgets/animated_play_pause_icon.dart +++ b/lib/src/widgets/animated_play_pause_icon.dart @@ -5,10 +5,9 @@ class _AnimatedPlayPauseIcon extends StatefulWidget { final String tag; const _AnimatedPlayPauseIcon({ - Key? key, - this.size, required this.tag, - }) : super(key: key); + this.size, + }); @override State<_AnimatedPlayPauseIcon> createState() => _AnimatedPlayPauseIconState(); @@ -55,35 +54,35 @@ class _AnimatedPlayPauseIconState extends State<_AnimatedPlayPauseIcon> return GetBuilder( tag: widget.tag, id: 'overlay', - builder: (_podCtr) { + builder: (podCtr) { return GetBuilder( tag: widget.tag, id: 'podVideoState', - builder: (_f) => MaterialIconButton( - toolTipMesg: _f.isvideoPlaying - ? _podCtr.podPlayerLabels.pause ?? + builder: (f) => MaterialIconButton( + toolTipMesg: f.isvideoPlaying + ? podCtr.podPlayerLabels.pause ?? 'Pause${kIsWeb ? ' (space)' : ''}' - : _podCtr.podPlayerLabels.play ?? + : podCtr.podPlayerLabels.play ?? 'Play${kIsWeb ? ' (space)' : ''}', onPressed: - _podCtr.isOverlayVisible ? _podCtr.togglePlayPauseVideo : null, - child: onStateChange(_podCtr), + podCtr.isOverlayVisible ? podCtr.togglePlayPauseVideo : null, + child: onStateChange(podCtr), ), ); }, ); } - Widget onStateChange(PodGetXVideoController _podCtr) { - if (kIsWeb) return _playPause(_podCtr); - if (_podCtr.podVideoState == PodVideoState.loading) { + Widget onStateChange(PodGetXVideoController podCtr) { + if (kIsWeb) return _playPause(podCtr); + if (podCtr.podVideoState == PodVideoState.loading) { return const SizedBox(); } else { - return _playPause(_podCtr); + return _playPause(podCtr); } } - Widget _playPause(PodGetXVideoController _podCtr) { + Widget _playPause(PodGetXVideoController podCtr) { return AnimatedIcon( icon: AnimatedIcons.play_pause, progress: _payCtr, diff --git a/lib/src/widgets/core/overlays/mobile_bottomsheet.dart b/lib/src/widgets/core/overlays/mobile_bottomsheet.dart index 587ec96f..5cf988e9 100644 --- a/lib/src/widgets/core/overlays/mobile_bottomsheet.dart +++ b/lib/src/widgets/core/overlays/mobile_bottomsheet.dart @@ -4,26 +4,25 @@ class _MobileBottomSheet extends StatelessWidget { final String tag; const _MobileBottomSheet({ - Key? key, required this.tag, - }) : super(key: key); + }); @override Widget build(BuildContext context) { return GetBuilder( tag: tag, - builder: (_podCtr) => Column( + builder: (podCtr) => Column( mainAxisSize: MainAxisSize.min, children: [ - if (_podCtr.vimeoOrVideoUrls.isNotEmpty) + if (podCtr.vimeoOrVideoUrls.isNotEmpty) _bottomSheetTiles( - title: _podCtr.podPlayerLabels.quality, + title: podCtr.podPlayerLabels.quality, icon: Icons.video_settings_rounded, - subText: '${_podCtr.vimeoPlayingVideoQuality}p', + subText: '${podCtr.vimeoPlayingVideoQuality}p', onTap: () { Navigator.of(context).pop(); Timer(const Duration(milliseconds: 100), () { - showModalBottomSheet( + showModalBottomSheet( context: context, builder: (context) => SafeArea( child: _VideoQualitySelectorMob( @@ -39,24 +38,24 @@ class _MobileBottomSheet extends StatelessWidget { }, ), _bottomSheetTiles( - title: _podCtr.podPlayerLabels.loopVideo, + title: podCtr.podPlayerLabels.loopVideo, icon: Icons.loop_rounded, - subText: _podCtr.isLooping - ? _podCtr.podPlayerLabels.optionEnabled - : _podCtr.podPlayerLabels.optionDisabled, + subText: podCtr.isLooping + ? podCtr.podPlayerLabels.optionEnabled + : podCtr.podPlayerLabels.optionDisabled, onTap: () { Navigator.of(context).pop(); - _podCtr.toggleLooping(); + podCtr.toggleLooping(); }, ), _bottomSheetTiles( - title: _podCtr.podPlayerLabels.playbackSpeed, + title: podCtr.podPlayerLabels.playbackSpeed, icon: Icons.slow_motion_video_rounded, - subText: _podCtr.currentPaybackSpeed, + subText: podCtr.currentPaybackSpeed, onTap: () { Navigator.of(context).pop(); Timer(const Duration(milliseconds: 100), () { - showModalBottomSheet( + showModalBottomSheet( context: context, isScrollControlled: true, builder: (context) => SafeArea( @@ -121,25 +120,24 @@ class _VideoQualitySelectorMob extends StatelessWidget { final String tag; const _VideoQualitySelectorMob({ - Key? key, required this.onTap, required this.tag, - }) : super(key: key); + }); @override Widget build(BuildContext context) { - final _podCtr = Get.find(tag: tag); + final podCtr = Get.find(tag: tag); return SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, - children: _podCtr.vimeoOrVideoUrls + children: podCtr.vimeoOrVideoUrls .map( (e) => ListTile( title: Text('${e.quality}p'), onTap: () { onTap != null ? onTap!() : Navigator.of(context).pop(); - _podCtr.changeVideoQuality(e.quality); + podCtr.changeVideoQuality(e.quality); }, ), ) @@ -154,24 +152,23 @@ class _VideoPlaybackSelectorMob extends StatelessWidget { final String tag; const _VideoPlaybackSelectorMob({ - Key? key, required this.onTap, required this.tag, - }) : super(key: key); + }); @override Widget build(BuildContext context) { - final _podCtr = Get.find(tag: tag); + final podCtr = Get.find(tag: tag); return SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, - children: _podCtr.videoPlaybackSpeeds + children: podCtr.videoPlaybackSpeeds .map( (e) => ListTile( title: Text(e), onTap: () { onTap != null ? onTap!() : Navigator.of(context).pop(); - _podCtr.setVideoPlayBack(e); + podCtr.setVideoPlayBack(e); }, ), ) @@ -185,9 +182,8 @@ class _MobileOverlayBottomControlles extends StatelessWidget { final String tag; const _MobileOverlayBottomControlles({ - Key? key, required this.tag, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -197,7 +193,7 @@ class _MobileOverlayBottomControlles extends StatelessWidget { return GetBuilder( tag: tag, id: 'full-screen', - builder: (_podCtr) => Column( + builder: (podCtr) => Column( mainAxisSize: MainAxisSize.min, children: [ Row( @@ -206,11 +202,11 @@ class _MobileOverlayBottomControlles extends StatelessWidget { GetBuilder( tag: tag, id: 'video-progress', - builder: (_podCtr) { + builder: (podCtr) { return Row( children: [ Text( - _podCtr.calculateVideoDuration(_podCtr.videoPosition), + podCtr.calculateVideoDuration(podCtr.videoPosition), style: const TextStyle(color: itemColor), ), const Text( @@ -218,7 +214,7 @@ class _MobileOverlayBottomControlles extends StatelessWidget { style: durationTextStyle, ), Text( - _podCtr.calculateVideoDuration(_podCtr.videoDuration), + podCtr.calculateVideoDuration(podCtr.videoDuration), style: durationTextStyle, ), ], @@ -227,25 +223,25 @@ class _MobileOverlayBottomControlles extends StatelessWidget { ), const Spacer(), MaterialIconButton( - toolTipMesg: _podCtr.isFullScreen - ? _podCtr.podPlayerLabels.exitFullScreen ?? + toolTipMesg: podCtr.isFullScreen + ? podCtr.podPlayerLabels.exitFullScreen ?? 'Exit full screen${kIsWeb ? ' (f)' : ''}' - : _podCtr.podPlayerLabels.fullscreen ?? + : podCtr.podPlayerLabels.fullscreen ?? 'Fullscreen${kIsWeb ? ' (f)' : ''}', color: itemColor, onPressed: () { - if (_podCtr.isOverlayVisible) { - if (_podCtr.isFullScreen) { - _podCtr.disableFullScreen(context, tag); + if (podCtr.isOverlayVisible) { + if (podCtr.isFullScreen) { + podCtr.disableFullScreen(context, tag); } else { - _podCtr.enableFullScreen(tag); + podCtr.enableFullScreen(tag); } } else { - _podCtr.toggleVideoOverlay(); + podCtr.toggleVideoOverlay(); } }, child: Icon( - _podCtr.isFullScreen + podCtr.isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen, ), @@ -255,16 +251,16 @@ class _MobileOverlayBottomControlles extends StatelessWidget { GetBuilder( tag: tag, id: 'overlay', - builder: (_podCtr) { - if (_podCtr.isFullScreen) { + builder: (podCtr) { + if (podCtr.isFullScreen) { return Padding( padding: const EdgeInsets.fromLTRB(12, 0, 12, 20), child: Visibility( - visible: _podCtr.isOverlayVisible, + visible: podCtr.isOverlayVisible, child: PodProgressBar( tag: tag, alignment: Alignment.topCenter, - podProgressBarConfig: _podCtr.podProgressBarConfig, + podProgressBarConfig: podCtr.podProgressBarConfig, ), ), ); @@ -272,7 +268,7 @@ class _MobileOverlayBottomControlles extends StatelessWidget { return PodProgressBar( tag: tag, alignment: Alignment.bottomCenter, - podProgressBarConfig: _podCtr.podProgressBarConfig, + podProgressBarConfig: podCtr.podProgressBarConfig, ); }, ), diff --git a/lib/src/widgets/core/overlays/mobile_overlay.dart b/lib/src/widgets/core/overlays/mobile_overlay.dart index 2d4f713d..1afe558d 100644 --- a/lib/src/widgets/core/overlays/mobile_overlay.dart +++ b/lib/src/widgets/core/overlays/mobile_overlay.dart @@ -4,15 +4,14 @@ class _MobileOverlay extends StatelessWidget { final String tag; const _MobileOverlay({ - Key? key, required this.tag, - }) : super(key: key); + }); @override Widget build(BuildContext context) { const overlayColor = Colors.black38; const itemColor = Colors.white; - final _podCtr = Get.find(tag: tag); + final podCtr = Get.find(tag: tag); return Stack( alignment: Alignment.center, children: [ @@ -28,8 +27,8 @@ class _MobileOverlay extends StatelessWidget { isForward: false, height: double.maxFinite, onDoubleTap: _isRtl() - ? _podCtr.onRightDoubleTap - : _podCtr.onLeftDoubleTap, + ? podCtr.onRightDoubleTap + : podCtr.onLeftDoubleTap, ), ), SizedBox( @@ -44,8 +43,8 @@ class _MobileOverlay extends StatelessWidget { tag: tag, height: double.maxFinite, onDoubleTap: _isRtl() - ? _podCtr.onLeftDoubleTap - : _podCtr.onRightDoubleTap, + ? podCtr.onLeftDoubleTap + : podCtr.onRightDoubleTap, ), ), ], @@ -59,17 +58,17 @@ class _MobileOverlay extends StatelessWidget { children: [ Expanded( child: IgnorePointer( - child: _podCtr.videoTitle ?? const SizedBox(), + child: podCtr.videoTitle ?? const SizedBox(), ), ), MaterialIconButton( - toolTipMesg: _podCtr.podPlayerLabels.settings, + toolTipMesg: podCtr.podPlayerLabels.settings, color: itemColor, onPressed: () { - if (_podCtr.isOverlayVisible) { + if (podCtr.isOverlayVisible) { _bottomSheet(context); } else { - _podCtr.toggleVideoOverlay(); + podCtr.toggleVideoOverlay(); } }, child: const Icon( @@ -106,7 +105,7 @@ class _MobileOverlay extends StatelessWidget { } void _bottomSheet(BuildContext context) { - showModalBottomSheet( + showModalBottomSheet( context: context, builder: (context) => SafeArea(child: _MobileBottomSheet(tag: tag)), ); diff --git a/lib/src/widgets/core/overlays/overlays.dart b/lib/src/widgets/core/overlays/overlays.dart index ae0bbdf5..d634c609 100644 --- a/lib/src/widgets/core/overlays/overlays.dart +++ b/lib/src/widgets/core/overlays/overlays.dart @@ -4,41 +4,40 @@ class _VideoOverlays extends StatelessWidget { final String tag; const _VideoOverlays({ - Key? key, required this.tag, - }) : super(key: key); + }); @override Widget build(BuildContext context) { - final _podCtr = Get.find(tag: tag); - if (_podCtr.overlayBuilder != null) { + final podCtr = Get.find(tag: tag); + if (podCtr.overlayBuilder != null) { return GetBuilder( id: 'update-all', tag: tag, - builder: (_podCtr) { + builder: (podCtr) { ///Custom overlay - final _progressBar = PodProgressBar( + final progressBar = PodProgressBar( tag: tag, - podProgressBarConfig: _podCtr.podProgressBarConfig, + podProgressBarConfig: podCtr.podProgressBarConfig, ); final overlayOptions = OverLayOptions( - podVideoState: _podCtr.podVideoState, - videoDuration: _podCtr.videoDuration, - videoPosition: _podCtr.videoPosition, - isFullScreen: _podCtr.isFullScreen, - isLooping: _podCtr.isLooping, - isOverlayVisible: _podCtr.isOverlayVisible, - isMute: _podCtr.isMute, - autoPlay: _podCtr.autoPlay, - currentVideoPlaybackSpeed: _podCtr.currentPaybackSpeed, - videoPlayBackSpeeds: _podCtr.videoPlaybackSpeeds, - videoPlayerType: _podCtr.videoPlayerType, - podProgresssBar: _progressBar, + podVideoState: podCtr.podVideoState, + videoDuration: podCtr.videoDuration, + videoPosition: podCtr.videoPosition, + isFullScreen: podCtr.isFullScreen, + isLooping: podCtr.isLooping, + isOverlayVisible: podCtr.isOverlayVisible, + isMute: podCtr.isMute, + autoPlay: podCtr.autoPlay, + currentVideoPlaybackSpeed: podCtr.currentPaybackSpeed, + videoPlayBackSpeeds: podCtr.videoPlaybackSpeeds, + videoPlayerType: podCtr.videoPlayerType, + podProgresssBar: progressBar, ); /// Returns the custom overlay, otherwise returns the default /// overlay with gesture detector - return _podCtr.overlayBuilder!(overlayOptions); + return podCtr.overlayBuilder!(overlayOptions); }, ); } else { @@ -46,10 +45,10 @@ class _VideoOverlays extends StatelessWidget { return GetBuilder( tag: tag, id: 'overlay', - builder: (_podCtr) { + builder: (podCtr) { return AnimatedOpacity( duration: const Duration(milliseconds: 200), - opacity: _podCtr.isOverlayVisible ? 1 : 0, + opacity: podCtr.isOverlayVisible ? 1 : 0, child: Stack( fit: StackFit.passthrough, children: [ diff --git a/lib/src/widgets/core/overlays/web_dropdown_menu.dart b/lib/src/widgets/core/overlays/web_dropdown_menu.dart index 6faee487..78965f89 100644 --- a/lib/src/widgets/core/overlays/web_dropdown_menu.dart +++ b/lib/src/widgets/core/overlays/web_dropdown_menu.dart @@ -4,9 +4,8 @@ class _WebSettingsDropdown extends StatefulWidget { final String tag; const _WebSettingsDropdown({ - Key? key, required this.tag, - }) : super(key: key); + }); @override State<_WebSettingsDropdown> createState() => _WebSettingsDropdownState(); @@ -21,43 +20,43 @@ class _WebSettingsDropdownState extends State<_WebSettingsDropdown> { ), child: GetBuilder( tag: widget.tag, - builder: (_podCtr) { + builder: (podCtr) { return MaterialIconButton( - toolTipMesg: _podCtr.podPlayerLabels.settings, + toolTipMesg: podCtr.podPlayerLabels.settings, color: Colors.white, child: const Icon(Icons.settings), - onPressed: () => _podCtr.isFullScreen - ? _podCtr.isWebPopupOverlayOpen = true - : _podCtr.isWebPopupOverlayOpen = false, + onPressed: () => podCtr.isFullScreen + ? podCtr.isWebPopupOverlayOpen = true + : podCtr.isWebPopupOverlayOpen = false, onTapDown: (details) async { - final _settingsMenu = await showMenu( + final settingsMenu = await showMenu( context: context, items: [ - if (_podCtr.vimeoOrVideoUrls.isNotEmpty) + if (podCtr.vimeoOrVideoUrls.isNotEmpty) PopupMenuItem( value: 'OUALITY', child: _bottomSheetTiles( - title: _podCtr.podPlayerLabels.quality, + title: podCtr.podPlayerLabels.quality, icon: Icons.video_settings_rounded, - subText: '${_podCtr.vimeoPlayingVideoQuality}p', + subText: '${podCtr.vimeoPlayingVideoQuality}p', ), ), PopupMenuItem( value: 'LOOP', child: _bottomSheetTiles( - title: _podCtr.podPlayerLabels.loopVideo, + title: podCtr.podPlayerLabels.loopVideo, icon: Icons.loop_rounded, - subText: _podCtr.isLooping - ? _podCtr.podPlayerLabels.optionEnabled - : _podCtr.podPlayerLabels.optionDisabled, + subText: podCtr.isLooping + ? podCtr.podPlayerLabels.optionEnabled + : podCtr.podPlayerLabels.optionDisabled, ), ), PopupMenuItem( value: 'SPEED', child: _bottomSheetTiles( - title: _podCtr.podPlayerLabels.playbackSpeed, + title: podCtr.podPlayerLabels.playbackSpeed, icon: Icons.slow_motion_video_rounded, - subText: _podCtr.currentPaybackSpeed, + subText: podCtr.currentPaybackSpeed, ), ), ], @@ -66,19 +65,19 @@ class _WebSettingsDropdownState extends State<_WebSettingsDropdown> { MediaQuery.of(context).size, ), ); - switch (_settingsMenu) { + switch (settingsMenu) { case 'OUALITY': - await _onVimeoQualitySelect(details, _podCtr); + await _onVimeoQualitySelect(details, podCtr); break; case 'SPEED': - await _onPlaybackSpeedSelect(details, _podCtr); + await _onPlaybackSpeedSelect(details, podCtr); break; case 'LOOP': - _podCtr.isWebPopupOverlayOpen = false; - await _podCtr.toggleLooping(); + podCtr.isWebPopupOverlayOpen = false; + await podCtr.toggleLooping(); break; default: - _podCtr.isWebPopupOverlayOpen = false; + podCtr.isWebPopupOverlayOpen = false; } }, ); @@ -89,21 +88,21 @@ class _WebSettingsDropdownState extends State<_WebSettingsDropdown> { Future _onPlaybackSpeedSelect( TapDownDetails details, - PodGetXVideoController _podCtr, + PodGetXVideoController podCtr, ) async { - await Future.delayed( + await Future.delayed( const Duration(milliseconds: 400), ); await showMenu( context: context, - items: _podCtr.videoPlaybackSpeeds + items: podCtr.videoPlaybackSpeeds .map( - (e) => PopupMenuItem( + (e) => PopupMenuItem( child: ListTile( title: Text(e), ), onTap: () { - _podCtr.setVideoPlayBack(e); + podCtr.setVideoPlayBack(e); }, ), ) @@ -114,26 +113,26 @@ class _WebSettingsDropdownState extends State<_WebSettingsDropdown> { MediaQuery.of(context).size, ), ); - _podCtr.isWebPopupOverlayOpen = false; + podCtr.isWebPopupOverlayOpen = false; } Future _onVimeoQualitySelect( TapDownDetails details, - PodGetXVideoController _podCtr, + PodGetXVideoController podCtr, ) async { - await Future.delayed( + await Future.delayed( const Duration(milliseconds: 400), ); await showMenu( context: context, - items: _podCtr.vimeoOrVideoUrls + items: podCtr.vimeoOrVideoUrls .map( - (e) => PopupMenuItem( + (e) => PopupMenuItem( child: ListTile( title: Text('${e.quality}p'), ), onTap: () { - _podCtr.changeVideoQuality( + podCtr.changeVideoQuality( e.quality, ); }, @@ -146,7 +145,7 @@ class _WebSettingsDropdownState extends State<_WebSettingsDropdown> { MediaQuery.of(context).size, ), ); - _podCtr.isWebPopupOverlayOpen = false; + podCtr.isWebPopupOverlayOpen = false; } Widget _bottomSheetTiles({ diff --git a/lib/src/widgets/core/overlays/web_overlay.dart b/lib/src/widgets/core/overlays/web_overlay.dart index 508aab34..3371b2fc 100644 --- a/lib/src/widgets/core/overlays/web_overlay.dart +++ b/lib/src/widgets/core/overlays/web_overlay.dart @@ -3,21 +3,20 @@ part of 'package:pod_player/src/pod_player.dart'; class _WebOverlay extends StatelessWidget { final String tag; const _WebOverlay({ - Key? key, required this.tag, - }) : super(key: key); + }); @override Widget build(BuildContext context) { const overlayColor = Colors.black38; - final _podCtr = Get.find(tag: tag); + final podCtr = Get.find(tag: tag); return Stack( children: [ Positioned.fill( child: _VideoGestureDetector( tag: tag, - onTap: _podCtr.togglePlayPauseVideo, - onDoubleTap: () => _podCtr.toggleFullScreenOnWeb(context, tag), + onTap: podCtr.togglePlayPauseVideo, + onDoubleTap: () => podCtr.toggleFullScreenOnWeb(context, tag), child: const ColoredBox( color: overlayColor, child: SizedBox.expand(), @@ -34,7 +33,7 @@ class _WebOverlay extends StatelessWidget { child: GetBuilder( tag: tag, id: 'double-tap', - builder: (_podCtr) { + builder: (podCtr) { return Row( children: [ Expanded( @@ -62,7 +61,7 @@ class _WebOverlay extends StatelessWidget { }, ), ), - IgnorePointer(child: _podCtr.videoTitle ?? const SizedBox()), + IgnorePointer(child: podCtr.videoTitle ?? const SizedBox()), ], ); } @@ -72,19 +71,18 @@ class _WebOverlayBottomControlles extends StatelessWidget { final String tag; const _WebOverlayBottomControlles({ - Key? key, required this.tag, - }) : super(key: key); + }); @override Widget build(BuildContext context) { - final _podCtr = Get.find(tag: tag); + final podCtr = Get.find(tag: tag); const durationTextStyle = TextStyle(color: Colors.white70); const itemColor = Colors.white; return MouseRegion( - onHover: (event) => _podCtr.onOverlayHover(), - onExit: (event) => _podCtr.onOverlayHoverExit(), + onHover: (event) => podCtr.onOverlayHover(), + onExit: (event) => podCtr.onOverlayHoverExit(), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Column( @@ -92,7 +90,7 @@ class _WebOverlayBottomControlles extends StatelessWidget { children: [ PodProgressBar( tag: tag, - podProgressBarConfig: _podCtr.podProgressBarConfig, + podProgressBarConfig: podCtr.podProgressBarConfig, ), Row( children: [ @@ -107,16 +105,16 @@ class _WebOverlayBottomControlles extends StatelessWidget { GetBuilder( tag: tag, id: 'volume', - builder: (_podCtr) => MaterialIconButton( - toolTipMesg: _podCtr.isMute - ? _podCtr.podPlayerLabels.unmute ?? + builder: (podCtr) => MaterialIconButton( + toolTipMesg: podCtr.isMute + ? podCtr.podPlayerLabels.unmute ?? 'Unmute${kIsWeb ? ' (m)' : ''}' - : _podCtr.podPlayerLabels.mute ?? + : podCtr.podPlayerLabels.mute ?? 'Mute${kIsWeb ? ' (m)' : ''}', color: itemColor, - onPressed: _podCtr.toggleMute, + onPressed: podCtr.toggleMute, child: Icon( - _podCtr.isMute + podCtr.isMute ? Icons.volume_off_rounded : Icons.volume_up_rounded, ), @@ -125,12 +123,12 @@ class _WebOverlayBottomControlles extends StatelessWidget { GetBuilder( tag: tag, id: 'video-progress', - builder: (_podCtr) { + builder: (podCtr) { return Row( children: [ Text( - _podCtr.calculateVideoDuration( - _podCtr.videoPosition, + podCtr.calculateVideoDuration( + podCtr.videoPosition, ), style: durationTextStyle, ), @@ -139,8 +137,8 @@ class _WebOverlayBottomControlles extends StatelessWidget { style: durationTextStyle, ), Text( - _podCtr.calculateVideoDuration( - _podCtr.videoDuration, + podCtr.calculateVideoDuration( + podCtr.videoDuration, ), style: durationTextStyle, ), @@ -161,16 +159,15 @@ class _WebOverlayBottomControlles extends StatelessWidget { children: [ _WebSettingsDropdown(tag: tag), MaterialIconButton( - toolTipMesg: _podCtr.isFullScreen - ? _podCtr.podPlayerLabels.exitFullScreen ?? + toolTipMesg: podCtr.isFullScreen + ? podCtr.podPlayerLabels.exitFullScreen ?? 'Exit full screen${kIsWeb ? ' (f)' : ''}' - : _podCtr.podPlayerLabels.fullscreen ?? + : podCtr.podPlayerLabels.fullscreen ?? 'Fullscreen${kIsWeb ? ' (f)' : ''}', color: itemColor, - onPressed: () => - _onFullScreenToggle(_podCtr, context), + onPressed: () => _onFullScreenToggle(podCtr, context), child: Icon( - _podCtr.isFullScreen + podCtr.isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen, ), @@ -188,29 +185,29 @@ class _WebOverlayBottomControlles extends StatelessWidget { } void _onFullScreenToggle( - PodGetXVideoController _podCtr, + PodGetXVideoController podCtr, BuildContext context, ) { - if (_podCtr.isOverlayVisible) { - if (_podCtr.isFullScreen) { + if (podCtr.isOverlayVisible) { + if (podCtr.isFullScreen) { if (kIsWeb) { - _html.document.exitFullscreen(); - _podCtr.disableFullScreen(context, tag); + uni_html.document.exitFullscreen(); + podCtr.disableFullScreen(context, tag); return; } else { - _podCtr.disableFullScreen(context, tag); + podCtr.disableFullScreen(context, tag); } } else { if (kIsWeb) { - _html.document.documentElement?.requestFullscreen(); - _podCtr.enableFullScreen(tag); + uni_html.document.documentElement?.requestFullscreen(); + podCtr.enableFullScreen(tag); return; } else { - _podCtr.enableFullScreen(tag); + podCtr.enableFullScreen(tag); } } } else { - _podCtr.toggleVideoOverlay(); + podCtr.toggleVideoOverlay(); } } } diff --git a/lib/src/widgets/core/pod_core_player.dart b/lib/src/widgets/core/pod_core_player.dart index a40ffa22..7a7a3e47 100644 --- a/lib/src/widgets/core/pod_core_player.dart +++ b/lib/src/widgets/core/pod_core_player.dart @@ -6,25 +6,24 @@ class _PodCoreVideoPlayer extends StatelessWidget { final String tag; const _PodCoreVideoPlayer({ - Key? key, required this.videoPlayerCtr, required this.videoAspectRatio, required this.tag, - }) : super(key: key); + }); @override Widget build(BuildContext context) { - final _podCtr = Get.find(tag: tag); + final podCtr = Get.find(tag: tag); return Builder( - builder: (_ctrx) { + builder: (ctrx) { return RawKeyboardListener( autofocus: true, focusNode: - (_podCtr.isFullScreen ? FocusNode() : _podCtr.keyboardFocusWeb) ?? + (podCtr.isFullScreen ? FocusNode() : podCtr.keyboardFocusWeb) ?? FocusNode(), - onKey: (value) => _podCtr.onKeyBoardEvents( + onKey: (value) => podCtr.onKeyBoardEvents( event: value, - appContext: _ctrx, + appContext: ctrx, tag: tag, ), child: Stack( @@ -42,13 +41,13 @@ class _PodCoreVideoPlayer extends StatelessWidget { builder: (_) => GetBuilder( tag: tag, id: 'video-progress', - builder: (_podCtr) { - if (_podCtr.videoThumbnail == null) { + builder: (podCtr) { + if (podCtr.videoThumbnail == null) { return const SizedBox(); } - if (_podCtr.podVideoState == PodVideoState.paused && - _podCtr.videoPosition == Duration.zero) { + if (podCtr.podVideoState == PodVideoState.paused && + podCtr.videoPosition == Duration.zero) { return SizedBox.expand( child: TweenAnimationBuilder( builder: (context, value, child) => Opacity( @@ -59,7 +58,7 @@ class _PodCoreVideoPlayer extends StatelessWidget { duration: const Duration(milliseconds: 400), child: DecoratedBox( decoration: BoxDecoration( - image: _podCtr.videoThumbnail, + image: podCtr.videoThumbnail, ), ), ), @@ -74,8 +73,8 @@ class _PodCoreVideoPlayer extends StatelessWidget { child: GetBuilder( tag: tag, id: 'podVideoState', - builder: (_podCtr) { - final loadingWidget = _podCtr.onLoading?.call(context) ?? + builder: (podCtr) { + final loadingWidget = podCtr.onLoading?.call(context) ?? const Center( child: CircularProgressIndicator( backgroundColor: Colors.transparent, @@ -85,7 +84,7 @@ class _PodCoreVideoPlayer extends StatelessWidget { ); if (kIsWeb) { - switch (_podCtr.podVideoState) { + switch (podCtr.podVideoState) { case PodVideoState.loading: return loadingWidget; case PodVideoState.paused: @@ -116,7 +115,7 @@ class _PodCoreVideoPlayer extends StatelessWidget { return const SizedBox(); } } else { - if (_podCtr.podVideoState == PodVideoState.loading) { + if (podCtr.podVideoState == PodVideoState.loading) { return loadingWidget; } return const SizedBox(); @@ -128,13 +127,13 @@ class _PodCoreVideoPlayer extends StatelessWidget { GetBuilder( tag: tag, id: 'full-screen', - builder: (_podCtr) => _podCtr.isFullScreen + builder: (podCtr) => podCtr.isFullScreen ? const SizedBox() : GetBuilder( tag: tag, id: 'overlay', - builder: (_podCtr) => _podCtr.isOverlayVisible || - !_podCtr.alwaysShowProgressBar + builder: (podCtr) => podCtr.isOverlayVisible || + !podCtr.alwaysShowProgressBar ? const SizedBox() : Align( alignment: Alignment.bottomCenter, @@ -142,7 +141,7 @@ class _PodCoreVideoPlayer extends StatelessWidget { tag: tag, alignment: Alignment.bottomCenter, podProgressBarConfig: - _podCtr.podProgressBarConfig, + podCtr.podProgressBarConfig, ), ), ), diff --git a/lib/src/widgets/core/video_gesture_detector.dart b/lib/src/widgets/core/video_gesture_detector.dart index a6bf30f0..763582e5 100644 --- a/lib/src/widgets/core/video_gesture_detector.dart +++ b/lib/src/widgets/core/video_gesture_detector.dart @@ -7,21 +7,20 @@ class _VideoGestureDetector extends StatelessWidget { final String tag; const _VideoGestureDetector({ - Key? key, + required this.tag, this.child, this.onDoubleTap, this.onTap, - required this.tag, - }) : super(key: key); + }); @override Widget build(BuildContext context) { - final _podCtr = Get.find(tag: tag); + final podCtr = Get.find(tag: tag); return MouseRegion( - onHover: (event) => _podCtr.onOverlayHover(), - onExit: (event) => _podCtr.onOverlayHoverExit(), + onHover: (event) => podCtr.onOverlayHover(), + onExit: (event) => podCtr.onOverlayHoverExit(), child: GestureDetector( - onTap: onTap ?? _podCtr.toggleVideoOverlay, + onTap: onTap ?? podCtr.toggleVideoOverlay, onDoubleTap: onDoubleTap, child: child, ), diff --git a/lib/src/widgets/doubble_tap_effect.dart b/lib/src/widgets/doubble_tap_effect.dart index e68370e6..f23915f9 100644 --- a/lib/src/widgets/doubble_tap_effect.dart +++ b/lib/src/widgets/doubble_tap_effect.dart @@ -32,7 +32,7 @@ class DoubleTapRippleEffect extends StatefulWidget { final double? height; const DoubleTapRippleEffect({ - Key? key, + super.key, this.child, this.wrapper, this.rippleColor, @@ -43,7 +43,7 @@ class DoubleTapRippleEffect extends StatefulWidget { this.onDoubleTap, this.width, this.height, - }) : super(key: key); + }); @override State createState() => _DoubleTapRippleEffectState(); @@ -105,7 +105,7 @@ class _DoubleTapRippleEffectState extends State // checking animation status is completed void _animStatus() { if (_anim.status == AnimationStatus.completed) { - Future.delayed( + Future.delayed( widget.rippleEndingDuraiton ?? const Duration(milliseconds: 600), ).then((value) { setState(() { diff --git a/lib/src/widgets/double_tap_icon.dart b/lib/src/widgets/double_tap_icon.dart index 2f2ae9ee..1875e920 100644 --- a/lib/src/widgets/double_tap_icon.dart +++ b/lib/src/widgets/double_tap_icon.dart @@ -13,14 +13,14 @@ class DoubleTapIcon extends StatefulWidget { final double? width; const DoubleTapIcon({ - Key? key, required this.onDoubleTap, required this.tag, - this.iconOnly = false, required this.isForward, + super.key, + this.iconOnly = false, this.height = 50, this.width, - }) : super(key: key); + }); @override State createState() => _DoubleTapIconState(); @@ -146,13 +146,13 @@ class _DoubleTapIconState extends State GetBuilder( tag: widget.tag, id: 'double-tap', - builder: (_podCtr) { - if (widget.isForward && _podCtr.isRightDbTapIconVisible) { + builder: (podCtr) { + if (widget.isForward && podCtr.isRightDbTapIconVisible) { return AnimatedOpacity( duration: const Duration(milliseconds: 300), opacity: opacityCtr.value, child: Text( - '${_podCtr.isLeftDbTapIconVisible ? _podCtr.leftDoubleTapduration : _podCtr.rightDubleTapduration} Sec', + '${podCtr.isLeftDbTapIconVisible ? podCtr.leftDoubleTapduration : podCtr.rightDubleTapduration} Sec', style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, @@ -160,12 +160,12 @@ class _DoubleTapIconState extends State ), ); } - if (!widget.isForward && _podCtr.isLeftDbTapIconVisible) { + if (!widget.isForward && podCtr.isLeftDbTapIconVisible) { return AnimatedOpacity( duration: const Duration(milliseconds: 300), opacity: opacityCtr.value, child: Text( - '${_podCtr.isLeftDbTapIconVisible ? _podCtr.leftDoubleTapduration : _podCtr.rightDubleTapduration} Sec', + '${podCtr.isLeftDbTapIconVisible ? podCtr.leftDoubleTapduration : podCtr.rightDubleTapduration} Sec', style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, diff --git a/lib/src/widgets/full_screen_view.dart b/lib/src/widgets/full_screen_view.dart index 98021ae0..e26501ac 100644 --- a/lib/src/widgets/full_screen_view.dart +++ b/lib/src/widgets/full_screen_view.dart @@ -3,9 +3,9 @@ part of 'package:pod_player/src/pod_player.dart'; class FullScreenView extends StatefulWidget { final String tag; const FullScreenView({ - Key? key, required this.tag, - }) : super(key: key); + super.key, + }); @override State createState() => _FullScreenViewState(); @@ -55,21 +55,21 @@ class _FullScreenViewState extends State backgroundColor: Colors.black, body: GetBuilder( tag: widget.tag, - builder: (_podCtr) => Center( + builder: (podCtr) => Center( child: ColoredBox( color: Colors.black, child: SizedBox( height: MediaQuery.of(context).size.height, width: MediaQuery.of(context).size.width, child: Center( - child: _podCtr.videoCtr == null + child: podCtr.videoCtr == null ? loadingWidget - : _podCtr.videoCtr!.value.isInitialized + : podCtr.videoCtr!.value.isInitialized ? _PodCoreVideoPlayer( tag: widget.tag, - videoPlayerCtr: _podCtr.videoCtr!, + videoPlayerCtr: podCtr.videoCtr!, videoAspectRatio: - _podCtr.videoCtr?.value.aspectRatio ?? 16 / 9, + podCtr.videoCtr?.value.aspectRatio ?? 16 / 9, ) : loadingWidget, ), diff --git a/lib/src/widgets/material_icon_button.dart b/lib/src/widgets/material_icon_button.dart index e80734d2..6dccb2c1 100644 --- a/lib/src/widgets/material_icon_button.dart +++ b/lib/src/widgets/material_icon_button.dart @@ -2,15 +2,15 @@ import 'package:flutter/material.dart'; class MaterialIconButton extends StatelessWidget { const MaterialIconButton({ - Key? key, - this.color, required this.child, - this.radius = 12, required this.toolTipMesg, + super.key, + this.color, + this.radius = 12, this.onPressed, this.onHover, this.onTapDown, - }) : super(key: key); + }); final Color? color; final Widget child; diff --git a/lib/src/widgets/pod_progress_bar.dart b/lib/src/widgets/pod_progress_bar.dart index 7706f61b..855180cd 100644 --- a/lib/src/widgets/pod_progress_bar.dart +++ b/lib/src/widgets/pod_progress_bar.dart @@ -9,21 +9,20 @@ import '../models/pod_progress_bar_config.dart'; /// Renders progress bar for the video using custom paint. class PodProgressBar extends StatefulWidget { const PodProgressBar({ - Key? key, + required this.tag, + super.key, PodProgressBarConfig? podProgressBarConfig, this.onDragStart, this.onDragEnd, this.onDragUpdate, this.alignment = Alignment.center, - required this.tag, - }) : podProgressBarConfig = - podProgressBarConfig ?? const PodProgressBarConfig(), - super(key: key); + }) : podProgressBarConfig = + podProgressBarConfig ?? const PodProgressBarConfig(); final PodProgressBarConfig podProgressBarConfig; - final Function()? onDragStart; - final Function()? onDragEnd; - final Function()? onDragUpdate; + final void Function()? onDragStart; + final void Function()? onDragEnd; + final void Function()? onDragUpdate; final Alignment alignment; final String tag; @@ -54,8 +53,8 @@ class _PodProgressBarState extends State { return GetBuilder( tag: widget.tag, id: 'video-progress', - builder: (_podCtr) { - videoPlayerValue = _podCtr.videoCtr?.value; + builder: (podCtr) { + videoPlayerValue = podCtr.videoCtr?.value; return LayoutBuilder( builder: (context, size) { return GestureDetector( @@ -66,9 +65,9 @@ class _PodProgressBarState extends State { return; } _controllerWasPlaying = - _podCtr.videoCtr?.value.isPlaying ?? false; + podCtr.videoCtr?.value.isPlaying ?? false; if (_controllerWasPlaying) { - _podCtr.videoCtr?.pause(); + podCtr.videoCtr?.pause(); } if (widget.onDragStart != null) { @@ -79,16 +78,16 @@ class _PodProgressBarState extends State { if (!videoPlayerValue!.isInitialized) { return; } - _podCtr.isShowOverlay(true); + podCtr.isShowOverlay(true); seekToRelativePosition(details.globalPosition); widget.onDragUpdate?.call(); }, onHorizontalDragEnd: (DragEndDetails details) { if (_controllerWasPlaying) { - _podCtr.videoCtr?.play(); + podCtr.videoCtr?.play(); } - _podCtr.toggleVideoOverlay(); + podCtr.toggleVideoOverlay(); if (widget.onDragEnd != null) { widget.onDragEnd?.call(); @@ -120,11 +119,11 @@ class _PodProgressBarState extends State { child: GetBuilder( tag: widget.tag, id: 'overlay', - builder: (_podCtr) => CustomPaint( + builder: (podCtr) => CustomPaint( painter: _ProgressBarPainter( videoPlayerValue!, podProgressBarConfig: widget.podProgressBarConfig.copyWith( - circleHandlerRadius: _podCtr.isOverlayVisible || + circleHandlerRadius: podCtr.isOverlayVisible || widget .podProgressBarConfig.alwaysVisibleCircleHandler ? widget.podProgressBarConfig.circleHandlerRadius diff --git a/pubspec.yaml b/pubspec.yaml index 2673138d..e6c446c0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,16 +11,16 @@ dependencies: flutter: sdk: flutter # services - video_player: ^2.6.1 + video_player: ^2.7.0 http: ^0.13.6 get: ^4.6.5 - wakelock_plus: ^1.0.0+3 + wakelock_plus: ^1.1.0 universal_html: ^2.2.3 youtube_explode_dart: ^1.12.4 dev_dependencies: flutter_test: sdk: flutter - very_good_analysis: ^2.4.0 + very_good_analysis: ^5.0.0+1 screenshots: - description: Pod video player logo From 595e9ebb6aa1909808a3055cae90e2d59a7cd5ad Mon Sep 17 00:00:00 2001 From: newtaDev Date: Sat, 8 Jul 2023 12:10:30 +0530 Subject: [PATCH 16/24] fix: lint and formating --- .github/workflows/ci.yml | 2 +- lib/src/utils/video_apis.dart | 3 +-- pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2090a0d4..38a1c9bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - name: Check format - run: flutter format --set-exit-if-changed . + run: dart format --set-exit-if-changed . lint: name: Check lints diff --git a/lib/src/utils/video_apis.dart b/lib/src/utils/video_apis.dart index d5507828..3dfca8f5 100644 --- a/lib/src/utils/video_apis.dart +++ b/lib/src/utils/video_apis.dart @@ -77,8 +77,7 @@ class VideoApis { Uri.parse('https://api.vimeo.com/videos/$videoId'), headers: httpHeader, ); - final jsonData = - jsonDecode(response.body)['files'] as List; + final jsonData = jsonDecode(response.body)['files'] as List; final List list = []; for (int i = 0; i < jsonData.length; i++) { diff --git a/pubspec.yaml b/pubspec.yaml index e6c446c0..62eab3a4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,7 +20,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - very_good_analysis: ^5.0.0+1 + very_good_analysis: ^4.0.0+1 screenshots: - description: Pod video player logo From e1fb768b9614127652bb766e99907b2f6fa9507e Mon Sep 17 00:00:00 2001 From: newtaDev Date: Sat, 8 Jul 2023 12:24:54 +0530 Subject: [PATCH 17/24] =?UTF-8?q?=F0=9F=9A=80=20pub=20-v=200.2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 7 +++++++ pubspec.yaml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8163f83..6a3d528a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.2.0 + - upgraded dependencies + - migrate from `wakelock` to `wakelock_plus` PR [#129](https://github.com/newtaDev/pod_player/pull/129) + - fixed all lint rules + - migrated `VideoPlayerController.network` to `VideoPlayerController.networkUrl` + - Breaking: + - In `PlayVideoFrom.file` [file] param datatype changed from [dynamic] to [File] ## 0.1.5 - merged PR #103 - support unlisted vimeo videos diff --git a/pubspec.yaml b/pubspec.yaml index 62eab3a4..9f0a3e96 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pod_player description: Vimeo and youtube player for flutter, Pod player provides customizable video player controls that support android, ios and web. -version: 0.1.5 +version: 0.2.0 homepage: https://github.com/newtaDev/pod_player environment: From 59f0b945b013f67302b6390465023245141bdafa Mon Sep 17 00:00:00 2001 From: newtaDev Date: Mon, 14 Aug 2023 18:12:12 +0530 Subject: [PATCH 18/24] =?UTF-8?q?=F0=9F=9A=80=20pub=20-v=200.2.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 5 +++++ lib/src/controllers/pod_video_controller.dart | 12 +++++++----- pubspec.yaml | 17 +++++++++-------- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a3d528a..ab8e0fea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.2.1 +- upgraded all dependencies +- upgraded `http` lib to `^1.1.0` +- fix fullscreen issue in IOS + ## 0.2.0 - upgraded dependencies - migrate from `wakelock` to `wakelock_plus` PR [#129](https://github.com/newtaDev/pod_player/pull/129) diff --git a/lib/src/controllers/pod_video_controller.dart b/lib/src/controllers/pod_video_controller.dart index 345ad5cc..0a0d4ea6 100644 --- a/lib/src/controllers/pod_video_controller.dart +++ b/lib/src/controllers/pod_video_controller.dart @@ -200,11 +200,13 @@ class _PodVideoController extends _PodUiController { DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]), - SystemChrome.setPreferredOrientations(DeviceOrientation.values), - SystemChrome.setEnabledSystemUIMode( - SystemUiMode.manual, - overlays: SystemUiOverlay.values, - ), + if (!(defaultTargetPlatform == TargetPlatform.iOS)) ...[ + SystemChrome.setPreferredOrientations(DeviceOrientation.values), + SystemChrome.setEnabledSystemUIMode( + SystemUiMode.manual, + overlays: SystemUiOverlay.values, + ), + ] ]); } diff --git a/pubspec.yaml b/pubspec.yaml index 9f0a3e96..88647f4e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pod_player description: Vimeo and youtube player for flutter, Pod player provides customizable video player controls that support android, ios and web. -version: 0.2.0 +version: 0.2.1 homepage: https://github.com/newtaDev/pod_player environment: @@ -12,16 +12,17 @@ dependencies: sdk: flutter # services video_player: ^2.7.0 - http: ^0.13.6 - get: ^4.6.5 - wakelock_plus: ^1.1.0 - universal_html: ^2.2.3 - youtube_explode_dart: ^1.12.4 + http: ^1.1.0 + get: ^4.6.5 + wakelock_plus: ^1.1.1 + universal_html: ^2.2.3 + youtube_explode_dart: ^2.0.1 + dev_dependencies: flutter_test: sdk: flutter - very_good_analysis: ^4.0.0+1 + very_good_analysis: ^5.0.0+1 screenshots: - description: Pod video player logo - path: screenshots/logo.png \ No newline at end of file + path: screenshots/logo.png From a44f75bbeb63a7b4597c4a189ff0575b45183ea6 Mon Sep 17 00:00:00 2001 From: newtaDev Date: Wed, 16 Aug 2023 13:16:45 +0530 Subject: [PATCH 19/24] fix: CI error --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 88647f4e..600491f8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -21,7 +21,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - very_good_analysis: ^5.0.0+1 + very_good_analysis: ^4.0.0+1 screenshots: - description: Pod video player logo From 29b5c2523d6b2990d25dca1e7506135b47805d5e Mon Sep 17 00:00:00 2001 From: newtaDev Date: Wed, 16 Aug 2023 13:20:54 +0530 Subject: [PATCH 20/24] fix: flexible dependencies for universal_html and very_good_analysis --- pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 600491f8..362822ea 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,13 +15,13 @@ dependencies: http: ^1.1.0 get: ^4.6.5 wakelock_plus: ^1.1.1 - universal_html: ^2.2.3 + universal_html: youtube_explode_dart: ^2.0.1 dev_dependencies: flutter_test: sdk: flutter - very_good_analysis: ^4.0.0+1 + very_good_analysis: screenshots: - description: Pod video player logo From 1f7d7e7ff5cadec5d27ed90e3269bc1a9f3f9d32 Mon Sep 17 00:00:00 2001 From: newtaDev Date: Wed, 16 Aug 2023 13:37:54 +0530 Subject: [PATCH 21/24] revert --- pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 362822ea..88647f4e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,13 +15,13 @@ dependencies: http: ^1.1.0 get: ^4.6.5 wakelock_plus: ^1.1.1 - universal_html: + universal_html: ^2.2.3 youtube_explode_dart: ^2.0.1 dev_dependencies: flutter_test: sdk: flutter - very_good_analysis: + very_good_analysis: ^5.0.0+1 screenshots: - description: Pod video player logo From 4a096c344a84a1b31be4c992b540fcc1627d78a1 Mon Sep 17 00:00:00 2001 From: Newton Michael | Newta Date: Mon, 9 Oct 2023 17:17:20 +0530 Subject: [PATCH 22/24] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ea8b1e19..4dd4015c 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ pub points

+

newta

+ Video player for flutter web & mobile devices, pod player supports playing video from `Youtube` and `Vimeo` pod player is a simple and easy-to-use video player. Its video controls are similar to Youtube player (with customizable controls) and also can play videos from `Youtube` and `Vimeo` (By providing url/video_id). From e40799b35175e03fe3f51c8b1df2961ed24d59c8 Mon Sep 17 00:00:00 2001 From: newtaDev Date: Thu, 11 Apr 2024 09:49:40 +0530 Subject: [PATCH 23/24] fix: broken vimeo api requests and upgraded the dependencies --- README.md | 14 ++--- example/ios/Flutter/AppFrameworkInfo.plist | 2 +- example/ios/Podfile | 2 +- example/ios/Podfile.lock | 17 +++--- example/ios/Runner.xcodeproj/project.pbxproj | 8 +-- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- .../Flutter/GeneratedPluginRegistrant.swift | 4 +- example/macos/Podfile.lock | 52 ++++++++++++++++ lib/src/utils/video_apis.dart | 61 +++++++++++-------- pubspec.yaml | 14 ++--- 10 files changed, 122 insertions(+), 54 deletions(-) create mode 100644 example/macos/Podfile.lock diff --git a/README.md b/README.md index 4dd4015c..e5515225 100644 --- a/README.md +++ b/README.md @@ -39,24 +39,24 @@ This plugin built upon flutter's official [`video_player`](https://pub.dartlang. - Custom progress bar - Custom labels - `Change video quality` (for vimeo and youtube) -- Enable/disable fullscreen player +- Enable/disable full-screen player - support for live youtube video - [TODO] support for video playlist ## Features on web -- Double tap on Video player to enable/disable fullscreen -- `Mute/unmute` volume +- Double tap on Video player to enable/disable full-screen +- `Mute/unMute` volume - Video player integration with keyboard - `SPACE` play/pause video - `M` mute/unMute video - - `F` enable/disable fullscreen - - `ESC` enable/disable fullscreen + - `F` enable/disable full-screen + - `ESC` enable/disable full-screen - `->` seek video forward - `<-` seek video backward -- Double tap on video (enable/diables fullscreen) +- Double tap on video (enable/disables full-screen) ## Demo @@ -98,7 +98,7 @@ This plugin built upon flutter's official [`video_player`](https://pub.dartlang. --- -- On mobile full screen +- On mobile full-screen --- diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 9625e105..7c569640 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index 88359b22..279576f3 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '11.0' +# platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 2d8232cd..9e54c99f 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -4,13 +4,14 @@ PODS: - Flutter - video_player_avfoundation (0.0.1): - Flutter + - FlutterMacOS - wakelock_plus (0.0.1): - Flutter DEPENDENCIES: - Flutter (from `Flutter`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`) + - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`) - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`) EXTERNAL SOURCES: @@ -19,16 +20,16 @@ EXTERNAL SOURCES: package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" video_player_avfoundation: - :path: ".symlinks/plugins/video_player_avfoundation/ios" + :path: ".symlinks/plugins/video_player_avfoundation/darwin" wakelock_plus: :path: ".symlinks/plugins/wakelock_plus/ios" SPEC CHECKSUMS: - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 - package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7 - video_player_avfoundation: 81e49bb3d9fb63dccf9fa0f6d877dc3ddbeac126 - wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c + video_player_avfoundation: 02011213dab73ae3687df27ce441fbbcc82b5579 + wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1 -PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 +PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011 -COCOAPODS: 1.11.2 +COCOAPODS: 1.15.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 5b1c9f9c..325aea03 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -155,7 +155,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -342,7 +342,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -420,7 +420,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -469,7 +469,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c87d15a3..5e31d3d3 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ ; - final progressiveUrls = List.generate( - jsonData.length, - (index) => VideoQalityUrls( - quality: int.parse( - (jsonData[index]['quality'] as String?)?.split('p').first ?? '0', - ), - url: jsonData[index]['url'] as String, - ), - ); - if (progressiveUrls.isEmpty) { - final jsonRes = - jsonDecode(response.body)['request']['files']['hls']['cdns']; - for (final element in (jsonRes as Map).entries.toList()) { - progressiveUrls.add( - VideoQalityUrls( - quality: 720, - url: element.value['url'] as String, + final jsonData = jsonDecode(response.body)['request']['files']; + final dashData = jsonData['dash']; + final hlsData = jsonData['hls']; + final defaultCDN = hlsData['default_cdn']; + final cdnVideoUrl = (hlsData['cdns'][defaultCDN]['url'] as String?) ?? ''; + final List rawStreamUrls = + (dashData['streams'] as List?) ?? []; + + final List vimeoQualityUrls = []; + + for (final item in rawStreamUrls) { + final sepList = cdnVideoUrl.split('/sep/video/'); + final firstUrlPiece = sepList.firstOrNull ?? ''; + final lastUrlPiece = + ((sepList.lastOrNull ?? '').split('/').lastOrNull) ?? + (sepList.lastOrNull ?? ''); + final String urlId = + ((item['id'] ?? '') as String).split('-').firstOrNull ?? ''; + vimeoQualityUrls.add( + VideoQalityUrls( + quality: int.parse( + (item['quality'] as String?)?.split('p').first ?? '0', ), - ); - break; - } + url: '$firstUrlPiece/sep/video/$urlId/$lastUrlPiece', + ), + ); } - return progressiveUrls; + if (vimeoQualityUrls.isEmpty) { + vimeoQualityUrls.add( + VideoQalityUrls( + quality: 720, + url: cdnVideoUrl, + ), + ); + } + + return vimeoQualityUrls; } catch (error) { if (error.toString().contains('XMLHttpRequest')) { log( @@ -77,7 +89,8 @@ class VideoApis { Uri.parse('https://api.vimeo.com/videos/$videoId'), headers: httpHeader, ); - final jsonData = jsonDecode(response.body)['files'] as List; + final jsonData = + (jsonDecode(response.body)['files'] as List?) ?? []; final List list = []; for (int i = 0; i < jsonData.length; i++) { diff --git a/pubspec.yaml b/pubspec.yaml index 88647f4e..e4f7d6d4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,19 +4,19 @@ version: 0.2.1 homepage: https://github.com/newtaDev/pod_player environment: - sdk: ">=2.17.0 <4.0.0" + sdk: ">=3.0.0 <4.0.0" flutter: ">=1.17.0" dependencies: flutter: sdk: flutter # services - video_player: ^2.7.0 - http: ^1.1.0 - get: ^4.6.5 - wakelock_plus: ^1.1.1 - universal_html: ^2.2.3 - youtube_explode_dart: ^2.0.1 + video_player: ^2.8.5 + http: ^1.2.1 + get: ^4.6.6 + wakelock_plus: ^1.2.4 + universal_html: ^2.2.4 + youtube_explode_dart: ^2.2.0 dev_dependencies: flutter_test: From f3ea20e044d50bac6f35ac408edd65276f534540 Mon Sep 17 00:00:00 2001 From: newtaDev Date: Thu, 11 Apr 2024 10:30:08 +0530 Subject: [PATCH 24/24] =?UTF-8?q?=F0=9F=9A=80=20pub=20-v=200.2.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 ++++++ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab8e0fea..26d68b0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.2.2 +- fixed broken vimeo api requests +- upgraded minimum sdk version from ">=2.17.0 <4.0.0" to ">=3.0.0 <4.0.0" +- upgraded all the dependencies to latest version +- fix typos in README.md + ## 0.2.1 - upgraded all dependencies - upgraded `http` lib to `^1.1.0` diff --git a/pubspec.yaml b/pubspec.yaml index e4f7d6d4..c04b2050 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pod_player description: Vimeo and youtube player for flutter, Pod player provides customizable video player controls that support android, ios and web. -version: 0.2.1 +version: 0.2.2 homepage: https://github.com/newtaDev/pod_player environment: