diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9b1a9f80..38a1c9bb 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:
@@ -14,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/CHANGELOG.md b/CHANGELOG.md
index 26acffa1..26d68b0f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,39 @@
+## 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`
+- 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)
+ - 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
+ - upgraded dependencies
+ - Updated Readme file
+## 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
+ - 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..e5515225 100644
--- a/README.md
+++ b/README.md
@@ -3,12 +3,14 @@
-
-
-
-
+
+
+
+
+
+
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).
@@ -26,8 +28,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.
@@ -37,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
@@ -68,8 +70,14 @@ This plugin built upon flutter's official [`video_player`](https://pub.dartlang.
+- Video player on web
+
---
+
+
+
+
- Vimeo player and custom video player
---
@@ -90,7 +98,7 @@ This plugin built upon flutter's official [`video_player`](https://pub.dartlang.
---
-- On mobile full screen
+- On mobile full-screen
---
@@ -116,12 +124,6 @@ This plugin built upon flutter's official [`video_player`](https://pub.dartlang.
---
----
-
-
-
-
-
## Usage
- [Installation](#installation)
@@ -380,6 +382,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
---
@@ -396,14 +441,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/analysis_options.yaml b/analysis_options.yaml
index a547bf2a..18aea978 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,19 +1,17 @@
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
- missing_required_param: true
prefer_const_declarations: true
prefer_const_constructors: true
public_member_api_docs: false
@@ -22,7 +20,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
@@ -34,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/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/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/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/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist
index 8d4492f9..7c569640 100644
--- a/example/ios/Flutter/AppFrameworkInfo.plist
+++ b/example/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 9.0
+ 12.0
diff --git a/example/ios/Podfile b/example/ios/Podfile
index 1e8c3c90..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, '9.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 5292f26f..9e54c99f 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -1,28 +1,35 @@
PODS:
- Flutter (1.0.0)
+ - package_info_plus (0.4.5):
+ - Flutter
- video_player_avfoundation (0.0.1):
- Flutter
- - wakelock (0.0.1):
+ - FlutterMacOS
+ - wakelock_plus (0.0.1):
- Flutter
DEPENDENCIES:
- Flutter (from `Flutter`)
- - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
- - wakelock (from `.symlinks/plugins/wakelock/ios`)
+ - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
+ - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
+ - 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"
+ :path: ".symlinks/plugins/video_player_avfoundation/darwin"
+ wakelock_plus:
+ :path: ".symlinks/plugins/wakelock_plus/ios"
SPEC CHECKSUMS:
- Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
- video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
- wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
+ Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
+ package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
+ video_player_avfoundation: 02011213dab73ae3687df27ce441fbbcc82b5579
+ wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1
-PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
+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 c94fba36..325aea03 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 = "";
};
@@ -156,7 +155,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1300;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -200,10 +199,12 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
+ "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
@@ -214,6 +215,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@@ -340,7 +342,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 = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -418,7 +420,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 = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -467,7 +469,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 = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -492,7 +494,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.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 @@
+ CADisableMinimumFrameDurationOnPhone
+
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
@@ -29,6 +31,8 @@
NSAllowsArbitraryLoads
+ UIApplicationSupportsIndirectInputEvents
+
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
@@ -48,7 +52,5 @@
UIViewControllerBasedStatusBarAppearance
- CADisableMinimumFrameDurationOnPhone
-
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/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift
index 1c2c9b07..8e40e9f0 100644
--- a/example/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -5,8 +5,12 @@
import FlutterMacOS
import Foundation
-import wakelock_macos
+import package_info_plus
+import video_player_avfoundation
+import wakelock_plus
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
- WakelockMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockMacosPlugin"))
+ FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
+ FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
+ WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
}
diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock
new file mode 100644
index 00000000..5bfc2eea
--- /dev/null
+++ b/example/macos/Podfile.lock
@@ -0,0 +1,52 @@
+PODS:
+ - FlutterMacOS (1.0.0)
+ - media_kit_libs_macos_video (1.0.4):
+ - FlutterMacOS
+ - media_kit_native_event_loop (1.0.0):
+ - FlutterMacOS
+ - media_kit_video (0.0.1):
+ - FlutterMacOS
+ - package_info_plus (0.0.1):
+ - FlutterMacOS
+ - screen_brightness_macos (0.1.0):
+ - FlutterMacOS
+ - wakelock_plus (0.0.1):
+ - FlutterMacOS
+
+DEPENDENCIES:
+ - FlutterMacOS (from `Flutter/ephemeral`)
+ - media_kit_libs_macos_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos`)
+ - media_kit_native_event_loop (from `Flutter/ephemeral/.symlinks/plugins/media_kit_native_event_loop/macos`)
+ - media_kit_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos`)
+ - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
+ - screen_brightness_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos`)
+ - wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
+
+EXTERNAL SOURCES:
+ FlutterMacOS:
+ :path: Flutter/ephemeral
+ media_kit_libs_macos_video:
+ :path: Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos
+ media_kit_native_event_loop:
+ :path: Flutter/ephemeral/.symlinks/plugins/media_kit_native_event_loop/macos
+ media_kit_video:
+ :path: Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos
+ package_info_plus:
+ :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
+ screen_brightness_macos:
+ :path: Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos
+ wakelock_plus:
+ :path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos
+
+SPEC CHECKSUMS:
+ FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
+ media_kit_libs_macos_video: b3e2bbec2eef97c285f2b1baa7963c67c753fb82
+ media_kit_native_event_loop: 81fd5b45192b72f8b5b69eaf5b540f45777eb8d5
+ media_kit_video: c75b07f14d59706c775778e4dd47dd027de8d1e5
+ package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
+ screen_brightness_macos: 2d6d3af2165592d9a55ffcd95b7550970e41ebda
+ wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
+
+PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
+
+COCOAPODS: 1.11.2
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 a0ef656f..4edc604c 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,20 +69,20 @@ 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}) {
- 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_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/controllers/pod_getx_video_controller.dart b/lib/src/controllers/pod_getx_video_controller.dart
index 1197369b..7a46d30d 100644
--- a/lib/src/controllers/pod_getx_video_controller.dart
+++ b/lib/src/controllers/pod_getx_video_controller.dart
@@ -5,8 +5,8 @@ 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:wakelock/wakelock.dart';
+import 'package:universal_html/html.dart' as uni_html;
+import 'package:wakelock_plus/wakelock_plus.dart';
import '../../pod_player.dart';
import '../utils/logger.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,58 +95,61 @@ 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:
- await getQualityUrlsFromVimeoId(playVideoFrom.dataSource!);
- final _url = await getUrlFromVideoQualityUrls(
+ await getQualityUrlsFromVimeoId(
+ playVideoFrom.dataSource!,
+ hash: playVideoFrom.hash,
+ );
+ 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:
@@ -179,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;
}
@@ -226,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);
}
@@ -239,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);
}
}
@@ -254,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 9734e9cc..229ce884 100644
--- a/lib/src/controllers/pod_player_controller.dart
+++ b/lib/src/controllers/pod_player_controller.dart
@@ -2,8 +2,8 @@ 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:universal_html/html.dart' as uni_html;
+import 'package:wakelock_plus/wakelock_plus.dart';
import '../../pod_player.dart';
import '../utils/logger.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();
}
@@ -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,
@@ -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);
@@ -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_controller.dart b/lib/src/controllers/pod_video_controller.dart
index e9586162..0a0d4ea6 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);
}
@@ -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,
+ ),
+ ]
]);
}
@@ -226,7 +228,7 @@ class _PodVideoController extends _PodUiController {
Navigator.push(
mainContext,
- PageRouteBuilder(
+ PageRouteBuilder(
fullscreenDialog: true,
pageBuilder: (BuildContext context, _, __) => FullScreenView(
tag: tag,
@@ -243,14 +245,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 9f4b8dee..f841e018 100644
--- a/lib/src/controllers/pod_video_quality_controller.dart
+++ b/lib/src/controllers/pod_video_quality_controller.dart
@@ -14,13 +14,19 @@ 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 ?? [];
+ vimeoOrVideoUrls = vimeoVideoUrls ?? [];
} catch (e) {
rethrow;
}
@@ -32,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;
}
@@ -45,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
@@ -121,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 87849a61..d3927bbb 100644
--- a/lib/src/models/play_video_from.dart
+++ b/lib/src/models/play_video_from.dart
@@ -1,11 +1,14 @@
+import 'dart:io';
+
import '../../pod_player.dart';
class PlayVideoFrom {
final String? dataSource;
+ final String? hash;
final PodVideoPlayerType playerType;
final VideoFormat? formatHint;
final String? package;
- final dynamic file;
+ final File? file;
final List? videoQualityUrls;
final Future? closedCaptionFile;
final VideoPlayerOptions? videoPlayerOptions;
@@ -13,9 +16,10 @@ class PlayVideoFrom {
final bool live;
const PlayVideoFrom._({
+ required this.playerType,
this.live = false,
this.dataSource,
- required this.playerType,
+ this.hash,
this.formatHint,
this.package,
this.file,
@@ -60,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,
}) {
@@ -74,6 +78,7 @@ class PlayVideoFrom {
factory PlayVideoFrom.vimeo(
String dataSource, {
+ String? hash,
VideoFormat? formatHint,
Future? closedCaptionFile,
VideoPlayerOptions? videoPlayerOptions,
@@ -82,6 +87,7 @@ class PlayVideoFrom {
return PlayVideoFrom._(
playerType: PodVideoPlayerType.vimeo,
dataSource: dataSource,
+ hash: hash,
formatHint: formatHint,
closedCaptionFile: closedCaptionFile,
videoPlayerOptions: videoPlayerOptions,
diff --git a/lib/src/pod_player.dart b/lib/src/pod_player.dart
index 1148d485..82f451f8 100644
--- a/lib/src/pod_player.dart
+++ b/lib/src/pod_player.dart
@@ -1,16 +1,15 @@
import 'dart:async';
-import 'dart:ui';
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 'package:universal_html/html.dart' as uni_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';
@@ -57,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,
@@ -73,7 +72,7 @@ class PodVideoPlayer extends StatefulWidget {
this.videoThumbnail,
this.onToggleFullScreen,
this.onLoading,
- }) : super(key: key) {
+ }) {
addToUiController();
}
@@ -121,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());
}
}
@@ -159,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(
@@ -191,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),
);
@@ -244,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,
);
},
@@ -263,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 e319469e..69153a19 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,24 +12,61 @@ 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 jsonData =
- jsonDecode(response.body)['request']['files']['progressive'];
- return List.generate(
- jsonData.length,
- (index) => VideoQalityUrls(
- quality: int.parse(
- (jsonData[index]['quality'] as String?)?.split('p').first ?? '0',
+ final response = await _makeRequestHash(videoId, hash);
+ 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',
+ ),
+ url: '$firstUrlPiece/sep/video/$urlId/$lastUrlPiece',
),
- url: jsonData[index]['url'],
- ),
- );
+ );
+ }
+ if (vimeoQualityUrls.isEmpty) {
+ vimeoQualityUrls.add(
+ VideoQalityUrls(
+ quality: 720,
+ url: cdnVideoUrl,
+ ),
+ );
+ }
+
+ return vimeoQualityUrls;
} catch (error) {
if (error.toString().contains('XMLHttpRequest')) {
log(
@@ -51,7 +89,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++) {
@@ -59,7 +98,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 d38bb3d5..1afe558d 100644
--- a/lib/src/widgets/core/overlays/mobile_overlay.dart
+++ b/lib/src/widgets/core/overlays/mobile_overlay.dart
@@ -4,63 +4,52 @@ 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: [
- 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,
@@ -69,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(
@@ -98,7 +87,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
@@ -116,66 +105,9 @@ class _MobileOverlay extends StatelessWidget {
}
void _bottomSheet(BuildContext context) {
- showModalBottomSheet(
+ showModalBottomSheet(
context: context,
builder: (context) => SafeArea(child: _MobileBottomSheet(tag: tag)),
);
}
}
-
-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/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 0d62564f..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();
@@ -18,47 +17,46 @@ class _WebSettingsDropdownState extends State<_WebSettingsDropdown> {
return Theme(
data: Theme.of(context).copyWith(
focusColor: Colors.white,
- selectedRowColor: Colors.white,
),
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,
),
),
],
@@ -67,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;
}
},
);
@@ -90,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);
},
),
)
@@ -115,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,
);
},
@@ -147,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 cce58a60..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(),
@@ -31,28 +30,38 @@ 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()),
+ IgnorePointer(child: podCtr.videoTitle ?? const SizedBox()),
],
);
}
@@ -62,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(
@@ -82,7 +90,7 @@ class _WebOverlayBottomControlles extends StatelessWidget {
children: [
PodProgressBar(
tag: tag,
- podProgressBarConfig: _podCtr.podProgressBarConfig,
+ podProgressBarConfig: podCtr.podProgressBarConfig,
),
Row(
children: [
@@ -97,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,
),
@@ -115,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,
),
@@ -129,8 +137,8 @@ class _WebOverlayBottomControlles extends StatelessWidget {
style: durationTextStyle,
),
Text(
- _podCtr.calculateVideoDuration(
- _podCtr.videoDuration,
+ podCtr.calculateVideoDuration(
+ podCtr.videoDuration,
),
style: durationTextStyle,
),
@@ -151,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,
),
@@ -178,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
new file mode 100644
index 00000000..f23915f9
--- /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({
+ super.key,
+ this.child,
+ this.wrapper,
+ this.rippleColor,
+ this.backgroundColor,
+ this.borderRadius,
+ this.rippleDuration,
+ this.rippleEndingDuraiton,
+ this.onDoubleTap,
+ this.width,
+ this.height,
+ });
+
+ @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..1875e920
--- /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({
+ required this.onDoubleTap,
+ required this.tag,
+ required this.isForward,
+ super.key,
+ this.iconOnly = false,
+ this.height = 50,
+ this.width,
+ });
+
+ @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/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 42fdd23e..c04b2050 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,29 +1,28 @@
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.2.2
homepage: https://github.com/newtaDev/pod_player
environment:
- sdk: ">=2.17.0 <3.0.0"
+ sdk: ">=3.0.0 <4.0.0"
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
- # ui
- lottie: ^1.3.0
# services
- video_player: ^2.4.5
- http: ^0.13.4
- get: ^4.6.5
- wakelock: ^0.6.1+2
- universal_html: ^2.0.8
- youtube_explode_dart: ^1.11.0
+ 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:
sdk: flutter
- very_good_analysis: ^2.4.0
+ very_good_analysis: ^5.0.0+1
-flutter:
- assets:
- - assets/
+screenshots:
+ - description: Pod video player logo
+ path: screenshots/logo.png
diff --git a/screenshots/logo.png b/screenshots/logo.png
new file mode 100644
index 00000000..ab58ee62
Binary files /dev/null and b/screenshots/logo.png differ
diff --git a/scripts/verify_pub.sh b/scripts/verify_pub.sh
index eb21b5a3..8e78c89e 100644
--- a/scripts/verify_pub.sh
+++ b/scripts/verify_pub.sh
@@ -1,7 +1,7 @@
#!/bin/bash
echo "--------------- Format code ---------------"
-flutter format .
+dart format .
echo "--------------- --dry-run ---------------"
dart pub publish --dry-run
echo "--------------- verify pub score ---------------"