newtaDev / pod_player

Video player for flutter web & mobile devices, Play video from youtube or vimeo or network in flutter using pod player
https://pub.dev/packages/pod_player
MIT License
102 stars 181 forks source link

Custom overlay doesn't work #148

Open RuslanOrolbaev opened 1 year ago

RuslanOrolbaev commented 1 year ago

Hello, I tried to use a custom overlay, but it doesn't work. Debugger shows the following:

it correctly assigns here in pod_player.dart:

void addToUiController() { Get.find(tag: controller.getTag) ///add to ui controller ..podPlayerLabels = podPlayerLabels ..alwaysShowProgressBar = alwaysShowProgressBar ..podProgressBarConfig = podProgressBarConfig ..overlayBuilder = overlayBuilder ..videoTitle = videoTitle ..onToggleFullScreen = onToggleFullScreen ..onLoading = onLoading ..videoThumbnail = videoThumbnail; }

however later here in overlays.dart the check shows that the builder is null:

Widget build(BuildContext context) { final podCtr = Get.find(tag: tag); if (podCtr.overlayBuilder != null) { return GetBuilder( id: 'update-all', tag: tag, builder: (podCtr) { ///Custom overlay

Can you please look into the issue? Thank you. Version 0.2.1

newtaDev commented 1 year ago

OverlayBuilder is working fine

you can refer:

import 'package:pod_player/pod_player.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(const CustomOverlayApp());
}

class CustomOverlayApp extends StatelessWidget {
  const CustomOverlayApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('custom overlay example')),
        body: const CustomOverlayExample(),
      ),
    );
  }
}

class CustomOverlayExample extends StatefulWidget {
  const CustomOverlayExample({Key? key}) : super(key: key);

  @override
  State<CustomOverlayExample> createState() => _PlayVideoFromAssetState();
}

class _PlayVideoFromAssetState extends State<CustomOverlayExample> {
  late final PodPlayerController controller;
  final videoTextFieldCtr = TextEditingController();

  @override
  void initState() {
    controller = PodPlayerController(
      playVideoFrom: PlayVideoFrom.network(
        'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4',
      ),
    )..initialise();
    super.initState();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ListView(
        shrinkWrap: true,
        children: [
          PodVideoPlayer(
              controller: controller,
              podProgressBarConfig: const PodProgressBarConfig(
                padding: kIsWeb
                    ? EdgeInsets.zero
                    : EdgeInsets.only(
                        bottom: 20,
                        left: 20,
                        right: 20,
                      ),
                playingBarColor: Colors.blue,
                circleHandlerColor: Colors.blue,
                backgroundColor: Colors.blueGrey,
              ),
              overlayBuilder: (options) {
                return Container(
                  color: Colors.grey.withOpacity(0.2),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: [
                      Row(
                        children: [
                          ElevatedButton(
                            child: Text(
                              options.isMute ? 'UnMute' : 'Mute',
                            ),
                            onPressed: () {
                              controller.toggleVolume();
                            },
                          ),
                          const SizedBox(width: 10),
                          ElevatedButton(
                            child: Text(
                              options.podVideoState == PodVideoState.paused
                                  ? 'Play'
                                  : 'Pause',
                            ),
                            onPressed: () {
                              controller.togglePlayPause();
                            },
                          ),
                          const SizedBox(width: 10),
                          ElevatedButton(
                            child: const Text('Full Screen'),
                            onPressed: () {
                              if (controller.isFullScreen) {
                                controller.disableFullScreen(context);
                              } else {
                                controller.enableFullScreen();
                              }
                            },
                          ),
                        ],
                      ),
                      const SizedBox(height: 20),
                      options.podProgresssBar,
                      const SizedBox(height: 20),
                    ],
                  ),
                );
              }),
          const SizedBox(height: 40),
          _loadVideoFromUrl()
        ],
      ),
    );
  }

  Row _loadVideoFromUrl() {
    return Row(
      children: [
        Expanded(
          flex: 2,
          child: TextField(
            controller: videoTextFieldCtr,
            decoration: const InputDecoration(
              labelText: 'Enter video url',
              floatingLabelBehavior: FloatingLabelBehavior.always,
              hintText:
                  'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4',
              border: OutlineInputBorder(),
            ),
          ),
        ),
      ],
    );
  }

  void snackBar(String text) {
    ScaffoldMessenger.of(context)
      ..hideCurrentSnackBar()
      ..showSnackBar(
        SnackBar(
          content: Text(text),
        ),
      );
  }
}
RuslanOrolbaev commented 1 year ago

Thank you for looking into the issue. However, in my case, it was not working. Neither OverlayBuilder, nor podProgressBarConfig parameters for PodGetXVideoController were not working. I started looking into the code and found that the issue was with tag, which is generated here:

(pod_player_controller.dart)

void _init() { getTag = UniqueKey().toString(); Get.config(enableLog: PodVideoPlayer.enableGetxLogs); _ctr = Get.put(PodGetXVideoController(), permanent: true, tag: getTag) ..config( playVideoFrom: playVideoFrom, playerConfig: podPlayerConfig, ); }

The _init() method runs twice, once here:

_PodPlayerController({ required this.playVideoFrom, this.podPlayerConfig = const PodPlayerConfig(), }) { _init(); }_

and then here:

Future initialise() async { if (!_isCtrInitialised) { _init(); } WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { try { if (!_isCtrInitialised) { await _ctr.videoInit(); podLog('$getTag Pod player Initialized'); } else { podLog('$getTag Pod Player Controller Already Initialized'); } } catch (error) { podLog('$getTag Pod Player Controller failed to initialize'); _initializationError = error; } }); await _checkAndWaitTillInitialized(); }

So it generates one tag while creating the PodPlayerController class and then generates another tag while initialization. So, If I create PodPlayerController object first and assign parameters, and later somewhere in another piece of code run initialise() method, _init() will run again, additional tag will be generated and GetX would refer to wrong object with default parameters.

So I added another boolean to monitor if _init() runs only once to ensure that the tag is generated only once:

bool _preInitDone = false;

void _init() { getTag = UniqueKey().toString(); Get.config(enableLog: PodVideoPlayer.enableGetxLogs); _ctr = Get.put(PodGetXVideoController(), permanent: true, tag: getTag) ..config( playVideoFrom: playVideoFrom, playerConfig: podPlayerConfig, ); _preInitDone = true; }

Future initialise() async { if (!_isCtrInitialised && !_preInitDone) { _init(); }

Now it works like a charm. Please let me know your thoughts on this.