Skip to content

Commit

Permalink
fix(player/react): captions component throws when switching view types
Browse files Browse the repository at this point in the history
  • Loading branch information
mihar-22 committed Jun 20, 2024
1 parent 9608ad3 commit 471f314
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 58 deletions.
9 changes: 7 additions & 2 deletions packages/react/src/components/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ interface MediaOutletProps extends React.HTMLAttributes<HTMLMediaElement> {
}

function MediaOutlet({ provider, ...props }: MediaOutletProps) {
const { crossOrigin, poster, remotePlaybackInfo, nativeControls } = useStateContext(mediaState),
const { crossOrigin, poster, remotePlaybackInfo, nativeControls, viewType } =
useStateContext(mediaState),
{ loader } = provider.$state,
{ $provider: $$provider, $providerSetup: $$providerSetup } = useMediaContext(),
$nativeControls = useSignal(nativeControls),
Expand All @@ -78,6 +79,8 @@ function MediaOutlet({ provider, ...props }: MediaOutletProps) {
$providerSetup = useSignal($$providerSetup),
$remoteInfo = useSignal(remotePlaybackInfo),
$mediaType = $loader?.mediaType(),
$viewType = useSignal(viewType),
isAudioView = $viewType === 'audio',
isYouTubeEmbed = $loader?.name === 'youtube',
isVimeoEmbed = $loader?.name === 'vimeo',
isEmbed = isYouTubeEmbed || isVimeoEmbed,
Expand Down Expand Up @@ -142,7 +145,9 @@ function MediaOutlet({ provider, ...props }: MediaOutletProps) {
provider.load(el);
},
}),
!$nativeControls ? React.createElement('div', { className: 'vds-blocker' }) : null,
!$nativeControls && !isAudioView
? React.createElement('div', { className: 'vds-blocker' })
: null,
)
: $mediaType
? React.createElement($mediaType === 'audio' ? 'audio' : 'video', {
Expand Down
3 changes: 2 additions & 1 deletion packages/vidstack/mangle.json
Original file line number Diff line number Diff line change
Expand Up @@ -784,5 +784,6 @@
"_calcNewKeyValue": "Dn",
"_repeatedKeys": "Bn",
"_setupMenuContainer": "En",
"_setupWatchScrubbing": "Fn"
"_setupWatchScrubbing": "Fn",
"_listenToFontStyleChanges": "Gn"
}
94 changes: 51 additions & 43 deletions packages/vidstack/src/components/ui/captions/captions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, effect, peek, scoped } from 'maverick.js';
import { Component, effect, peek, signal } from 'maverick.js';
import { listenEvent, setAttribute } from 'maverick.js/std';
import type { CaptionsRenderer } from 'media-captions';

Expand Down Expand Up @@ -33,9 +33,11 @@ export class Captions extends Component<CaptionsProps> {
};

private _media!: MediaContext;
private _renderer!: CaptionsRenderer;
private _textRenderer!: CaptionsTextRenderer;
private _lib!: typeof import('media-captions');

private static _lib = signal<typeof import('media-captions') | null>(null);
private get _lib() {
return Captions._lib;
}

protected override onSetup(): void {
this._media = useMediaContext();
Expand All @@ -49,45 +51,27 @@ export class Captions extends Component<CaptionsProps> {
}

protected override onConnect(el: HTMLElement) {
const player = this._media.player;
if (player) listenEvent(player, 'vds-font-change', this._onFontStyleChange.bind(this));

if (this._renderer) {
effect(this._watchViewType.bind(this));
return;
if (!this._lib()) {
import('media-captions').then((lib) => this._lib.set(lib));
}

import('media-captions').then((lib) => {
if (!this.connectScope) return;
scoped(() => {
this._lib = lib;
const { CaptionsRenderer } = this._lib;
this._renderer = new CaptionsRenderer(el);
this._textRenderer = new CaptionsTextRenderer(this._renderer);
effect(this._watchViewType.bind(this));
}, this.connectScope);
});
}

protected override onDestroy() {
if (this._textRenderer) {
this._textRenderer.detach();
this._media.textRenderers.remove(this._textRenderer);
}

this._renderer?.destroy();
effect(this._watchViewType.bind(this));
}

private _isHidden() {
const { textTrack, remotePlaybackState, iOSControls } = this._media.$state,
track = textTrack();

return (
iOSControls() || remotePlaybackState() === 'connected' || !track || !isTrackCaptionKind(track)
);
}

private _watchViewType() {
if (!this._lib()) return;

const { viewType } = this._media.$state;

if (viewType() === 'audio') {
return this._setupAudioView();
} else {
Expand All @@ -97,16 +81,22 @@ export class Captions extends Component<CaptionsProps> {

private _setupAudioView() {
effect(this._onTrackChange.bind(this));

this._listenToFontStyleChanges(null);

return () => {
this.el!.textContent = '';
};
}

private _onTrackChange() {
if (this._isHidden()) return;
const { textTrack } = this._media.$state;

this._onCueChange();

const { textTrack } = this._media.$state;
listenEvent(textTrack()!, 'cue-change', this._onCueChange.bind(this));

effect(this._onUpdateTimedNodes.bind(this));
}

Expand All @@ -118,7 +108,7 @@ export class Captions extends Component<CaptionsProps> {
}

const { realCurrentTime, textTrack } = this._media.$state,
{ renderVTTCueString } = this._lib,
{ renderVTTCueString } = this._lib()!,
time = peek(realCurrentTime),
activeCues = peek(textTrack)!.activeCues;

Expand All @@ -135,37 +125,55 @@ export class Captions extends Component<CaptionsProps> {

private _onUpdateTimedNodes() {
const { realCurrentTime } = this._media.$state,
{ updateTimedVTTCueNodes } = this._lib;
{ updateTimedVTTCueNodes } = this._lib()!;

updateTimedVTTCueNodes(this.el!, realCurrentTime());
}

private _setupVideoView() {
effect(this._watchTextDirection.bind(this));
effect(this._watchMediaTime.bind(this));
this._media.textRenderers.add(this._textRenderer);
const { CaptionsRenderer } = this._lib()!,
renderer = new CaptionsRenderer(this.el!),
textRenderer = new CaptionsTextRenderer(renderer);

this._media.textRenderers.add(textRenderer);

effect(this._watchTextDirection.bind(this, renderer));
effect(this._watchMediaTime.bind(this, renderer));

this._listenToFontStyleChanges(renderer);

return () => {
this.el!.textContent = '';
this._textRenderer.detach();
this._media.textRenderers.remove(this._textRenderer);
this._media.textRenderers.remove(textRenderer);
renderer.destroy();
};
}

private _watchTextDirection() {
this._renderer.dir = this.$props.textDir();
private _watchTextDirection(renderer: CaptionsRenderer) {
renderer.dir = this.$props.textDir();
}

private _watchMediaTime() {
private _watchMediaTime(renderer: CaptionsRenderer) {
if (this._isHidden()) return;

const { realCurrentTime, textTrack } = this._media.$state;
this._renderer.currentTime = realCurrentTime();

renderer.currentTime = realCurrentTime();

if (this._hideExampleTimer >= 0 && textTrack()?.activeCues[0]) {
this._removeExample();
}
}

private _onFontStyleChange() {
private _listenToFontStyleChanges(renderer: CaptionsRenderer | null) {
const player = this._media.player;
if (!player) return;

const onChange = this._onFontStyleChange.bind(this, renderer);
listenEvent(player, 'vds-font-change', onChange);
}

private _onFontStyleChange(renderer: CaptionsRenderer | null) {
if (this._hideExampleTimer >= 0) {
this._hideExample();
return;
Expand All @@ -176,7 +184,7 @@ export class Captions extends Component<CaptionsProps> {
if (!textTrack()?.activeCues[0]) {
this._showExample();
} else {
this._renderer?.update(true);
renderer?.update(true);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { effect, onDispose } from 'maverick.js';
import { effect, onDispose, peek, untrack } from 'maverick.js';
import { listenEvent } from 'maverick.js/std';

import type { MediaContext } from '../../../api/media-context';
Expand Down Expand Up @@ -34,13 +34,13 @@ export class TextRenderers {

add(renderer: TextRenderer) {
this._renderers.push(renderer);
this._update();
untrack(this._update.bind(this));
}

remove(renderer: TextRenderer) {
renderer.detach();
this._renderers.splice(this._renderers.indexOf(renderer), 1);
this._update();
untrack(this._update.bind(this));
}

/** @internal */
Expand Down
23 changes: 14 additions & 9 deletions packages/vidstack/src/elements/define/provider-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,24 @@ export class MediaProviderElement extends Host(HTMLElement, MediaProvider) {

if (isEmbed && target) {
effect(() => {
const { nativeControls } = this._media.$state,
showControls = nativeControls();

if (showControls) {
const { nativeControls, viewType } = this._media.$state,
showNativeControls = nativeControls(),
isAudioView = viewType() === 'audio',
showBlocker = showNativeControls && !isAudioView;

if (showBlocker) {
this._blocker = this.querySelector('.vds-blocker');
if (!this._blocker) {
this._blocker = document.createElement('div');
this._blocker.classList.add('vds-blocker');
target.after(this._blocker);
}
} else {
this._blocker?.remove();
this._blocker = null;
} else {
this._blocker = this.querySelector('.vds-blocker') ?? document.createElement('div');
this._blocker.classList.add('vds-blocker');
target.after(this._blocker);
}

setAttribute(target, 'data-no-controls', !showControls);
setAttribute(target, 'data-no-controls', !showNativeControls);
});
}
}
Expand Down

0 comments on commit 471f314

Please sign in to comment.