File
Metadata
selector |
app-player |
templateUrl |
player.component.html |
contentProgressEvents$
|
Type: Subject<any>
|
Constructor
constructor(configService: any, router: Router, toasterService: any, resourceService: any, navigationHelperService: any)
|
Methods
loadCdnPlayer
|
loadCdnPlayer()
|
Returns: void
|
loadDefaultPlayer
|
loadDefaultPlayer(url: any)
|
Returns: void
|
loadPlayer
|
loadPlayer()
|
Initializes player with given config and emits player telemetry events Emits event when content starts playing and end event when content was played/read completely
Returns: void
|
setPlayerType
|
setPlayerType()
|
Returns: void
|
adjustPlayerHeight
|
adjustPlayerHeight()
|
Adjust player height after load
Returns: void
|
generateScoreSubmitEvent
|
generateScoreSubmitEvent(event: any)
|
Returns: void
|
generateContentReadEvent
|
generateContentReadEvent(event: any, newPlayerEvent: any)
|
Returns: void
|
eventHandler
|
eventHandler(event: any)
|
Returns: void
|
emitSceneChangeEvent
|
emitSceneChangeEvent(timer: number)
|
Returns: void
|
showRatingPopup
|
showRatingPopup(event: any)
|
Returns: void
|
buildNumber
|
buildNumber: string
|
configService
|
configService: any
|
CONSTANT
|
CONSTANT: { ACCESSEVENT: string; }
|
contentIframe
|
contentIframe: any
|
contentRatingModal
|
contentRatingModal: boolean
|
Default value: false
|
isCdnWorking
|
isCdnWorking: string
|
modal
|
modal: any
|
Dom element reference of contentRatingModal
|
navigationHelperService
|
navigationHelperService: any
|
playerLoaded
|
playerLoaded: boolean
|
Default value: false
|
Public playerType
|
playerType: string
|
previewCdnUrl
|
previewCdnUrl: string
|
resourceService
|
resourceService: any
|
import { ConfigService, NavigationHelperService } from '@sunbird/shared';
import { Component, AfterViewInit, ViewChild, ElementRef, Input, Output, EventEmitter, OnChanges } from '@angular/core';
import * as _ from 'lodash-es';
import { PlayerConfig } from '@sunbird/shared';
import { environment } from '@sunbird/environment';
import { Router } from '@angular/router';
import { ToasterService, ResourceService } from '@sunbird/shared';
const OFFLINE_ARTIFACT_MIME_TYPES = ['application/epub', 'video/webm', 'video/mp4', 'application/pdf'];
import { Subject } from 'rxjs';
@Component({
selector: 'app-player',
templateUrl: './player.component.html'
})
export class PlayerComponent implements AfterViewInit, OnChanges {
@Input() playerConfig: PlayerConfig;
@Output() assessmentEvents = new EventEmitter<any>();
@Output() questionScoreSubmitEvents = new EventEmitter<any>();
@ViewChild('contentIframe') contentIframe: ElementRef;
@Output() playerOnDestroyEvent = new EventEmitter<any>();
@Output() sceneChangeEvent = new EventEmitter<any>();
@Input() contentProgressEvents$: Subject<any>;
playerLoaded = false;
buildNumber: string;
@Input() playerOption: any;
contentRatingModal = false;
previewCdnUrl: string;
isCdnWorking: string;
public playerType: string;
CONSTANT = {
ACCESSEVENT: 'renderer:question:submitscore'
};
/**
* Dom element reference of contentRatingModal
*/
@ViewChild('modal') modal;
constructor(public configService: ConfigService, public router: Router, private toasterService: ToasterService,
public resourceService: ResourceService, public navigationHelperService: NavigationHelperService) {
this.buildNumber = (<HTMLInputElement>document.getElementById('buildNumber'))
? (<HTMLInputElement>document.getElementById('buildNumber')).value : '1.0';
this.previewCdnUrl = (<HTMLInputElement>document.getElementById('previewCdnUrl'))
? (<HTMLInputElement>document.getElementById('previewCdnUrl')).value : undefined;
this.isCdnWorking = (<HTMLInputElement>document.getElementById('cdnWorking'))
? (<HTMLInputElement>document.getElementById('cdnWorking')).value : 'no';
}
/**
* loadPlayer method will be called
*/
ngAfterViewInit() {
if (this.playerConfig) {
this.loadPlayer();
}
}
ngOnChanges() {
this.contentRatingModal = false;
if (this.playerConfig) {
this.loadPlayer();
// if (this.playerLoaded) {
// const playerElement = this.contentIframe.nativeElement;
// playerElement.contentWindow.initializePreview(this.playerConfig);
// } else {
// this.loadPlayer();
// }
}
}
loadCdnPlayer() {
const iFrameSrc = this.configService.appConfig.PLAYER_CONFIG.cdnUrl + '&build_number=' + this.buildNumber;
setTimeout(() => {
const playerElement = this.contentIframe.nativeElement;
playerElement.src = iFrameSrc;
playerElement.onload = (event) => {
try {
this.adjustPlayerHeight();
this.playerLoaded = true;
playerElement.contentWindow.initializePreview(this.playerConfig);
playerElement.addEventListener('renderer:telemetry:event', telemetryEvent => this.generateContentReadEvent(telemetryEvent));
window.frames['contentPlayer'].addEventListener('message', accessEvent => this.generateScoreSubmitEvent(accessEvent), false);
} catch (err) {
console.log('loading cdn player failed', err);
this.loadDefaultPlayer();
}
};
}, 0);
}
loadDefaultPlayer(url = this.configService.appConfig.PLAYER_CONFIG.baseURL) {
const iFrameSrc = url + '&build_number=' + this.buildNumber;
setTimeout(() => {
const playerElement = this.contentIframe.nativeElement;
playerElement.src = iFrameSrc;
playerElement.onload = (event) => {
try {
this.adjustPlayerHeight();
this.playerLoaded = true;
playerElement.contentWindow.initializePreview(this.playerConfig);
playerElement.addEventListener('renderer:telemetry:event', telemetryEvent => this.generateContentReadEvent(telemetryEvent));
window.frames['contentPlayer'].addEventListener('message', accessEvent => this.generateScoreSubmitEvent(accessEvent), false);
} catch (err) {
console.log('loading default player failed', err);
const prevUrls = this.navigationHelperService.history;
if (this.isCdnWorking.toLowerCase() === 'yes' && prevUrls[prevUrls.length - 2]) {
history.back();
}
}
};
}, 0);
}
/**
* Initializes player with given config and emits player telemetry events
* Emits event when content starts playing and end event when content was played/read completely
*/
loadPlayer() {
this.playerType = 'default-player';
this.setPlayerType();
if (this.playerType === 'default-player') {
if (_.includes(this.router.url, 'browse') && environment.isOffline) {
this.loadDefaultPlayer(`${this.configService.appConfig.PLAYER_CONFIG.localBaseUrl}webview=true`);
return;
} else if (environment.isOffline) {
if (_.get(this.playerConfig, 'metadata.artifactUrl')
&& _.includes(OFFLINE_ARTIFACT_MIME_TYPES, this.playerConfig.metadata.mimeType)) {
const artifactFileName = this.playerConfig.metadata.artifactUrl.split('/');
this.playerConfig.metadata.artifactUrl = artifactFileName[artifactFileName.length - 1];
}
this.loadDefaultPlayer(this.configService.appConfig.PLAYER_CONFIG.localBaseUrl);
return;
}
if (this.previewCdnUrl !== '' && (this.isCdnWorking).toLowerCase() === 'yes') {
this.loadCdnPlayer();
return;
}
this.loadDefaultPlayer();
} else {
this.adjustPlayerHeight();
if (this.playerType !== 'epub-player') {
this.playerConfig.config = {};
}
}
}
setPlayerType() {
const playerType = _.get(this.configService.appConfig.PLAYER_CONFIG, 'playerType');
_.forIn(playerType, (value, key) => {
if (value.length) {
if (_.includes(value, _.get(this.playerConfig, 'metadata.mimeType'))) {
this.playerType = key;
}
}
});
}
/**
* Adjust player height after load
*/
adjustPlayerHeight() {
const playerWidth = $('#contentPlayer').width();
if (playerWidth) {
const height = playerWidth * (9 / 16);
$('#contentPlayer').css('height', height + 'px');
}
}
generateScoreSubmitEvent(event: any) {
if (event.data.toLowerCase() === (this.CONSTANT.ACCESSEVENT).toLowerCase()) {
this.questionScoreSubmitEvents.emit(event);
}
}
generateContentReadEvent(event: any, newPlayerEvent?) {
let eventCopy = newPlayerEvent ? _.cloneDeep(event) : event;
if (!eventCopy) {
return;
}
if (newPlayerEvent) {
eventCopy = { detail: {telemetryData: eventCopy}};
}
const eid = _.get(eventCopy, 'detail.telemetryData.eid');
if (eid && (eid === 'START' || eid === 'END')) {
this.showRatingPopup(eventCopy);
if (this.contentProgressEvents$) {
this.contentProgressEvents$.next(eventCopy);
}
} else if (eid && (eid === 'IMPRESSION')) {
this.emitSceneChangeEvent();
}
if (eid && (eid === 'ASSESS') || eid === 'START' || eid === 'END') {
this.assessmentEvents.emit(eventCopy);
}
}
eventHandler(event) {
}
emitSceneChangeEvent(timer = 0) {
setTimeout(() => {
const stageId = this.contentIframe.nativeElement.contentWindow.EkstepRendererAPI.getCurrentStageId();
const eventData = { stageId };
this.sceneChangeEvent.emit(eventData);
}, timer); // waiting for player to load, then fetching stageId (if we dont wait stageId will be undefined)
}
showRatingPopup(event) {
let contentProgress;
const playerSummary: Array<any> = _.get(event, 'detail.telemetryData.edata.summary');
if (playerSummary) {
contentProgress = _.find(event.detail.telemetryData.edata.summary, 'progress');
}
if (event.detail.telemetryData.eid === 'END' && contentProgress.progress === 100) {
this.contentRatingModal = true;
if (this.modal) {
this.modal.showContentRatingModal = true;
}
}
}
}