smnbbrv / ngx-plyr

Angular 6+ binding for Plyr video & audio player
https://smnbbrv.github.io/ngx-plyr/
MIT License
100 stars 65 forks source link

Blocking forward seeking #15

Closed mgzurakowski closed 5 years ago

mgzurakowski commented 5 years ago

Is there possibility to block forward seeking? I found this codepen example for plain Plyr https://codepen.io/gurupras/pen/rdzBLK but it doesn't work for me with ngx-plyr (and, of course, it doesn't look like legit way to achieving it in Angular ;)). I tried doing this via returning false on plyrSeeking, but it doesn't work as expected.

smnbbrv commented 5 years ago

Hi @mgzurakowski

the plyrSeeked is one-directional, because it is (as any @Output by Angular design) an Observable and not an HTML-like event.

I am quite sure that event.preventDefault() is the real solution, not the return value, at least in the example you found I can safely remove return false; part and it still works.

I guess something like <plyr (plyrSeeked)="$event.preventDefault()"></plyr> should work to block overall seeking. If yes, then the rest is just to implement the rest from this example.

Please post whether it helped :)

mgzurakowski commented 5 years ago

Thanks for response :)

Sadly it's another solution I tried and in this case I get

Unable to preventDefault inside passive event listener invocation.

error in console.

smnbbrv commented 5 years ago

The problem is that the plyr events are passive (and it cannot be changed on the end user's side).

The only way I see is then to use [plyrOptions]="options" in combination with (plyrInit):

<plyr ... [plyrOptions]="options" (plyrInit)="player = $event"></plyr>

and options is something like (just took the code from example)

// ...

options: ...;

player: ...;

// ...

ngOnInit() {
    function _getTargetTime(plyr, input) {
      if (
        typeof input === "object" &&
        (input.type === "input" || input.type === "change")
      ) {
        return input.target.value / input.target.max * plyr.media.duration;
      } else {
        // We're assuming its a number
        return Number(input);
      }
    }

    this.options = {
      listeners: {
        seek: function customSeekBehavior(e) {
          var currentTime = this.player.currentTime;
          var newTime = _getTargetTime(this.player, e);
          // We only want rewind functionality
          // Therefore, disallow moving forward
          if (newTime > currentTime) {
            // Works if we add the following:
            // Object.defineProperty(event, "defaultPrevented", {
            //   value: event.defaultPrevented,
            //   writable: true
            // });
            // event.preventDefault = () => {
            //   event.defaultPrevented = true;
            // };
            e.preventDefault();
            console.log(`prevented`);
            return false;
          }
        }
      }
    };
}

This way it does not create passive events.

However, relying on this behavior... is quite shaky.

mgzurakowski commented 5 years ago

OK, after some changes it works for me. Thanks :)

smnbbrv commented 5 years ago

wow, super! Could you post the solution, please? Or at least a small note on what helped you out.

This will be useful for future readers.

Could the issue be closed then?

pokono commented 4 years ago

@mgzurakowski I am looking for the same. How did you ended up doing it?