indigo-player icon indicating copy to clipboard operation
indigo-player copied to clipboard

Provide a React component

Open matvp91 opened this issue 5 years ago • 6 comments

Description Provide a npm module that exposes a Player component for React. Idea: import Player from 'indigo-player/react' (currently not available, this is merely an idea).

Code sample

import React, { useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import IndigoPlayer from 'indigo-player';

const CHUNKS_PATH = `https://cdn.jsdelivr.net/npm/indigo-player@${
  IndigoPlayer.VERSION
}/lib/`;

export default function Player({ config, chunksPath }) {
  const container = useRef(null);

  useEffect(() => {
    IndigoPlayer.setChunksPath(chunksPath);
  }, [chunksPath]);

  useEffect(() => {
    const player = IndigoPlayer.init(container.current, config);
    return () => player.destroy();
  }, [config]);

  return <div ref={container} />;
}

Player.propTypes = {
  config: PropTypes.shape({}).isRequired,
  chunksPath: PropTypes.string,
};

Player.defaultProps = {
  config: undefined,
  chunksPath: CHUNKS_PATH,
};
  • [x] Proper cleanup when player.destroy() is called.
  • [ ] Find a proper way to expose the player API which is returned by IndigoPlayer.init.
  • I'm not convinced about the IndigoPlayer.setChunksPath implementation for libraries. Chunks never really worked out-of-the-box when including an npm lib.

matvp91 avatar Apr 09 '19 14:04 matvp91

Find a proper way to expose the player API which is returned by IndigoPlayer.init

You could have a prop called onPlayerDraw or some such that fires after a player is ready and sends back the player along with anything else that is needed, like if (typeof onPlayerDraw === 'function') onPlayerDraw({player}); It would allow you to get the player API to the user if they want it (some may not need it) and allow them to run their own functionality to deal with the player draw (like autoplay checks and the like).

stoicbuddha avatar May 15 '19 19:05 stoicbuddha

I've had to use the same thing on a React project to notify a parent component that a child component is now hidden.

stoicbuddha avatar May 15 '19 19:05 stoicbuddha

Thought about it too but using a callback on a sync instruction (IndigoPlayer.init is sync) feels a bit counter-intuitive. One thing I'd like to try is using the useRef hook to create a reference to the player in combination with the useImperativeHandle hook to provide strictly the player API in the ref.

Eg:

const player = useRef();

// Access controller

// eg: player.current.play(), player.current.pause(), ...

// Access state
// indigo-player can provide these kind of hooks, eg: `usePlayerState(ref)`
const [playerState, setPlayerState] = useState(null);

useEffect(() => {
  if (player.current) {
    player.current.addListener(Events.STATE_CHANGE, state => setPlayerState(state));
    return () => player.current.removeListener(Events.STATE_CHANGE);
  }
}, [player.current]);

// eg: access state like playerState.playing, playerState.paused, ...

<Player ref={player} config={config} />

I'll have a play with this in the upcoming days.

matvp91 avatar May 16 '19 09:05 matvp91

Any updates on this idea @matvp91 ?

FreddyJD avatar Jan 21 '20 03:01 FreddyJD

@FreddyJD not at the moment, I've recently merged in https://github.com/matvp91/indigo-player/pull/53 which is a first step in a better module structure. Once I've cleared out the other roadblocks (and maintain backwards compatibility), you'll be able to install indigo-player as a module. This would make it a whole lot easier to wrap it around a React component.

Edit: The following code should get you started, simply run yarn add indigo-player (or npm) and you're good to go:

import React from "react";
import ReactDOM from "react-dom";
import indigoPlayer from "indigo-player";
import "indigo-player/lib/indigo-theme.css";

function App() {
  const ref = React.useRef();

  React.useEffect(() => {
    indigoPlayer.init(ref.current, {
      sources: [
        {
          type: "mp4",
          src:
            "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
        },
      ],
    });
  }, []);

  return (
    <div>
      <div ref={ref} />
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

Although there is no official integration for indigo-player with React yet, the sample above should get anyone going who wants to implement this in React.

matvp91 avatar Apr 20 '20 18:04 matvp91

@matvp91 Thanks for the sample.

Unfortunately I'm new to both React and Typescript and thought I'd found a holy-grail here, but alas I can't get it to work as is.

Property 'init' does not exist on type 'typeof import("/home/jon/source/myapp/node_modules/indigo-player/src/index")'.

I did manage to fix an issue with the useRef usage by making the following change: const ref = useRef<HTMLDivElement>(null);

hastarin avatar Jul 04 '20 00:07 hastarin