mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 11:06:16 -08:00
refactor(playback): use signal APIs in VideoJS player
This commit is contained in:
1 parent
c6a87aa507
commit
c53799e2bc
2 files changed
+39
-19
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import { SimpleChange } from '@angular/core';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import type { VjsPlayerComponent as VjsPlayerComponentInstance } from './vjs-player.component';
|
||||
|
||||
const videoJsMock = jest.fn();
|
||||
@@ -23,21 +24,41 @@ describe('VjsPlayerComponent', () => {
|
||||
let VjsPlayerComponent: typeof import('./vjs-player.component').VjsPlayerComponent;
|
||||
let component: VjsPlayerComponentInstance;
|
||||
let player: VjsPlayerComponentInstance['player'];
|
||||
type SignalApiShape = {
|
||||
options: () => unknown;
|
||||
volume: () => number;
|
||||
startTime: () => number;
|
||||
timeUpdate: { emit: (event: unknown) => void };
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
({ VjsPlayerComponent } = await import('./vjs-player.component'));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
component = new VjsPlayerComponent();
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [VjsPlayerComponent],
|
||||
}).compileComponents();
|
||||
|
||||
component = TestBed.createComponent(VjsPlayerComponent).componentInstance;
|
||||
player = {
|
||||
src: jest.fn(),
|
||||
reset: jest.fn(),
|
||||
volume: jest.fn(),
|
||||
dispose: jest.fn(),
|
||||
} as unknown as VjsPlayerComponentInstance['player'];
|
||||
component.player = player;
|
||||
});
|
||||
|
||||
it('uses signal-based inputs and outputs', () => {
|
||||
const signalComponent = component as unknown as SignalApiShape;
|
||||
|
||||
expect(typeof signalComponent.options).toBe('function');
|
||||
expect(signalComponent.volume()).toBe(1);
|
||||
expect(signalComponent.startTime()).toBe(0);
|
||||
expect(typeof signalComponent.timeUpdate.emit).toBe('function');
|
||||
});
|
||||
|
||||
it('does not reset VideoJS when options change without changing the source', () => {
|
||||
const previousOptions = {
|
||||
sources: [
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import {
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output,
|
||||
SimpleChanges,
|
||||
ViewChild,
|
||||
ViewEncapsulation,
|
||||
input,
|
||||
output,
|
||||
viewChild,
|
||||
} from '@angular/core';
|
||||
import '@yangkghjh/videojs-aspect-ratio-panel';
|
||||
import { getExtensionFromUrl } from 'm3u-utils';
|
||||
@@ -88,16 +87,16 @@ type VideoJsPlayer = Omit<
|
||||
})
|
||||
export class VjsPlayerComponent implements OnInit, OnChanges, OnDestroy {
|
||||
/** DOM-element reference */
|
||||
@ViewChild('target', { static: true }) target!: ElementRef<Element>;
|
||||
readonly target = viewChild.required<ElementRef<Element>>('target');
|
||||
/** Options of VideoJs player */
|
||||
@Input() options!: VideoPlayerOptions;
|
||||
readonly options = input.required<VideoPlayerOptions>();
|
||||
/** VideoJs object */
|
||||
player!: VideoJsPlayer;
|
||||
/** mpegts.js player for raw MPEG-TS streams */
|
||||
private mpegtsPlayer: mpegts.Player | null = null;
|
||||
@Input() volume = 1;
|
||||
@Input() startTime = 0;
|
||||
@Output() timeUpdate = new EventEmitter<{
|
||||
readonly volume = input(1);
|
||||
readonly startTime = input(0);
|
||||
readonly timeUpdate = output<{
|
||||
currentTime: number;
|
||||
duration: number;
|
||||
}>();
|
||||
@@ -106,27 +105,27 @@ export class VjsPlayerComponent implements OnInit, OnChanges, OnDestroy {
|
||||
* Instantiate Video.js on component init
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
const source = this.options?.sources?.[0];
|
||||
const source = this.options().sources?.[0];
|
||||
const isMpegTs = this.isMpegTsSource(source?.src);
|
||||
|
||||
// For raw MPEG-TS streams, init Video.js without a source (UI/controls only)
|
||||
const vjsOptions = isMpegTs
|
||||
? { ...this.options, sources: [], autoplay: false }
|
||||
: { ...this.options, autoplay: true };
|
||||
? { ...this.options(), sources: [], autoplay: false }
|
||||
: { ...this.options(), autoplay: true };
|
||||
|
||||
this.player = videoJs(
|
||||
this.target.nativeElement,
|
||||
this.target().nativeElement,
|
||||
vjsOptions,
|
||||
() => {
|
||||
console.log(
|
||||
'Setting VideoJS player initial volume to:',
|
||||
this.volume
|
||||
this.volume()
|
||||
);
|
||||
this.player.volume(this.volume);
|
||||
this.player.volume(this.volume());
|
||||
|
||||
this.player.on('loadedmetadata', () => {
|
||||
if (this.startTime > 0) {
|
||||
this.player.currentTime(this.startTime);
|
||||
if (this.startTime() > 0) {
|
||||
this.player.currentTime(this.startTime());
|
||||
}
|
||||
this.logAudioTracks();
|
||||
this.setupAudioTrackMenu();
|
||||
|
||||
Reference in new issue
Block a user