Skip to content

Commit 09da06b

Browse files
committedNov 11, 2024·
fix(youtube-player): ready event not emitting
Fixes that the `youtube-player`'s `ready` event wasn't emitting. The issue is that we create the outputs lazily based on a stream of newly-created players, however that stream emits after the `ready` event. Relates to #29874. (cherry picked from commit 96afa88)
1 parent 2885987 commit 09da06b

File tree

3 files changed

+13
-14
lines changed

3 files changed

+13
-14
lines changed
 

‎src/youtube-player/youtube-player.spec.ts

-5
Original file line numberDiff line numberDiff line change
@@ -725,17 +725,12 @@ describe('YoutubePlayer', () => {
725725

726726
const player = noEventsApp.componentInstance.player;
727727
const subscriptions: Subscription[] = [];
728-
const readySpy = jasmine.createSpy('ready spy');
729728
const stateChangeSpy = jasmine.createSpy('stateChange spy');
730729
const playbackQualityChangeSpy = jasmine.createSpy('playbackQualityChange spy');
731730
const playbackRateChangeSpy = jasmine.createSpy('playbackRateChange spy');
732731
const errorSpy = jasmine.createSpy('error spy');
733732
const apiChangeSpy = jasmine.createSpy('apiChange spy');
734733

735-
subscriptions.push(player.ready.subscribe(readySpy));
736-
events.onReady({target: playerSpy});
737-
expect(readySpy).toHaveBeenCalledWith({target: playerSpy});
738-
739734
subscriptions.push(player.stateChange.subscribe(stateChangeSpy));
740735
events.onStateChange({target: playerSpy, data: 5});
741736
expect(stateChangeSpy).toHaveBeenCalledWith({target: playerSpy, data: 5});

‎src/youtube-player/youtube-player.ts

+13-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
CSP_NONCE,
3030
ChangeDetectorRef,
3131
AfterViewInit,
32+
EventEmitter,
3233
} from '@angular/core';
3334
import {isPlatformBrowser} from '@angular/common';
3435
import {Observable, of as observableOf, Subject, BehaviorSubject, fromEventPattern} from 'rxjs';
@@ -218,22 +219,29 @@ export class YouTubePlayer implements AfterViewInit, OnChanges, OnDestroy {
218219
*/
219220
@Input() placeholderImageQuality: PlaceholderImageQuality;
220221

221-
/** Outputs are direct proxies from the player itself. */
222-
@Output() readonly ready: Observable<YT.PlayerEvent> =
223-
this._getLazyEmitter<YT.PlayerEvent>('onReady');
222+
// Note: ready event can't go through the lazy emitter, because it
223+
// happens before the `_playerChanges` stream emits the new player.
224224

225+
/** Emits when the player is initialized. */
226+
@Output() readonly ready: Observable<YT.PlayerEvent> = new EventEmitter<YT.PlayerEvent>();
227+
228+
/** Emits when the state of the player has changed. */
225229
@Output() readonly stateChange: Observable<YT.OnStateChangeEvent> =
226230
this._getLazyEmitter<YT.OnStateChangeEvent>('onStateChange');
227231

232+
/** Emits when there's an error while initializing the player. */
228233
@Output() readonly error: Observable<YT.OnErrorEvent> =
229234
this._getLazyEmitter<YT.OnErrorEvent>('onError');
230235

236+
/** Emits when the underlying API of the player has changed. */
231237
@Output() readonly apiChange: Observable<YT.PlayerEvent> =
232238
this._getLazyEmitter<YT.PlayerEvent>('onApiChange');
233239

240+
/** Emits when the playback quality has changed. */
234241
@Output() readonly playbackQualityChange: Observable<YT.OnPlaybackQualityChangeEvent> =
235242
this._getLazyEmitter<YT.OnPlaybackQualityChangeEvent>('onPlaybackQualityChange');
236243

244+
/** Emits when the playback rate has changed. */
237245
@Output() readonly playbackRateChange: Observable<YT.OnPlaybackRateChangeEvent> =
238246
this._getLazyEmitter<YT.OnPlaybackRateChangeEvent>('onPlaybackRateChange');
239247

@@ -575,7 +583,7 @@ export class YouTubePlayer implements AfterViewInit, OnChanges, OnDestroy {
575583
}),
576584
);
577585

578-
const whenReady = () => {
586+
const whenReady = (event: YT.PlayerEvent) => {
579587
// Only assign the player once it's ready, otherwise YouTube doesn't expose some APIs.
580588
this._ngZone.run(() => {
581589
this._isLoading = false;
@@ -584,6 +592,7 @@ export class YouTubePlayer implements AfterViewInit, OnChanges, OnDestroy {
584592
this._pendingPlayer = undefined;
585593
player.removeEventListener('onReady', whenReady);
586594
this._playerChanges.next(player);
595+
(this.ready as EventEmitter<YT.PlayerEvent>).emit(event);
587596
this._setSize();
588597
this._setQuality();
589598

‎tools/public_api_guard/youtube-player/youtube-player.md

-5
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,10 @@ export const YOUTUBE_PLAYER_CONFIG: InjectionToken<YouTubePlayerConfig>;
2424
// @public
2525
export class YouTubePlayer implements AfterViewInit, OnChanges, OnDestroy {
2626
constructor(...args: unknown[]);
27-
// (undocumented)
2827
readonly apiChange: Observable<YT.PlayerEvent>;
2928
disableCookies: boolean;
3029
disablePlaceholder: boolean;
3130
endSeconds: number | undefined;
32-
// (undocumented)
3331
readonly error: Observable<YT.OnErrorEvent>;
3432
getAvailablePlaybackRates(): number[];
3533
getAvailableQualityLevels(): YT.SuggestedVideoQuality[];
@@ -77,9 +75,7 @@ export class YouTubePlayer implements AfterViewInit, OnChanges, OnDestroy {
7775
pauseVideo(): void;
7876
placeholderButtonLabel: string;
7977
placeholderImageQuality: PlaceholderImageQuality;
80-
// (undocumented)
8178
readonly playbackQualityChange: Observable<YT.OnPlaybackQualityChangeEvent>;
82-
// (undocumented)
8379
readonly playbackRateChange: Observable<YT.OnPlaybackRateChangeEvent>;
8480
playerVars: YT.PlayerVars | undefined;
8581
playVideo(): void;
@@ -90,7 +86,6 @@ export class YouTubePlayer implements AfterViewInit, OnChanges, OnDestroy {
9086
protected _shouldShowPlaceholder(): boolean;
9187
showBeforeIframeApiLoads: boolean;
9288
startSeconds: number | undefined;
93-
// (undocumented)
9489
readonly stateChange: Observable<YT.OnStateChangeEvent>;
9590
stopVideo(): void;
9691
suggestedQuality: YT.SuggestedVideoQuality | undefined;

0 commit comments

Comments
 (0)
Please sign in to comment.