Skip to content

Writing a Plugin

While we have published a majority of the plugins we have developed, there will always be new use cases that may require new functionality. Writing a plugin in the easiest way to extend Player functionality for these cases. Plugins work slightly differently on each platform so in this guide we will cover how to write a plugin for each platform.

Core plugins are the easiest way to extend Player functionality regardless of what platform you are using Player on. To make writing core plugins easy @player-ui/player exposes an interface PlayerPlugin that denotes everything needed. The two mandatory features are a name property which is lets Player know how to refer to the plugin and an implemented apply function that takes a player object. Optionally a symbol property can be used to provide a unique identifier that can be used to retrieve the plugin from Player.

The first step for creating a plugin is making our plugin class, making sure it implements the PlayerPlugin interface from @player-ui/player. By convention, a name attribute with the dash-cased name of your plugin should be defined.

export default class ExamplePlayerPlugin implements PlayerPlugin {
name = 'example-player-plugin';
{/* A constructor can go here */}
apply(player: Player) {
{/* Your logic here */}
}
{/* Helper methods can go here */}
}

The apply function is where the actual logic of the plugin lives. By tapping the hooks exposed via player.hooks you gain access to the internal pipeline of components that comprise Player and can inject your functionality into their exposed hooks. For example if you want to do something any time Player’s state changes you could do the following:

apply(player: Player) {
player.hooks.state.tap(this.name, (state) => {
{/* Your logic here */}
});
}

Some components expose hooks themselves which may require multiple levels of taps which is not uncommon. For example if you wanted to modify the ViewInstance before it was resolved you would do the following:

apply(player: Player) {
player.hooks.viewController.tap(this.name, (vc) => {
vc.hooks.view.tap(this.name, (vc) => {
{/* Your logic here */}
})
});
}

It is not uncommon for core plugins to have constructors for cases where the plugin needs to take some configuration. In cases where plugin configs are more complicated than basic feature flags, it is recommended to make an interface to represent the config object. As an added benefit it also makes it easier to down stream consumers to use your plugin.

For a more comprehensive guide on plugins, check out this Plugin Implementation example.

Note: For the React Player you can import and load the plugin the same way you would a React Player Plugin but for the iOS and Android Players you will need to wrap the javascript bundle in a iOS/Android plugin to ensure it is available on your platform.