diff --git a/lib/src/controllers/pod_getx_video_controller.dart b/lib/src/controllers/pod_getx_video_controller.dart index 7a46d30d..9385e3da 100644 --- a/lib/src/controllers/pod_getx_video_controller.dart +++ b/lib/src/controllers/pod_getx_video_controller.dart @@ -93,7 +93,6 @@ class PodGetXVideoController extends _PodGesturesController { httpHeaders: playVideoFrom.httpHeaders, ); playingVideoUrl = playVideoFrom.dataSource; - break; case PodVideoPlayerType.networkQualityUrls: final url = await getUrlFromVideoQualityUrls( qualityList: podPlayerConfig.videoQualityPriority, @@ -109,8 +108,6 @@ class PodGetXVideoController extends _PodGesturesController { httpHeaders: playVideoFrom.httpHeaders, ); playingVideoUrl = url; - - break; case PodVideoPlayerType.youtube: final urls = await getVideoQualityUrlsFromYoutube( playVideoFrom.dataSource!, @@ -130,8 +127,6 @@ class PodGetXVideoController extends _PodGesturesController { httpHeaders: playVideoFrom.httpHeaders, ); playingVideoUrl = url; - - break; case PodVideoPlayerType.vimeo: await getQualityUrlsFromVimeoId( playVideoFrom.dataSource!, @@ -150,8 +145,6 @@ class PodGetXVideoController extends _PodGesturesController { httpHeaders: playVideoFrom.httpHeaders, ); playingVideoUrl = url; - - break; case PodVideoPlayerType.asset: /// @@ -162,8 +155,6 @@ class PodGetXVideoController extends _PodGesturesController { videoPlayerOptions: playVideoFrom.videoPlayerOptions, ); playingVideoUrl = playVideoFrom.dataSource; - - break; case PodVideoPlayerType.file: if (kIsWeb) { throw Exception('file doesnt support web'); @@ -175,8 +166,6 @@ class PodGetXVideoController extends _PodGesturesController { closedCaptionFile: playVideoFrom.closedCaptionFile, videoPlayerOptions: playVideoFrom.videoPlayerOptions, ); - - break; case PodVideoPlayerType.vimeoPrivateVideos: await getQualityUrlsFromVimeoPrivateId( playVideoFrom.dataSource!, @@ -195,8 +184,6 @@ class PodGetXVideoController extends _PodGesturesController { httpHeaders: playVideoFrom.httpHeaders, ); playingVideoUrl = url; - - break; } } @@ -259,18 +246,14 @@ class PodGetXVideoController extends _PodGesturesController { case PodVideoState.playing: if (podPlayerConfig.wakelockEnabled) WakelockPlus.enable(); playVideo(true); - break; case PodVideoState.paused: if (podPlayerConfig.wakelockEnabled) WakelockPlus.disable(); playVideo(false); - break; case PodVideoState.loading: isShowOverlay(true); - break; case PodVideoState.error: 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 229ce884..b5a51b79 100644 --- a/lib/src/controllers/pod_player_controller.dart +++ b/lib/src/controllers/pod_player_controller.dart @@ -160,6 +160,11 @@ class PodPlayerController { _ctr.isMute ? await _ctr.unMute() : await _ctr.mute(); } + /// set the volume of the video + Future setVolume(double newVolumeValue) async { + await _ctr.setVolume(newVolumeValue); + } + ///Dispose pod video player controller void dispose() { _isCtrInitialised = false; diff --git a/lib/src/models/pod_player_config.dart b/lib/src/models/pod_player_config.dart index f44c7918..39c3a71e 100644 --- a/lib/src/models/pod_player_config.dart +++ b/lib/src/models/pod_player_config.dart @@ -3,6 +3,7 @@ class PodPlayerConfig { final bool isLooping; final bool forcedVideoFocus; final bool wakelockEnabled; + final bool showVolumeBar; /// Initial video quality priority. The first available option will be used, /// from start to the end of this list. If all options informed are not @@ -16,6 +17,7 @@ class PodPlayerConfig { this.isLooping = false, this.forcedVideoFocus = false, this.wakelockEnabled = true, + this.showVolumeBar = true, this.videoQualityPriority = const [1080, 720, 360], }); @@ -24,6 +26,7 @@ class PodPlayerConfig { bool? isLooping, bool? forcedVideoFocus, bool? wakelockEnabled, + bool? showVolumeBar, List? videoQualityPriority, }) { return PodPlayerConfig( @@ -31,6 +34,7 @@ class PodPlayerConfig { isLooping: isLooping ?? this.isLooping, forcedVideoFocus: forcedVideoFocus ?? this.forcedVideoFocus, wakelockEnabled: wakelockEnabled ?? this.wakelockEnabled, + showVolumeBar: showVolumeBar ?? this.showVolumeBar, videoQualityPriority: videoQualityPriority ?? this.videoQualityPriority, ); } diff --git a/lib/src/pod_player.dart b/lib/src/pod_player.dart index 82f451f8..0ad900bb 100644 --- a/lib/src/pod_player.dart +++ b/lib/src/pod_player.dart @@ -11,6 +11,7 @@ import 'controllers/pod_getx_video_controller.dart'; import 'utils/logger.dart'; import 'widgets/double_tap_icon.dart'; import 'widgets/material_icon_button.dart'; +import 'widgets/material_slider.dart'; part 'widgets/animated_play_pause_icon.dart'; diff --git a/lib/src/widgets/core/overlays/mobile_bottomsheet.dart b/lib/src/widgets/core/overlays/mobile_bottomsheet.dart index 5cf988e9..e77823c8 100644 --- a/lib/src/widgets/core/overlays/mobile_bottomsheet.dart +++ b/lib/src/widgets/core/overlays/mobile_bottomsheet.dart @@ -199,6 +199,31 @@ class _MobileOverlayBottomControlles extends StatelessWidget { Row( children: [ const SizedBox(width: 12), + GetBuilder( + tag: tag, + id: 'volume', + builder: (podCtr) => MaterialIconButton( + toolTipMesg: podCtr.isMute + ? podCtr.podPlayerLabels.unmute ?? 'Unmute' + : podCtr.podPlayerLabels.mute ?? 'Mute', + color: itemColor, + onPressed: podCtr.toggleMute, + child: Icon( + podCtr.isMute + ? Icons.volume_off_rounded + : Icons.volume_up_rounded, + ), + ), + ), + GetBuilder( + tag: tag, + id: 'volume-setter', + builder: (podCtr) => MaterialSlider( + isVisible: podCtr.podPlayerConfig.showVolumeBar, + initialValue: podCtr.videoCtr?.value.volume ?? 0, + onChanged: podCtr.setVolume, + ), + ), GetBuilder( tag: tag, id: 'video-progress', diff --git a/lib/src/widgets/core/overlays/web_dropdown_menu.dart b/lib/src/widgets/core/overlays/web_dropdown_menu.dart index 78965f89..122e602b 100644 --- a/lib/src/widgets/core/overlays/web_dropdown_menu.dart +++ b/lib/src/widgets/core/overlays/web_dropdown_menu.dart @@ -12,6 +12,8 @@ class _WebSettingsDropdown extends StatefulWidget { } class _WebSettingsDropdownState extends State<_WebSettingsDropdown> { + final double settingsFontSize = 12; + @override Widget build(BuildContext context) { return Theme( @@ -68,14 +70,11 @@ class _WebSettingsDropdownState extends State<_WebSettingsDropdown> { switch (settingsMenu) { case 'OUALITY': await _onVimeoQualitySelect(details, podCtr); - break; case 'SPEED': await _onPlaybackSpeedSelect(details, podCtr); - break; case 'LOOP': podCtr.isWebPopupOverlayOpen = false; await podCtr.toggleLooping(); - break; default: podCtr.isWebPopupOverlayOpen = false; } @@ -99,7 +98,10 @@ class _WebSettingsDropdownState extends State<_WebSettingsDropdown> { .map( (e) => PopupMenuItem( child: ListTile( - title: Text(e), + title: Text( + e, + style: TextStyle(fontSize: settingsFontSize), + ), ), onTap: () { podCtr.setVideoPlayBack(e); @@ -129,7 +131,10 @@ class _WebSettingsDropdownState extends State<_WebSettingsDropdown> { .map( (e) => PopupMenuItem( child: ListTile( - title: Text('${e.quality}p'), + title: Text( + '${e.quality}p', + style: TextStyle(fontSize: settingsFontSize), + ), ), onTap: () { podCtr.changeVideoQuality( @@ -153,38 +158,39 @@ class _WebSettingsDropdownState extends State<_WebSettingsDropdown> { required IconData icon, String? subText, }) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 15), - child: FittedBox( - fit: BoxFit.scaleDown, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(icon), - const SizedBox(width: 20), - Text( - title, - ), - if (subText != null) const SizedBox(width: 10), - if (subText != null) - const SizedBox( - height: 4, - width: 4, - child: DecoratedBox( - decoration: BoxDecoration( - color: Colors.grey, - shape: BoxShape.circle, - ), + return FittedBox( + fit: BoxFit.scaleDown, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, size: 15), + const SizedBox(width: 10), + Text( + title, + style: TextStyle(fontSize: settingsFontSize), + ), + if (subText != null) const SizedBox(width: 10), + if (subText != null) + const SizedBox( + height: 4, + width: 4, + child: DecoratedBox( + decoration: BoxDecoration( + color: Colors.grey, + shape: BoxShape.circle, ), ), - if (subText != null) const SizedBox(width: 6), - if (subText != null) - Text( - subText, - style: const TextStyle(color: Colors.grey), + ), + if (subText != null) const SizedBox(width: 6), + if (subText != null) + Text( + subText, + style: TextStyle( + color: Colors.grey, + fontSize: settingsFontSize, ), - ], - ), + ), + ], ), ); } diff --git a/lib/src/widgets/core/overlays/web_overlay.dart b/lib/src/widgets/core/overlays/web_overlay.dart index 3371b2fc..f5215c91 100644 --- a/lib/src/widgets/core/overlays/web_overlay.dart +++ b/lib/src/widgets/core/overlays/web_overlay.dart @@ -120,6 +120,15 @@ class _WebOverlayBottomControlles extends StatelessWidget { ), ), ), + GetBuilder( + tag: tag, + id: 'volume-setter', + builder: (podCtr) => MaterialSlider( + isVisible: podCtr.podPlayerConfig.showVolumeBar, + initialValue: podCtr.videoCtr?.value.volume ?? 0, + onChanged: podCtr.setVolume, + ), + ), GetBuilder( tag: tag, id: 'video-progress', diff --git a/lib/src/widgets/material_slider.dart b/lib/src/widgets/material_slider.dart new file mode 100644 index 00000000..2d4cf761 --- /dev/null +++ b/lib/src/widgets/material_slider.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; + +class MaterialSlider extends StatefulWidget { + final bool isVisible; + + const MaterialSlider({ + required this.isVisible, + required this.onChanged, + required this.initialValue, + this.activeTrackColor = Colors.white, + this.inactiveTrackColor = Colors.white24, + this.thumbColor = Colors.white, + super.key, + }); + + final Color activeTrackColor; + final Color inactiveTrackColor; + final Color thumbColor; + + final void Function(double) onChanged; + final double initialValue; + + @override + State createState() => _MaterialSliderState(); +} + +class _MaterialSliderState extends State { + double _value = 0; + + void _initValue() { + if (mounted) setState(() => _value = widget.initialValue); + } + + void _onChanged(double newValue) { + if (mounted) setState(() => _value = newValue); + widget.onChanged(newValue); + } + + @override + void initState() { + super.initState(); + _initValue(); + } + + @override + Widget build(BuildContext context) { + if (!widget.isVisible) return const SizedBox(); + + return Material( + type: MaterialType.transparency, + color: Colors.orange, + child: Padding( + padding: const EdgeInsets.only(right: 12), + child: SliderTheme( + data: SliderTheme.of(context).copyWith( + thumbColor: widget.thumbColor, + activeTrackColor: widget.activeTrackColor, + inactiveTrackColor: widget.inactiveTrackColor, + thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 5), + trackShape: const RectangularSliderTrackShape(), + trackHeight: 3, + overlayShape: const RoundSliderOverlayShape(overlayRadius: 12), + ), + child: SizedBox( + width: 100, + child: Slider(value: _value, onChanged: _onChanged), + ), + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 88647f4e..96218375 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.2.1 homepage: https://github.com/newtaDev/pod_player environment: - sdk: ">=2.17.0 <4.0.0" + sdk: ">=3.0.0 <4.0.0" flutter: ">=1.17.0" dependencies: