File

src/app/player/player.page.ts

Implements

OnInit OnDestroy PlayerActionHandlerDelegate

Metadata

Index

Properties
Methods

Constructor

constructor(courseService: CourseService, profileService: ProfileService, contentService: ContentService, playerService: PlayerService, preferences: SharedPreferences, canvasPlayerService: CanvasPlayerService, platform: Platform, screenOrientation: ScreenOrientation, appGlobalService: AppGlobalService, statusBar: StatusBar, events: Events, alertCtrl: AlertController, commonUtilService: CommonUtilService, route: ActivatedRoute, router: Router, location: Location, popoverCtrl: PopoverController, formAndFrameworkUtilService: FormAndFrameworkUtilService, downloadPdfService: DownloadPdfService, fileOpener: FileOpener, transfer: FileTransfer, telemetryGeneratorService: TelemetryGeneratorService, printPdfService: PrintPdfService, file: File)
Parameters :
Name Type Optional
courseService CourseService No
profileService ProfileService No
contentService ContentService No
playerService PlayerService No
preferences SharedPreferences No
canvasPlayerService CanvasPlayerService No
platform Platform No
screenOrientation ScreenOrientation No
appGlobalService AppGlobalService No
statusBar StatusBar No
events Events No
alertCtrl AlertController No
commonUtilService CommonUtilService No
route ActivatedRoute No
router Router No
location Location No
popoverCtrl PopoverController No
formAndFrameworkUtilService FormAndFrameworkUtilService No
downloadPdfService DownloadPdfService No
fileOpener FileOpener No
transfer FileTransfer No
telemetryGeneratorService TelemetryGeneratorService No
printPdfService PrintPdfService No
file File No

Methods

checkIsPlayerEnabled
checkIsPlayerEnabled(config, playerType)
Parameters :
Name Optional
config No
playerType No
Returns : any
closeIframe
closeIframe(content?: any)

This will close the player page and will fire some end telemetry events from the player

Parameters :
Name Type Optional
content any Yes
Returns : void
downloadFileIos
downloadFileIos(content)
Parameters :
Name Optional
content No
Returns : void
Async getNewPlayerConfiguration
getNewPlayerConfiguration()
Returns : unknown
getNextContent
getNextContent(hierarchyInfo, identifier)
Parameters :
Name Optional
hierarchyInfo No
identifier No
Returns : any
handleDownload
handleDownload()
Returns : void
handleNavBackButton
handleNavBackButton()
Returns : void
Async ionViewWillEnter
ionViewWillEnter()
Returns : any
Async ionViewWillLeave
ionViewWillLeave()
Returns : any
Private isJSON
isJSON(input)
Parameters :
Name Optional
input No
Returns : boolean
ngOnDestroy
ngOnDestroy()
Returns : void
Async ngOnInit
ngOnInit()
Returns : any
onContentNotFound
onContentNotFound(identifier: string, hierarchyInfo: Array<HierarchyInfo>)

This will trigger from player/ iframe when it unable to find consecutive content

Parameters :
Name Type Optional Description
identifier string No

Content Identifier

hierarchyInfo Array<HierarchyInfo> No

Object of content hierarchy

Returns : void
onUserSwitch
onUserSwitch(selectedUser: User)

This is an callback to mobile when player switches user

Parameters :
Name Type Optional Description
selectedUser User No

User id of the newly selected user by player

Returns : void
Async openPDF
openPDF(url)
Parameters :
Name Optional
url No
Returns : any
Async playerEvents
playerEvents(event)
Parameters :
Name Optional
event No
Returns : any
playerTelemetryEvents
playerTelemetryEvents(event)
Parameters :
Name Optional
event No
Returns : void
playNextContent
playNextContent()
Returns : void
Async showConfirm
showConfirm()

This will show confirmation box while leaving the player, it will fire some telemetry events from the player.

Returns : any
toggleDeviceOrientation
toggleDeviceOrientation()
Returns : void
Private updateContentState
updateContentState()
Returns : void

Properties

backButtonSubscription
Type : Subscription
config
Type : object
Default value : {}
Private content
Type : Content
corRelationList
course
Type : Course
Private isChildContent
Type : boolean
Private isCourse
Default value : false
isExitPopupShown
Default value : false
Private navigateBackToContentDetails
Type : boolean
Private navigateBackToTrackableCollection
Type : boolean
nextContentToBePlayed
Type : Content
Public objRollup
Type : Rollup
pauseSubscription
Type : any
playerConfig
Type : any
playerType
Type : string
previewElement
Type : ElementRef
Decorators :
@ViewChild('preview', {static: false})
import { AppOrientation } from './../app.constant';
import { ActivatedRoute, Router } from '@angular/router';
import { CanvasPlayerService } from '@app/services/canvas-player.service';
import { AppGlobalService } from '@app/services/app-global-service.service';
import { CommonUtilService } from '@app/services/common-util.service';
import { Component, OnInit, ViewChild, ElementRef, Inject, OnDestroy } from '@angular/core';
import { Platform, AlertController, PopoverController } from '@ionic/angular';
import { Events } from '@app/util/events';
import { ScreenOrientation } from '@ionic-native/screen-orientation/ngx';
import { PlayerActionHandlerDelegate, HierarchyInfo, User } from './player-action-handler-delegate';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { EventTopics, ProfileConstants, RouterLinks, ShareItemType, PreferenceKey } from '../app.constant';
import { Location } from '@angular/common';
import { Subscription } from 'rxjs';
import {
  CourseService,
  Course,
  Content,
  Rollup,
  InteractType,
  UpdateContentStateTarget,
  UpdateContentStateRequest,
  TelemetryErrorCode,
  ErrorType, SunbirdSdk, ProfileService, ContentService,
  PlayerService,
  SharedPreferences
} from 'sunbird-sdk';
import { Environment, FormAndFrameworkUtilService, InteractSubtype, PageId, TelemetryGeneratorService } from '@app/services';
import { SbSharePopupComponent } from '../components/popups/sb-share-popup/sb-share-popup.component';
import { DownloadPdfService } from '@app/services/download-pdf/download-pdf.service';
import { FileOpener } from '@ionic-native/file-opener/ngx';
import { FileTransfer, FileTransferObject } from '@ionic-native/file-transfer/ngx';
import { ContentUtil } from '@app/util/content-util';
import { PrintPdfService } from '@app/services/print-pdf/print-pdf.service';
import { FormConstants } from '../form.constants';
import { File } from '@ionic-native/file/ngx';

declare const cordova;


@Component({
  selector: 'app-player',
  templateUrl: './player.page.html',
})

export class PlayerPage implements OnInit, OnDestroy, PlayerActionHandlerDelegate {

  config = {};
  backButtonSubscription: Subscription;
  course: Course;
  pauseSubscription: any;
  private navigateBackToContentDetails: boolean;
  private navigateBackToTrackableCollection: boolean;
  corRelationList;
  private isCourse = false;
  playerConfig: any;
  private isChildContent: boolean;
  private content: Content;
  public objRollup: Rollup;
  nextContentToBePlayed: Content;
  playerType: string;
  isExitPopupShown = false;


  @ViewChild('preview', { static: false }) previewElement: ElementRef;
  constructor(
    @Inject('COURSE_SERVICE') private courseService: CourseService,
    @Inject('PROFILE_SERVICE') private profileService: ProfileService,
    @Inject('CONTENT_SERVICE') private contentService: ContentService,
    @Inject('PLAYER_SERVICE') private playerService: PlayerService,
    @Inject('SHARED_PREFERENCES') private preferences: SharedPreferences,
    private canvasPlayerService: CanvasPlayerService,
    private platform: Platform,
    private screenOrientation: ScreenOrientation,
    private appGlobalService: AppGlobalService,
    private statusBar: StatusBar,
    private events: Events,
    private alertCtrl: AlertController,
    private commonUtilService: CommonUtilService,
    private route: ActivatedRoute,
    private router: Router,
    private location: Location,
    private popoverCtrl: PopoverController,
    private formAndFrameworkUtilService: FormAndFrameworkUtilService,
    private downloadPdfService: DownloadPdfService,
    private fileOpener: FileOpener,
    private transfer: FileTransfer,
    private telemetryGeneratorService: TelemetryGeneratorService,
    private printPdfService: PrintPdfService,
    private file: File,
  ) {
    this.canvasPlayerService.handleAction();

    // Binding following methods to making it available to content player which is an iframe
    (window as any).onContentNotFound = this.onContentNotFound.bind(this);
    (window as any).onUserSwitch = this.onUserSwitch.bind(this);

    if (this.router.getCurrentNavigation().extras.state) {
      this.content = this.router.getCurrentNavigation().extras.state.contentToPlay;
      this.config = this.router.getCurrentNavigation().extras.state.config;
      this.course = this.router.getCurrentNavigation().extras.state.course;
      this.navigateBackToContentDetails = this.router.getCurrentNavigation().extras.state.navigateBackToContentDetails;
      this.corRelationList = this.router.getCurrentNavigation().extras.state.corRelation;
      this.isCourse = this.router.getCurrentNavigation().extras.state.isCourse;
      this.isChildContent = this.router.getCurrentNavigation().extras.state.childContent;
    }
  }

  async ngOnInit() {
    this.playerConfig = await this.formAndFrameworkUtilService.getPdfPlayerConfiguration();
    if(this.config['metadata'].hierarchyInfo) {
      await this.getNextContent(this.config['metadata'].hierarchyInfo , this.config['metadata'].identifier)
    }
    if (this.config['metadata']['mimeType'] === 'application/pdf' && this.checkIsPlayerEnabled(this.playerConfig , 'pdfPlayer').name === "pdfPlayer") {
      this.screenOrientation.lock(this.screenOrientation.ORIENTATIONS.LANDSCAPE);
      this.config = await this.getNewPlayerConfiguration();
      this.playerType = 'sunbird-pdf-player'
    } else if (this.config['metadata']['mimeType'] === "application/epub" && this.checkIsPlayerEnabled(this.playerConfig , 'epubPlayer').name === "epubPlayer"){ 
      this.screenOrientation.lock(this.screenOrientation.ORIENTATIONS.LANDSCAPE);
      this.config = await this.getNewPlayerConfiguration();
      this.config['config'].sideMenu.showPrint = false;
      this.playerType = 'sunbird-epub-player'
    } else if(this.config['metadata']['mimeType'] === "application/vnd.sunbird.questionset" && this.checkIsPlayerEnabled(this.playerConfig , 'qumlPlayer').name === "qumlPlayer"){
      this.screenOrientation.lock(this.screenOrientation.ORIENTATIONS.LANDSCAPE);
      this.config = await this.getNewPlayerConfiguration();
      this.config['config'].sideMenu.showDownload = false;
      this.config['config'].sideMenu.showPrint = false;
      this.config['config'].showDeviceOrientation = true
      this.config['metadata']['children'] = (await this.contentService.getQuestionSetChildren(this.config['metadata']['identifier']))
      this.playerType = 'sunbird-quml-player';
    } else if(["video/mp4", "video/webm"].includes(this.config['metadata']['mimeType']) && this.checkIsPlayerEnabled(this.playerConfig , 'videoPlayer').name === "videoPlayer"){
      if(!this.platform.is('ios')){
        this.screenOrientation.lock(this.screenOrientation.ORIENTATIONS.LANDSCAPE);
      }
      this.config = await this.getNewPlayerConfiguration();
      this.config['config'].sideMenu.showPrint = false;
       this.playerType = 'sunbird-video-player';
    } else {
      this.playerType = 'sunbird-old-player';
    }
    this.config['context'].dispatcher = {
      dispatch: function (event) {
        SunbirdSdk.instance.telemetryService.saveTelemetry(JSON.stringify(event)).subscribe(
          (res) => console.log('response after telemetry', res),
        );
      }
    };

    this.pauseSubscription = this.platform.pause.subscribe(() => {
      const iframes = window.document.getElementsByTagName('iframe');
      if (iframes.length > 0) {
        iframes[0].contentWindow.postMessage('pause.youtube', window.parent.origin);
      }
    });

    this.isExitPopupShown = false;
  }
  async ionViewWillEnter() {
    const playerInterval = setInterval(async () => {
      if (this.playerType === 'sunbird-old-player') {
        this.screenOrientation.lock(this.screenOrientation.ORIENTATIONS.LANDSCAPE);
        this.statusBar.hide();
        this.config['uid'] = this.config['context'].actor.id;
        this.config['metadata'].basePath = '/_app_file_' + this.config['metadata'].basePath;

        if (this.config['metadata'].isAvailableLocally) {
          this.config['metadata'].contentData.streamingUrl = '/_app_file_' + this.config['metadata'].contentData.streamingUrl;
        }
        if (!this.config['config'].whiteListUrl || !this.config['config'].whiteListUrl.length) {
          const utilityConfigFields = await this.formAndFrameworkUtilService.getFormFields(FormConstants.UTILITY_CONFIG);
          if (utilityConfigFields && utilityConfigFields.length) {
            const utilityPlayerConfig = utilityConfigFields.find((config) => config.code === 'config')['config'];
            if (utilityPlayerConfig && utilityPlayerConfig.v1 && utilityPlayerConfig.v1.whitelistUrl
              && utilityPlayerConfig.v1.whitelistUrl.length) {
              this.config['config']['whiteListUrl'] = utilityPlayerConfig.v1.whitelistUrl;
            }
          }
        }
        if (this.previewElement?.nativeElement) {
          clearInterval(playerInterval);
          // This is to reload a iframe as iframes reload method not working on cross-origin.
          const src = this.previewElement.nativeElement.src;
          this.previewElement.nativeElement.src = '';
          this.previewElement.nativeElement.src = src;
          this.previewElement.nativeElement.onload = () => {
            setTimeout(() => {
              this.previewElement.nativeElement.contentWindow['cordova'] = window['cordova'];
              this.previewElement.nativeElement.contentWindow['Media'] = window['Media'];
              this.previewElement.nativeElement.contentWindow['initializePreview'](this.config);
              this.previewElement.nativeElement.contentWindow.addEventListener('message', resp => {
                if (resp.data === 'renderer:question:submitscore') {
                  this.courseService.syncAssessmentEvents().subscribe();
                } else if (resp.data === 'renderer:question:reviewAssessment') {
                  this.courseService.clearAssessments().subscribe();
                } else if (resp.data && typeof resp.data === 'object') {
                  if (resp.data['player.pdf-renderer.error']) {
                    const pdfError = resp.data['player.pdf-renderer.error'];
                    if (pdfError.name === 'MissingPDFException') {
                      const downloadUrl = this.config['metadata']['contentData']['streamingUrl'] ||
                        this.config['metadata']['contentData']['artifactUrl'];
                      this.telemetryGeneratorService.generateInteractTelemetry(
                        InteractType.TOUCH,
                        InteractSubtype.DOWNLOAD_PDF_CLICKED,
                        Environment.PLAYER,
                        PageId.PLAYER,
                        ContentUtil.getTelemetryObject(this.config['metadata']['contentData']),
                        undefined,
                        ContentUtil.generateRollUp(this.config['metadata']['hierarchyInfo'], this.config['metadata']['identifier']));
                      this.openPDF(downloadUrl);
                    }
                  } else if (resp.data && resp.data.event === 'renderer:contentNotComaptible'
                    || resp.data && resp.data.data.event === 'renderer:contentNotComaptible') {
                    cordova.plugins.InAppUpdateManager.checkForImmediateUpdate(
                      () => { },
                      () => { }
                    );
                  } else if (resp.data && resp.data.event === 'renderer:maxLimitExceeded') {
                    this.closeIframe();
                  }
                } else if (this.isJSON(resp.data)) {
                  const response = JSON.parse(resp.data);
                  if (response.event === 'renderer:navigate') {
                    this.navigateBackToTrackableCollection = true;
                    this.navigateBackToContentDetails = false;
                    this.closeIframe({
                      identifier: response.data.identifier
                    });
                  }
                }
              });
            }, 1000);
          };
        }
      }
    }, 500);

    this.backButtonSubscription = this.platform.backButton.subscribeWithPriority(10, async () => {
      const activeAlert = await this.alertCtrl.getTop();
      if (!activeAlert) {
        this.showConfirm();
      }
    });

    this.events.subscribe('endGenieCanvas', (res) => {
      if (res.showConfirmBox) {
        this.showConfirm();
      } else {
        this.closeIframe();
      }
    });
  }

  toggleDeviceOrientation() {
    if (this.screenOrientation.type.includes(AppOrientation.LANDSCAPE.toLocaleLowerCase())) {
      this.screenOrientation.unlock();
        this.screenOrientation.lock(this.screenOrientation.ORIENTATIONS.PORTRAIT);
      } else {
        this.screenOrientation.unlock();
        this.screenOrientation.lock(this.screenOrientation.ORIENTATIONS.LANDSCAPE);
    }
  }

  async ionViewWillLeave() {
    this.statusBar.show();
    const currentOrientation = await this.preferences.getString(PreferenceKey.ORIENTATION).toPromise();
    if (currentOrientation === AppOrientation.LANDSCAPE) {
      this.screenOrientation.lock(this.screenOrientation.ORIENTATIONS.LANDSCAPE);
    } else {
      this.screenOrientation.unlock();
      this.screenOrientation.lock(this.screenOrientation.ORIENTATIONS.PORTRAIT);
    }

    if (this.events) {
      this.events.unsubscribe('endGenieCanvas');
    }

    if (this.backButtonSubscription) {
      this.backButtonSubscription.unsubscribe();
    }
    window.removeEventListener('renderer:question:submitscore', () => { });
  }

  ngOnDestroy() {
    if (this.pauseSubscription) {
      this.pauseSubscription.unsubscribe();
    }

  }

  handleNavBackButton() {
    this.showConfirm();
  }

  async playerEvents(event) {
    if (event.edata) {
      const userId: string = this.appGlobalService.getCurrentUser().uid;
      const parentId: string = (this.content.rollup && this.content.rollup.l1) ? this.content.rollup.l1 : this.content.identifier;
      const contentId: string = this.content.identifier;
      if (event.edata['type'] === 'END') {
        const saveState: string = JSON.stringify(event.metaData);
        this.playerService.savePlayerState(userId, parentId, contentId, saveState);
      }
      if (event.edata['type'] === 'END' && this.config['metadata']['mimeType'] === "application/vnd.sunbird.questionset") {
        this.courseService.syncAssessmentEvents().subscribe();
      } else if (event.edata['type'] === 'EXIT') {
        this.playerService.deletePlayerSaveState(userId, parentId, contentId);
        if (this.config['metadata']['mimeType'] === "application/vnd.sunbird.questionset") {
          if (!this.isExitPopupShown) {
            this.showConfirm();
          }
        } else {
          this.location.back();
        }
      } else if (event.edata['type'] === 'SHARE') {
        const popover = await this.popoverCtrl.create({
          component: SbSharePopupComponent,
          componentProps: {
            content: this.content,
            corRelationList: this.corRelationList,
            pageId: PageId.PLAYER_PAGE,
            shareFromPlayer: true,
            shareItemType: this.isChildContent ? ShareItemType.LEAF_CONTENT : ShareItemType.ROOT_CONTENT
          },
          cssClass: 'sb-popover',
        });
        await popover.present();
      } else if (event.edata['type'] === 'DOWNLOAD') {
        this.handleDownload();
      } else if (event.edata['type'] === 'PRINT') {
        this.printPdfService.printPdf(this.config['metadata'].streamingUrl);
      } else if(event.edata.type === 'NEXT_CONTENT_PLAY') {
           this.playNextContent();
      } else if (event.edata.type === 'compatibility-error') {
        cordova.plugins.InAppUpdateManager.checkForImmediateUpdate(
          () => {},
          () => {}
        );
      } else if (event.edata.type === 'exdata') {
        if (event.edata.currentattempt) {
          const attemptInfo = {
            isContentDisabled: event.edata.maxLimitExceeded,
            isLastAttempt: event.edata.isLastAttempt
          };
          this.commonUtilService.handleAssessmentStatus(attemptInfo);
        }
      } else if (event.edata.type === 'DEVICE_ROTATION_CLICKED') {
        this.toggleDeviceOrientation();
      }
    }
  }

  handleDownload() {
    if (this.content.contentData.downloadUrl) {
      if (this.platform.is('ios')) {
        this.file.checkDir(this.file.documentsDirectory, 'downloads')
        .then(() => {
          this.file.checkFile(this.file.documentsDirectory, 'downloads/' + this.content.name + '.pdf')
          .then(_ => {this.commonUtilService.showToast("A file with the same name already exists!")})
          .catch(() => {
            this.downloadFileIos(this.content);
          })
        }) 
        .catch(() => {
          this.file.createDir(this.file.documentsDirectory, 'downloads', false)
          .then(response => {
            this.downloadFileIos(this.content);
          })
          .catch((err) => {
            this.commonUtilService.showToast('Error saving file:  ' + err.message, false, 'redErrorToast');
          })
        })
      } else { // android
        this.downloadPdfService.downloadPdf(this.content).then((res) => {
          this.commonUtilService.showToast('CONTENT_DOWNLOADED');
        }).catch((error) => {
          if (error.reason === 'device-permission-denied') {
            this.commonUtilService.showToast('DEVICE_NEEDS_PERMISSION');
          } else if (error.reason === 'user-permission-denied') {
            this.commonUtilService.showToast('DEVICE_NEEDS_PERMISSION');
          } else if (error.reason === 'download-failed') {
            this.commonUtilService.showToast('SOMETHING_WENT_WRONG');
          }
        });
      }
    } else {
      this.commonUtilService.showToast('ERROR_CONTENT_NOT_AVAILABLE');
    }
  }

  downloadFileIos(content) {
    const path = this.file.documentsDirectory;
    const fileUri = content.contentData.downloadUrl;
    const fileName = content.name;
    setTimeout(() => {
      const transfer = this.transfer.create();
      transfer.download(fileUri, path + 'downloads/' + fileName + '.pdf').then(entry => {
        this.commonUtilService.showToast('CONTENT_DOWNLOADED');
      }).catch(err => {
        this.commonUtilService.showToast('SOMETHING_WENT_WRONG');
      });
    },500)
  }

  async getNewPlayerConfiguration() {
      const nextContent = this.config['metadata'].hierarchyInfo && this.nextContentToBePlayed ? { name: this.nextContentToBePlayed.contentData.name, identifier: this.nextContentToBePlayed.contentData.identifier } : undefined;
      this.config['context']['pdata']['pid'] = 'sunbird.app.contentplayer';
      if (this.config['metadata'].isAvailableLocally) {
        this.config['metadata'].contentData.streamingUrl = '/_app_file_' + this.config['metadata'].contentData.streamingUrl;
      }
      this.config['metadata']['contentData']['basePath'] = '/_app_file_' + this.config['metadata'].basePath;
      this.config['metadata']['contentData']['isAvailableLocally'] = this.config['metadata'].isAvailableLocally;
      this.config['metadata'] = this.config['metadata'].contentData;
      this.config['data'] = {};
      this.config['config'] = {
        ...this.config['config'],
        nextContent,
        sideMenu: {
          showShare: true,
          showDownload: true,
          showReplay: false,
          showExit: true,
          showPrint: true
        }
      };

      if(this.config['metadata']['mimeType'] === "application/vnd.sunbird.questionset"){
        let questionSet;
        try{
          questionSet = await this.contentService.getQuestionSetRead(this.content.identifier, {fields:'instructions'}).toPromise();
        } catch(e){
          console.log(e);
        }
        this.config['metadata']['instructions'] = questionSet && questionSet.questionset.instructions ? questionSet.questionset.instructions : undefined;
      }
      const profile = await this.profileService.getActiveSessionProfile({ requiredFields: ProfileConstants.REQUIRED_FIELDS }).toPromise();
      this.config['context'].userData = {
        firstName:  profile && profile.serverProfile && profile.serverProfile.firstName ? profile.serverProfile.firstName : profile.handle,
        lastName: ''
      };
      return this.config;
  }

  getNextContent(hierarchyInfo, identifier) {
    return new Promise((resolve) => {
      this.contentService.nextContent(hierarchyInfo, identifier).subscribe((res) => {
        this.nextContentToBePlayed = res;
        resolve(res);
      })
    })
  }

  playNextContent(){
    const content = this.nextContentToBePlayed;
    this.events.publish(EventTopics.NEXT_CONTENT, {
      content,
      course: this.course
    });
    this.location.back();
  }

  /**
   * This will trigger from player/ iframe when it unable to find consecutive content
   * @param identifier Content Identifier
   * @param hierarchyInfo Object of content hierarchy
   */
  onContentNotFound(identifier: string, hierarchyInfo: Array<HierarchyInfo>) {
    const content = { identifier, hierarchyInfo };

    setTimeout(() => {
      this.closeIframe(content);
    }, 1000);
    this.events.publish(EventTopics.NEXT_CONTENT, {
      content,
      course: this.course
    });
  }

  /**
   * This is an callback to mobile when player switches user
   * @param selectedUser User id of the newly selected user by player
   */
  onUserSwitch(selectedUser: User) {
    this.appGlobalService.setSelectedUser(selectedUser);
  }

  /**
   * This will close the player page and will fire some end telemetry events from the player
   */
  closeIframe(content?: any) {
    const stageId = this.previewElement.nativeElement.contentWindow['EkstepRendererAPI'].getCurrentStageId();
    try {
      this.previewElement.nativeElement.contentWindow['TelemetryService'].exit(stageId);
    } catch (err) {
      console.error('End telemetry error:', err.message);
    }
    this.events.publish(EventTopics.PLAYER_CLOSED, {
      selectedUser: this.appGlobalService.getSelectedUser()
    });

    if (this.navigateBackToContentDetails) {
      window.history.go(-1);
      this.router.navigate([RouterLinks.CONTENT_DETAILS], {
        state: {
          content: content ? content : this.config['metadata'],
          corRelation: this.corRelationList,
          shouldNavigateBack: true,
          isCourse: this.isCourse,
          course: this.course
        },
        replaceUrl: true
      });
    }  else if (this.navigateBackToTrackableCollection) {
      this.router.navigate([RouterLinks.ENROLLED_COURSE_DETAILS], {
        state: {
          content
        },
        replaceUrl: true
      });
    } else {
      this.location.back();
    }
  }


  /**
   * This will show confirmation box while leaving the player, it will fire some telemetry events from the player.
   */
  async showConfirm() {
    this.isExitPopupShown = true;
    let type, stageId;
    if (this.playerType === 'sunbird-old-player') {
      type = (this.previewElement.nativeElement.contentWindow['Renderer']
        && !this.previewElement.nativeElement.contentWindow['Renderer'].running) ? 'EXIT_APP' : 'EXIT_CONTENT';
      stageId = this.previewElement.nativeElement.contentWindow['EkstepRendererAPI'].getCurrentStageId();
      this.previewElement.nativeElement.contentWindow['TelemetryService'].interact(
        'TOUCH', 'DEVICE_BACK_BTN', 'EXIT', { type, stageId });
    } else {
      this.telemetryGeneratorService.generateBackClickedNewTelemetry(true, Environment.PLAYER, PageId.PLAYER);
    }

    const alert = await this.alertCtrl.create({
      header: this.commonUtilService.translateMessage('CONFIRM'),
      message: this.commonUtilService.translateMessage('CONTENT_PLAYER_EXIT_PERMISSION'),
      buttons: [
        {
          text: this.commonUtilService.translateMessage('CANCEL'),
          role: 'cancel',
          handler: () => {
            this.isExitPopupShown = false;
            this.telemetryGeneratorService.generateInteractTelemetry(InteractType.TOUCH, 
              InteractSubtype.CANCEL_CLICKED, 
              Environment.PLAYER,
              PageId.PLAYER_PAGE);
            this.previewElement.nativeElement.contentWindow['TelemetryService'].interact(
              'TOUCH', 'ALERT_CANCEL', 'EXIT', { type, stageId });
          }
        },
        {
          text: this.commonUtilService.translateMessage('OKAY'),
          handler: async() => {
            this.telemetryGeneratorService.generateInteractTelemetry(InteractType.TOUCH, 
              InteractSubtype.OK_CLICKED, 
              Environment.PLAYER,
              PageId.PLAYER_PAGE);
            if (this.playerType === 'sunbird-old-player') {
              this.previewElement.nativeElement.contentWindow['TelemetryService'].interact(
                'END', 'ALERT_OK', 'EXIT', { type, stageId });
              this.previewElement.nativeElement.contentWindow['TelemetryService'].interrupt('OTHER', stageId);
              this.previewElement.nativeElement.contentWindow['EkstepRendererAPI'].dispatchEvent('renderer:telemetry:end');
              this.closeIframe();
            } else {
              this.location.back();
            }
          }
        }
      ],
      cssClass: 'player-exit-popup'
    });
    await alert.present();
  }

  async openPDF(url) {
    if (this.course) {
      setTimeout(() => {
        this.updateContentState();
      }, 1000);
    }
    const loader = await this.commonUtilService.getLoader(undefined, this.commonUtilService.translateMessage('DOWNLOADING_2'));
    await loader.present();
    const fileTransfer: FileTransferObject = this.transfer.create();
    const entry = await fileTransfer
      .download(url, cordova.file.cacheDirectory + url.substring(url.lastIndexOf('/') + 1))
      .catch((e) => {
        this.telemetryGeneratorService.generateErrorTelemetry(Environment.PLAYER,
          TelemetryErrorCode.ERR_DOWNLOAD_FAILED,
          ErrorType.SYSTEM,
          PageId.PLAYER,
          JSON.stringify(e),
        );
      });
    loader.dismiss();
    const stageId = this.previewElement.nativeElement.contentWindow['EkstepRendererAPI'].getCurrentStageId();
    try {
      this.previewElement.nativeElement.contentWindow['TelemetryService'].exit(stageId);
    } catch (err) {
      console.error('End telemetry error:', err.message);
    }

    if (entry) {
      const localUrl = entry.toURL();
      this.fileOpener
        .open(localUrl, 'application/pdf')
        .catch((e) => {
          console.log('Error opening file', e);
          this.commonUtilService.showToast('ERROR_TECHNICAL_PROBLEM');
        });
    }
    this.location.back();

  }

  private updateContentState() {
    const updateContentStateRequest: UpdateContentStateRequest = {
      userId: this.config['context']['actor']['id'],
      contentId: this.config['metadata']['identifier'],
      courseId: this.course['identifier'] || this.course['courseId'],
      batchId: this.course['batchId'],
      status: 2,
      progress: 100,
      target: [UpdateContentStateTarget.LOCAL, UpdateContentStateTarget.SERVER]
    };

    this.courseService.updateContentState(updateContentStateRequest).subscribe();
  }

  playerTelemetryEvents(event) {
    if (event) {
      SunbirdSdk.instance.telemetryService.saveTelemetry(JSON.stringify(event)).subscribe(
        (res) => console.log('response after telemetry', res),
        );
    }
  }

  private isJSON(input): boolean {
    try {
      JSON.parse(input);
      return true;
    } catch (e) {
      return false;
    }
  }

  checkIsPlayerEnabled(config , playerType) {
    return config.fields.find(ele =>   ele.name === playerType && ele.values[0].isEnabled);
  }
}
<ion-content>
  <div class="content-player" *ngIf="playerType === 'sunbird-old-player'">
    <iframe #preview title="player" id="contentPlayer" src="./content-player/preview.html?isMobile=true"
      style="width:100%;height:100vh;border:none;"></iframe>
  </div>
  <div *ngIf="playerType === 'sunbird-pdf-player'" style="height:100vh;width:100%;">
    <sunbird-pdf-player [playerConfig]="config" (playerEvent)="playerEvents($event)"
      (telemetryEvent)="playerTelemetryEvents($event)"></sunbird-pdf-player>
  </div>
  <div *ngIf="playerType === 'sunbird-epub-player'" style="height:100vh;width:100%;">
    <sunbird-epub-player [playerConfig]="config" (playerEvent)="playerEvents($event)"
      (telemetryEvent)="playerTelemetryEvents($event)"></sunbird-epub-player>
  </div>
  <div *ngIf="playerType === 'sunbird-quml-player'" style="height:100vh;width:100%;background-color: white;">
      <quml-main-player [playerConfig]="config" (playerEvent)="playerEvents($event)" 
      (telemetryEvent)="playerTelemetryEvents($event)"></quml-main-player>
  </div>
  <div *ngIf="playerType === 'sunbird-video-player'"  style="height:100vh;width:100%;">
    <div class="sb-player-container-ios" *ngIf="platform.is('ios')" (click)="handleNavBackButton();$event.stopPropagation()">
      <div class="sb-circle">
        <img src="assets/imgs/ic_back.svg" alt="back" aria-label="back" class="sb-arrow-back" role="button">
      </div>
    </div>
    <sunbird-video-player [playerConfig]="config" (playerEvent)="playerEvents($event)"
      (telemetryEvent)="playerTelemetryEvents($event)"></sunbird-video-player>
  </div>
</ion-content>

Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""