Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/google-cast/src/google-cast.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { MediaStreamType } from '@videojs/media';
import type { HTMLMediaElementHost, HTMLMediaTargetLike, MediaComponent } from '@videojs/media/dom';
import type { HTMLMediaElementHost, HTMLMediaTargetLike, MediaExtension } from '@videojs/media/dom';

import { GoogleCastProvider } from './google-cast-provider';
import { requiresCastFramework } from './utils';
Expand All @@ -19,7 +19,7 @@ export interface GoogleCastExtensionProps {
customData?: Record<string, unknown> | null | undefined;
}

export class GoogleCastExtension implements GoogleCastExtensionProps, MediaComponent {
export class GoogleCastExtension implements GoogleCastExtensionProps, MediaExtension {
static defaultProps: GoogleCastExtensionProps = {
src: undefined,
contentType: undefined,
Expand Down
6 changes: 3 additions & 3 deletions packages/google-cast/src/tests/google-cast-provider.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { addMediaComponent, type HTMLMediaTargetLike, HTMLVideoElementHost } from '@videojs/media/dom';
import { addMediaExtension, type HTMLMediaTargetLike, HTMLVideoElementHost } from '@videojs/media/dom';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vite-plus/test';

import { GoogleCastProvider } from '../google-cast-provider';
Expand Down Expand Up @@ -108,7 +108,7 @@ describe('GoogleCastExtension', () => {

host.attach(target as Parameters<HTMLVideoElementHost['attach']>[0]);

addMediaComponent(host, new GoogleCastExtension());
addMediaExtension(host, new GoogleCastExtension());
expect(ensureCastFramework).not.toHaveBeenCalled();

// The component's override must expose `remote` as an accessor so host
Expand All @@ -123,7 +123,7 @@ describe('GoogleCastExtension', () => {

const host = new HTMLVideoElementHost();

addMediaComponent(host, new GoogleCastExtension());
addMediaExtension(host, new GoogleCastExtension());

void host.remote;

Expand Down
4 changes: 2 additions & 2 deletions packages/google-cast/src/tests/google-cast.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { addMediaComponent, HTMLVideoElementHost } from '@videojs/media/dom';
import { addMediaExtension, HTMLVideoElementHost } from '@videojs/media/dom';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vite-plus/test';

import { GoogleCastExtension } from '../index';
Expand Down Expand Up @@ -49,7 +49,7 @@ function setup() {

const googleCast = new GoogleCastExtension();

addMediaComponent(host, googleCast);
addMediaExtension(host, googleCast);

const provider = mocks.FakeProvider.instances.at(-1)!;

Expand Down
6 changes: 3 additions & 3 deletions packages/hlsjs-video/src/tests/hls-media.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MediaError, type RemotePlaybackLike } from '@videojs/media';
import { addMediaComponent, CustomMediaElement, type MediaComponent } from '@videojs/media/dom';
import { addMediaExtension, CustomMediaElement, type MediaExtension } from '@videojs/media/dom';
import { NativeHlsMedia } from '@videojs/native-hls-video';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vite-plus/test';

Expand Down Expand Up @@ -807,13 +807,13 @@ describe('HlsJsMedia', () => {

media.attach(video);

const component: MediaComponent = {
const component: MediaExtension = {
get targetOverride() {
return { remote: { state: 'connected' } as RemotePlaybackLike, load };
},
};

addMediaComponent(media, component);
addMediaExtension(media, component);

return { media };
}
Expand Down
4 changes: 2 additions & 2 deletions packages/html/src/extensions/google-cast/extension.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { PropertyDeclarationMap } from '@videojs/element';
import { GoogleCastExtension as GoogleCastExtensionBase, type GoogleCastExtensionProps } from '@videojs/google-cast';

import { MediaComponentElement } from '../media-component-element';
import { MediaExtensionElement } from '../media-extension-element';

/**
* Adds the Google Cast extension to the surrounding player's media.
Expand All @@ -16,7 +16,7 @@ import { MediaComponentElement } from '../media-component-element';
* </video-player>
* ```;
*/
export class GoogleCastExtension extends MediaComponentElement<GoogleCastExtensionBase> {
export class GoogleCastExtension extends MediaExtensionElement<GoogleCastExtensionBase> {
static readonly tagName = 'google-cast';

static override properties = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ContextConsumer } from '@videojs/element/context';
import {
addMediaComponent,
addMediaExtension,
HTMLMediaElementHost,
type HTMLMediaTargetLike,
type Media,
type MediaComponent,
type MediaExtension,
} from '@videojs/media/dom';

import { mediaContext } from '../player/context';
Expand All @@ -22,27 +22,27 @@ function resolveMediaHost(media: Media | null): MediaHost | null {
}

/**
* Abstract base for extension elements that register a media component (e.g. Mux Data, Google Cast) with the media
* Abstract base for extension elements that register a media extension (e.g. Mux Data, Google Cast) with the media
* provided by the surrounding player.
*
* Place inside a player, as a sibling of the media element. The component is registered when a media host becomes
* available, follows the media when it changes, is removed when this element disconnects, and is destroyed with this
* element.
*/
export abstract class MediaComponentElement<Component extends MediaComponent> extends UIElement {
export abstract class MediaExtensionElement<Component extends MediaExtension> extends UIElement {
#component: Component | null = null;
#host: MediaHost | null = null;
#removeComponent: (() => void) | null = null;

/**
* Create the media component this element registers. Called once, lazily.
* Create the media extension this element registers. Called once, lazily.
*
* Must be a method rather than a field: upgrading an element that is already in the document runs its constructor
* while connected, so the media context callback below can fire before subclass field initializers have run.
*/
protected abstract createComponent(): Component;

/** The media component instance registered with the media host. */
/** The media extension instance registered with the media host. */
protected get component(): Component {
return (this.#component ??= this.createComponent());
}
Expand Down Expand Up @@ -78,6 +78,6 @@ export abstract class MediaComponentElement<Component extends MediaComponent> ex
this.#removeComponent = null;
this.#host = host;

if (host) this.#removeComponent = addMediaComponent(host, this.component);
if (host) this.#removeComponent = addMediaExtension(host, this.component);
}
}
4 changes: 2 additions & 2 deletions packages/html/src/extensions/mux-data/extension.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { PropertyDeclarationMap } from '@videojs/element';
import { MuxDataExtension as MuxDataExtensionBase, type MuxDataExtensionProps } from '@videojs/mux-data';

import { MediaComponentElement } from '../media-component-element';
import { MediaExtensionElement } from '../media-extension-element';

/**
* Adds the [Mux Data](https://www.mux.com/data) extension to the surrounding player's media.
Expand All @@ -22,7 +22,7 @@ import { MediaComponentElement } from '../media-component-element';
* </video-player>
* ```;
*/
export class MuxDataExtension extends MediaComponentElement<MuxDataExtensionBase> {
export class MuxDataExtension extends MediaExtensionElement<MuxDataExtensionBase> {
static readonly tagName = 'mux-data';

static override properties = {
Expand Down
18 changes: 9 additions & 9 deletions packages/html/src/extensions/tests/google-cast.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ContextProvider } from '@videojs/element/context';
import { GoogleCastExtension as GoogleCastExtensionBase } from '@videojs/google-cast';
import { getMediaComponents, HTMLVideoElementHost, type Media } from '@videojs/media/dom';
import { getMediaExtensions, HTMLVideoElementHost, type Media } from '@videojs/media/dom';
import { afterEach, describe, expect, it } from 'vite-plus/test';

import { mediaContext } from '../../player/context';
Expand Down Expand Up @@ -42,7 +42,7 @@ describe('GoogleCastExtension', () => {

provider.setMedia(host as unknown as Media);

expect(getMediaComponents(host).get(GoogleCastExtensionBase)).toBeInstanceOf(GoogleCastExtensionBase);
expect(getMediaExtensions(host).get(GoogleCastExtensionBase)).toBeInstanceOf(GoogleCastExtensionBase);
});

it('leaves the component to the base class lazy getter', () => {
Expand All @@ -57,7 +57,7 @@ describe('GoogleCastExtension', () => {

provider.setMedia({ host } as unknown as Media);

expect(getMediaComponents(host).get(GoogleCastExtensionBase)).toBeInstanceOf(GoogleCastExtensionBase);
expect(getMediaExtensions(host).get(GoogleCastExtensionBase)).toBeInstanceOf(GoogleCastExtensionBase);
});

it('ignores media that is not a media host', () => {
Expand All @@ -66,7 +66,7 @@ describe('GoogleCastExtension', () => {
provider.setMedia(host as unknown as Media);
provider.setMedia(document.createElement('video') as unknown as Media);

expect(getMediaComponents(host).get(GoogleCastExtensionBase)).toBeUndefined();
expect(getMediaExtensions(host).get(GoogleCastExtensionBase)).toBeUndefined();
});

it('forwards attributes to the component', () => {
Expand All @@ -79,7 +79,7 @@ describe('GoogleCastExtension', () => {
el.setAttribute('stream-type', 'live');
el.setAttribute('src', 'https://example.com/stream.m3u8');

const component = getMediaComponents(host).get(GoogleCastExtensionBase)!;
const component = getMediaExtensions(host).get(GoogleCastExtensionBase)!;

expect(component.receiver).toBe('APP_ID');
expect(component.contentType).toBe('application/x-mpegURL');
Expand All @@ -105,8 +105,8 @@ describe('GoogleCastExtension', () => {
provider.setMedia(host as unknown as Media);
provider.setMedia(nextHost as unknown as Media);

expect(getMediaComponents(host).get(GoogleCastExtensionBase)).toBeUndefined();
expect(getMediaComponents(nextHost).get(GoogleCastExtensionBase)).toBeInstanceOf(GoogleCastExtensionBase);
expect(getMediaExtensions(host).get(GoogleCastExtensionBase)).toBeUndefined();
expect(getMediaExtensions(nextHost).get(GoogleCastExtensionBase)).toBeInstanceOf(GoogleCastExtensionBase);
});

it('removes the component when the element disconnects', () => {
Expand All @@ -116,7 +116,7 @@ describe('GoogleCastExtension', () => {

el.remove();

expect(getMediaComponents(host).get(GoogleCastExtensionBase)).toBeUndefined();
expect(getMediaExtensions(host).get(GoogleCastExtensionBase)).toBeUndefined();
});

it('removes the component on destroy', () => {
Expand All @@ -126,6 +126,6 @@ describe('GoogleCastExtension', () => {

el.destroy();

expect(getMediaComponents(host).get(GoogleCastExtensionBase)).toBeUndefined();
expect(getMediaExtensions(host).get(GoogleCastExtensionBase)).toBeUndefined();
});
});
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ContextProvider } from '@videojs/element/context';
import { getMediaComponents, HTMLVideoElementHost, type Media, type MediaComponent } from '@videojs/media/dom';
import { getMediaExtensions, HTMLVideoElementHost, type Media, type MediaExtension } from '@videojs/media/dom';
import { afterEach, describe, expect, it } from 'vite-plus/test';

import { mediaContext } from '../../player/context';
import { UIElement } from '../../ui/ui-element';
import { MediaComponentElement } from '../media-component-element';
import { MediaExtensionElement } from '../media-extension-element';

class FakeComponent implements MediaComponent {
class FakeComponent implements MediaExtension {
destroyed = false;
destroy() {
this.destroyed = true;
Expand All @@ -24,7 +24,7 @@ class TestMediaProvider extends UIElement {
}
}

class TestMediaComponentElement extends MediaComponentElement<FakeComponent> {
class TestMediaExtensionElement extends MediaExtensionElement<FakeComponent> {
static readonly tagName = 'test-media-component';

/**
Expand All @@ -44,15 +44,15 @@ class TestMediaComponentElement extends MediaComponentElement<FakeComponent> {
}

customElements.define('test-media-component-provider', TestMediaProvider);
customElements.define(TestMediaComponentElement.tagName, TestMediaComponentElement);
customElements.define(TestMediaExtensionElement.tagName, TestMediaExtensionElement);

afterEach(() => {
document.body.innerHTML = '';
});

describe('MediaComponentElement', () => {
describe('MediaExtensionElement', () => {
it('resolves the component before subclass fields initialize', () => {
const el = new TestMediaComponentElement();
const el = new TestMediaExtensionElement();

expect(el.componentDuringFieldInit).toBeInstanceOf(FakeComponent);
// Created once and reused, not re-created per access.
Expand All @@ -62,19 +62,19 @@ describe('MediaComponentElement', () => {
it('registers the extension component with the media host from context', () => {
const host = new HTMLVideoElementHost();
const provider = new TestMediaProvider();
const el = new TestMediaComponentElement();
const el = new TestMediaExtensionElement();

provider.append(el);
document.body.append(provider);
provider.setMedia(host as unknown as Media);

expect(getMediaComponents(host).get(FakeComponent)).toBe(el.instance);
expect(getMediaExtensions(host).get(FakeComponent)).toBe(el.instance);
});

it('destroys the component when the element is destroyed', () => {
const host = new HTMLVideoElementHost();
const provider = new TestMediaProvider();
const el = new TestMediaComponentElement();
const el = new TestMediaExtensionElement();

provider.append(el);
document.body.append(provider);
Expand All @@ -83,15 +83,15 @@ describe('MediaComponentElement', () => {
el.destroy();

expect(el.instance.destroyed).toBe(true);
expect(getMediaComponents(host).get(FakeComponent)).toBeUndefined();
expect(getMediaExtensions(host).get(FakeComponent)).toBeUndefined();
});

it('does not create a component when destroyed before use', () => {
const el = new TestMediaComponentElement();
const el = new TestMediaExtensionElement();

// `componentDuringFieldInit` already forced creation, so assert through a
// subclass that never touches it.
class Untouched extends MediaComponentElement<FakeComponent> {
class Untouched extends MediaExtensionElement<FakeComponent> {
created = 0;
protected createComponent(): FakeComponent {
this.created++;
Expand Down
12 changes: 6 additions & 6 deletions packages/html/src/extensions/tests/mux-data.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ContextProvider } from '@videojs/element/context';
import { getMediaComponents, HTMLVideoElementHost, type Media } from '@videojs/media/dom';
import { getMediaExtensions, HTMLVideoElementHost, type Media } from '@videojs/media/dom';
import { MuxDataExtension as MuxDataExtensionBase } from '@videojs/mux-data';
import { afterEach, describe, expect, it } from 'vite-plus/test';

Expand Down Expand Up @@ -49,7 +49,7 @@ describe('MuxDataExtension', () => {

provider.innerHTML = '<test-mux-data></test-mux-data>';

expect(getMediaComponents(host).get(MuxDataExtensionBase)).toBeInstanceOf(MuxDataExtensionBase);
expect(getMediaExtensions(host).get(MuxDataExtensionBase)).toBeInstanceOf(MuxDataExtensionBase);
});

it('leaves the component to the base class lazy getter', () => {
Expand All @@ -63,7 +63,7 @@ describe('MuxDataExtension', () => {

provider.setMedia(host as unknown as Media);

expect(getMediaComponents(host).get(MuxDataExtensionBase)).toBeInstanceOf(MuxDataExtensionBase);
expect(getMediaExtensions(host).get(MuxDataExtensionBase)).toBeInstanceOf(MuxDataExtensionBase);
});

it('forwards attributes to the component', () => {
Expand All @@ -77,7 +77,7 @@ describe('MuxDataExtension', () => {
el.setAttribute('debug', '');
el.setAttribute('disable-cookies', '');

const component = getMediaComponents(host).get(MuxDataExtensionBase)!;
const component = getMediaExtensions(host).get(MuxDataExtensionBase)!;

expect(component.envKey).toBe('test-key');
expect(component.playerSoftwareName).toBe('mux-video');
Expand All @@ -97,7 +97,7 @@ describe('MuxDataExtension', () => {

el.metadata = metadata;

expect(getMediaComponents(host).get(MuxDataExtensionBase)!.metadata).toEqual(metadata);
expect(getMediaExtensions(host).get(MuxDataExtensionBase)!.metadata).toEqual(metadata);
});

it('removes the component when the element disconnects', () => {
Expand All @@ -107,6 +107,6 @@ describe('MuxDataExtension', () => {

el.remove();

expect(getMediaComponents(host).get(MuxDataExtensionBase)).toBeUndefined();
expect(getMediaExtensions(host).get(MuxDataExtensionBase)).toBeUndefined();
});
});
Loading
Loading