Skip to content

Commit

Permalink
feat(FEC-9341): refactor base component to HoC (#410)
Browse files Browse the repository at this point in the history
* added PlayerProvider and withPlayer components that expose player as prop to components
* added EventDispatcher and withEventDispatcher components that inject EventDispatcher actions from context to props of a component
* added withLogger component that inject logger as props of a component with a supplied namespace
* added withEventManager component that inject event manager as props of a component that require to manage event listeners
* fixed withAnimtation HoC signature to be inline with rest of HoCs
*moved `shouldRender` to be internal in component - this is cause HoCs don't expose static methods and in general this is not the best way to do it if we need to be able to dynamically add and remove components from bundle
* updated all indices of the player to use the new HoCs
* added doc
  • Loading branch information
OrenMe committed Sep 25, 2019
1 parent ccc225b commit f749921
Show file tree
Hide file tree
Showing 76 changed files with 1,868 additions and 1,025 deletions.
9 changes: 9 additions & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,12 @@ node_modules/@playkit-js/playkit-js/flow-typed/
unsafe.enable_getters_and_setters=true
esproposal.decorators=ignore
module.name_mapper.extension='scss' -> 'empty/object'
module.name_mapper='^utils\/\(.*\)$' -> '<PROJECT_ROOT>/src/utils/\1'
module.name_mapper='^utils$' -> '<PROJECT_ROOT>/src/utils'
module.name_mapper='^reducers\/\(.*\)$' -> '<PROJECT_ROOT>/src/reducers/\1'
module.name_mapper='^reducers$' -> '<PROJECT_ROOT>/src/reducers'
module.name_mapper='^components\/\(.*\)$' -> '<PROJECT_ROOT>/src/components/\1'
module.name_mapper='^components$' -> '<PROJECT_ROOT>/src/components'
module.name_mapper='^event\/\(.*\)$' -> '<PROJECT_ROOT>/src/event/\1'
module.name_mapper='^event$' -> '<PROJECT_ROOT>/src/event'
module.system.node.resolve_dirname='<PROJECT_ROOT>/src/'
2 changes: 1 addition & 1 deletion docs/components/fullscreen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { h, Fullscreen } from 'playkit-js-ui';

export default function customUIPreset(props: any) {
return (
<Fullscreen player={props.player} />
<Fullscreen />
)
}
```
2 changes: 1 addition & 1 deletion docs/components/loading/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { h, Loading } from 'playkit-js-ui';

export default function customUIPreset(props: any) {
return (
<Loading player={props.player} />
<Loading />
)
}
```
2 changes: 1 addition & 1 deletion docs/components/overlay-play/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { h, OverlayPlay } from 'playkit-js-ui';

export default function customUIPreset(props: any) {
return (
<OverlayPlay player={props.player} />
<OverlayPlay />
)
}
```
4 changes: 2 additions & 2 deletions docs/components/seekbar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ import { h, SeekBar } from 'playkit-js-ui';
export default function customUIPreset(props: any) {
return (
// show both frame preview and time bubble
<SeekBar showFramePreview showTimeBubble player={props.player} />
<SeekBar showFramePreview showTimeBubble />

// show only time bubble
<SeekBar showTimeBubble player={props.player} />
<SeekBar showTimeBubble />
)
}
```
2 changes: 1 addition & 1 deletion docs/components/time-display/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { h, TimeDisplay } from 'playkit-js-ui';

export default function customUIPreset(props: any) {
return (
<TimeDisplay format='current / total' player={props.player} />
<TimeDisplay format='current / total' />
)
}
```
12 changes: 6 additions & 6 deletions docs/create-ui-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ This component is using the player bundled PReact to manage state and intercept

```javascript
const h = KalturaPlayer.ui.h;
const BaseComponent = KalturaPlayer.ui.Components.BaseComponent;
const Component = KalturaPlayer.ui.preact.Component;

class SampleComponent extends BaseComponent {
class SampleComponent extends Component {
componentDidMount() {
// register to event handlers and other stuff here
}
Expand All @@ -55,9 +55,9 @@ If you want to use JSX follow this [guide](./custom-ui-preset.md#using-jsx), and

```javascript
const h = KalturaPlayer.ui.h;
const BaseComponent = KalturaPlayer.ui.Components.BaseComponent;
const Component = KalturaPlayer.ui.preact.Component;

class DumbComponent extends BaseComponent {
class DumbComponent extends Component {
render(props) {
return <div className="dumb-component">{props.children}</div>;
}
Expand Down Expand Up @@ -107,12 +107,12 @@ The component will also get a prop of additional className.
```javascript
//@flow
const h = KalturaPlayer.ui.h;
const BaseComponent = KalturaPlayer.ui.Components.BaseComponent;
const Component = KalturaPlayer.ui.preact.Component;
const connect = playkit.ui.redux.connect;

const mapStateToProps = state => ({playerState: state.engine.playerState});

class PlayerStateLog extends BaseComponent {
class PlayerStateLog extends Component {
log = new Array();

constructor() {
Expand Down
7 changes: 4 additions & 3 deletions docs/custom-ui-preset.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ const fullscreenUI = function(props){
h(
components.BottomBar,
h(
components.Fullscreen, { player: props.player },
components.Fullscreen,
{},
{ className: "playkit-left-controls" }
)
)
Expand Down Expand Up @@ -85,7 +86,7 @@ const fullscreenUI = function(props) {
return (
<div className="playback-gui-wrapper" style="height: 100%">
<BottomBar>
<Fullscreen player={props.player} />
<Fullscreen />
</BottomBar>
</div>
);
Expand All @@ -107,7 +108,7 @@ export default function fullscreenUI(props: any) {
return (
<div className='playback-gui-wrapper' style='height: 100%'>
<BottomBar>
<Fullscreen player={props.player} />
<Fullscreen />
</BottomBar>
</div>
)
Expand Down
10 changes: 6 additions & 4 deletions docs/guides.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Guides

* [Create UI Component](./create-ui-component.md)
* [Customizing the Player CSS](./css-classes-override.md)
* [Custom UI Preset](./custom-ui-preset.md)
* [Inject UI Component](./ui-components.md)
## Customizing the UI look-and-feel
* [UI customization](./ui-customization.md)

## Services and Events
* [UI manager services as HoC containers](./ui-manager-services.md)
* [Supported UI events](./events.md)
14 changes: 12 additions & 2 deletions docs/translations.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ A translation file may contain all the keys in the English translation, and any

## Choosing the display language

Setting the display language is done by defining the locale config option, where English is the default one.
Setting the display language is done by defining the `locale` config option, where English is the default one.

Only a locale that exist in the translations dictionary may be set, and setting a locale that doesn't exist will result in keeping the default one set.
> Only a locale that exist in the translations dictionary may be set, and setting a locale that doesn't exist will result in keeping the default one set.
```json5
{
"locale": "es", //set the desired locale
"translations": {
"en": {/*English dictionary*/},
"es": {/*Spanish dictionary*/}
}
}
```
6 changes: 6 additions & 0 deletions docs/ui-customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ An application can define its own UI layout and styling, by defining its presets

More information on how to build custom components and composing your own UI layout see [here](custom-ui-preset.md).

In addition, specific UI components can be defined and/or override instead of defining an entire UI preset

More information on how to build UI components and injecting them to UI see:
* [Create UI Component](./create-ui-component.md)
* [Inject UI Component](./ui-components.md)

## Removing style settings from the captions menu

The captions customizing level can be modified by removing settings from the captions setting menu.
Expand Down
9 changes: 9 additions & 0 deletions docs/ui-manager-services.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# UI manager services

The UI manager tries to separate concerns by allowing UI components to handle the presentational aspects.
In order to enable advanced use cases the manager exposes services as HoC that can inject those service to the component
without it having to take care of initialization or cleanup of the services.
The available services are:
* [withPlayer](./with-player.md) - exposes player instance to the component
* [withLogger](./with-logger.md) - exposes logger instance to the component
* [withEventManager](./with-logger.md) - exposes event manager instance to the component
143 changes: 143 additions & 0 deletions docs/with-event-manager.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
## Using an event manager in your component

### withEventManager HoC

If your components requires to listen to events then UI supplies an event manager as a service.
The event manager provides encapsulation over the document native event system, taking care of managing event registry per event and target and cleaning event listeners and upon component unmount to avoid memory leaks via the HoC.
In addition, the player, which is exposed via the [`withPlayer`](./with-player.md) HoC, is compatible as an event target that the event manager requires.
The HoC exposes the event manager to the wrapped component and will be accessible via the component props, i.e. `this.props.eventManager`.
Events can be added by `this.props.eventManager.listen(EVENT_TARGET, EVENT_NAME, EVENT_HANDLER)` or `listenOnce` which removes listener after first occurrence of the event.

Let's see an example, building on the [`withPlayer`](./with-player.md) sample:

> This sample will add a player `playing` event listener and prints it out to console when it is triggered.
```javascript
const h = KalturaPlayer.ui.h;
const withPlayer = KalturaPlayer.ui.components.withPlayer;
const withEventListener = KalturaPlayer.ui.components.withEventListener;
const Component = KalturaPlayer.ui.preact.Component;

class SampleComponent extends Component {
componentDidMount() {
this.props.eventManager.addEventListener(
this.props.player,
'playing',
() => {console.info('playing')}
);
}

componentWillUnount() {
// free resources here
}

render(props) {
return h(
'div',
{
className: 'dumb-component',
style: {
width: '40px',
height: '40px',
backgroundColor: 'red'
},
onClick: () => {
console.info(this.props.player.currentTime);
}
},
props.children
);
}
}

export default withEventListener(withPlayer(SampleComponent));
```

If you want to use JSX follow this [guide](./custom-ui-preset.md#using-jsx), and use following JSX syntax:

```javascript
const h = KalturaPlayer.ui.h;
const withPlayer = KalturaPlayer.ui.components.withPlayer;
const withEventListener = KalturaPlayer.ui.components.withEventListener;
const Component = KalturaPlayer.ui.preact.Component;

class DumbComponent extends Component {
componentDidMount() {
this.props.eventManager.addEventListener(
this.props.player,
'playing',
() => {console.info('playing')}
);
}
render(props) {
return <div
className="dumb-component"
style= {{
width: '40px',
height: '40px',
backgroundColor: 'red'
}}
onClick = {() => {
console.info(this.props.player.currentTime);
}}
>
{props.children}
</div>;
}
}

export default withEventListener(withPlayer(DumbComponent));
```

And if you want to use it as a decorator:

```javascript
const h = KalturaPlayer.ui.h;
const withPlayer = KalturaPlayer.ui.components.withPlayer;
const withEventListener = KalturaPlayer.ui.components.withEventListener;
const Component = KalturaPlayer.ui.preact.Component;

@withPlayer
@withEventListener
class DumbComponent extends Component {
componentDidMount() {
this.props.eventManager.addEventListener(
this.props.player,
'playing',
() => {console.info('playing')}
);
}
render(props) {
return <div
className="dumb-component"
style= {{
width: '40px',
height: '40px',
backgroundColor: 'red'
}}
onClick: {() => {
console.info(this.props.player.currentTime);
}}
>
{props.children}
</div>;
}
}

export default DumbComponent;
```

The usage of this component will be:

```javascript
const h = KalturaPlayer.ui.h;
h(DumbComponent, null, h('p', null, 'You can add here any components and html you want and it will be appended to the DumbComponent'));
```

Or again, if using JSX:

```html
<DumbComponent>
<p>You can add here any components and html you want and it will be appended to the DumbComponent</p>
</DumbComponent>
```

0 comments on commit f749921

Please sign in to comment.