src/app/modules/player-helper/components/player/player.component.ts
                OnInit
                AfterViewInit
                OnChanges
                OnDestroy
    
| selector | app-player | 
            
| styleUrls | ./player.component.scss | 
            
| templateUrl | ./player.component.html | 
            
constructor(configService: ConfigService, router: Router, toasterService: ToasterService, resourceService: ResourceService, navigationHelperService: NavigationHelperService, deviceDetectorService: DeviceDetectorService, userService: UserService, formService: FormService, contentUtilsServiceService: ContentUtilsServiceService, contentService: ContentService, cdr: ChangeDetectorRef, playerService: PublicPlayerService, utilService: UtilService)
                     | 
                ||||||||||||||||||||||||||||||||||||||||||
| 
                             
                                    Parameters :
                                     
                    
  | 
                
| contentData | |
                        Type :         any
                     | 
                |
| contentProgressEvents$ | |
                        Type :     Subject<any>
                     | 
                |
| isContentDeleted | |
                        Type :     Subject<any>
                     | 
                |
| isSingleContent | |
                        Type :         boolean
                     | 
                |
| overlayImagePath | |
                        Type :         string
                     | 
                |
| pageId | |
                        Type :         string
                     | 
                |
| playerConfig | |
                        Type :         PlayerConfig
                     | 
                |
| playerOption | |
                        Type :         any
                     | 
                |
| telemetryObject | |
                        Type :         literal type
                     | 
                |
| assessmentEvents | |
                        Type :     EventEmitter
                     | 
                |
| closePlayerEvent | |
                        Type :     EventEmitter
                     | 
                |
| playerOnDestroyEvent | |
                        Type :     EventEmitter
                     | 
                |
| questionScoreReviewEvents | |
                        Type :     EventEmitter
                     | 
                |
| questionScoreSubmitEvents | |
                        Type :     EventEmitter
                     | 
                |
| ratingPopupClose | |
                        Type :     EventEmitter
                     | 
                |
| sceneChangeEvent | |
                        Type :     EventEmitter
                     | 
                |
| selfAssessLastAttempt | |
                        Type :     EventEmitter
                     | 
                |
| window:orientationchange | 
                    Arguments : '$event' 
                 | 
            
window:orientationchange()
                 | 
            
| window:popstate | 
                    Arguments : '$event' 
                 | 
            
window:popstate(event)
                 | 
            
| Public addUserDataToContext | 
                    
                    addUserDataToContext()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| adjustPlayerHeight | 
adjustPlayerHeight()
                 | 
            
| 
                     Adjust player height after load 
                        Returns :          
                void
                     | 
            
| checkForQumlPlayer | 
checkForQumlPlayer()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| closeContentFullScreen | 
closeContentFullScreen()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| closeFullscreen | 
closeFullscreen()
                 | 
            
| 
                     when user clicks on close button this method will let the player to exit from fullscreen mode and 
 
                        Returns :          
                void
                     | 
            
| closeModal | 
closeModal()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| emitSceneChangeEvent | ||||||||
emitSceneChangeEvent(timer: number)
                 | 
            ||||||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| enablePlayer | ||||||
enablePlayer(mode: boolean)
                 | 
            ||||||
| 
                     this method will handle play button click and turn the player into landscape 
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| eventHandler | ||||
eventHandler(event)
                 | 
            ||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| focusOnReplay | 
focusOnReplay()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| generateContentReadEvent | |||||||||
generateContentReadEvent(event: any, newPlayerEvent?)
                 | 
            |||||||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| generatelimitedAttemptEvent | ||||
generatelimitedAttemptEvent(event)
                 | 
            ||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| generateScoreSubmitEvent | ||||||
generateScoreSubmitEvent(event: any)
                 | 
            ||||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| Public handleOrientationChange | 
                    
                    handleOrientationChange()
                 | 
            
                    Decorators : 
                    @HostListener('window:orientationchange', ['$event'])
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| loadCdnPlayer | 
loadCdnPlayer()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| loadDefaultPlayer | ||||||
loadDefaultPlayer(url)
                 | 
            ||||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| loadNewPlayer | 
loadNewPlayer()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| loadOldPlayer | 
loadOldPlayer()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| loadPlayer | 
loadPlayer()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| ngAfterViewInit | 
ngAfterViewInit()
                 | 
            
| 
                     loadPlayer method will be called 
                        Returns :          
                void
                     | 
            
| ngOnChanges | ||||
ngOnChanges(changes)
                 | 
            ||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| ngOnDestroy | 
ngOnDestroy()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| ngOnInit | 
ngOnInit()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| onPopState | ||||
                    
                    onPopState(event)
                 | 
            ||||
                    Decorators : 
                    @HostListener('window:popstate', ['$event'])
                 | 
            ||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| rotatePlayer | 
rotatePlayer()
                 | 
            
| 
                     this method checks for the browser capability to be fullscreen via if-else ladder if match found, it will turn the player along will be close button into fullscreen and then rotate it to landscape mode 
                        Returns :          
                void
                     | 
            
| setTelemetryData | 
setTelemetryData()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| showRatingPopup | ||||
showRatingPopup(event)
                 | 
            ||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| updateMetadataForDesktop | 
updateMetadataForDesktop()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| buildNumber | 
                        Type :         string
                     | 
                
| closeButtonInteractEdata | 
                        Type :         IInteractEventEdata
                     | 
                
| collectionId | 
                        Type :         string
                     | 
                
| Public configService | 
                        Type :         ConfigService
                     | 
                
| CONSTANT | 
                        Type :         object
                     | 
                
                        Default value : {
    ACCESSEVENT: 'renderer:question:submitscore',
    ISLASTATTEMPT: 'renderer:selfassess:lastattempt',
    MAXATTEMPT: 'renderer:maxLimitExceeded',
    ACCESSREVIEWEVENT: 'renderer:question:reviewAssessment'
  }
                     | 
                
| contentDeleted | 
                        Default value : false
                     | 
                
| contentId | 
                        Type :         string
                     | 
                
| contentIframe | 
                        Type :     ElementRef
                     | 
                
                        Decorators : 
                        
                            @ViewChild('contentIframe')
                     | 
                
| contentRatingModal | 
                        Default value : false
                     | 
                
| Public contentUtilsServiceService | 
                        Type :         ContentUtilsServiceService
                     | 
                
| Public formService | 
                        Type :         FormService
                     | 
                
| isCdnWorking | 
                        Type :         string
                     | 
                
| isDesktopApp | 
                        Default value : false
                     | 
                
| isFullScreenView | 
                        Default value : false
                     | 
                
| isMobileOrTab | 
                        Type :         boolean
                     | 
                
| loadPlayerInteractEdata | 
                        Type :         IInteractEventEdata
                     | 
                
| mobileViewDisplay | 
                        Type :         string
                     | 
                
                        Default value : 'block'
                     | 
                
| modal | 
                        Decorators : 
                        
                            @ViewChild('modal')
                     | 
                
| 
                     Dom element reference of contentRatingModal  | 
            
| Public navigationHelperService | 
                        Type :         NavigationHelperService
                     | 
                
| playerLoaded | 
                        Default value : false
                     | 
                
| playerOverlayImage | 
                        Type :         string
                     | 
                
| Public playerService | 
                        Type :         PublicPlayerService
                     | 
                
| playerType | 
                        Type :         string
                     | 
                
| previewCdnUrl | 
                        Type :         string
                     | 
                
| Public resourceService | 
                        Type :         ResourceService
                     | 
                
| Public router | 
                        Type :     Router
                     | 
                
| Public showNewPlayer | 
                        Default value : false
                     | 
                
| showPlayIcon | 
                        Default value : true
                     | 
                
| showQumlPlayer | 
                        Default value : false
                     | 
                
| showRatingModalAfterClose | 
                        Default value : false
                     | 
                
| Public unsubscribe | 
                        Default value : new Subject<void>()
                     | 
                
import { ConfigService, NavigationHelperService, UtilService } from '@sunbird/shared';
import { Component, AfterViewInit, ViewChild, ElementRef, Input, Output, EventEmitter,
OnChanges, HostListener, OnInit, ChangeDetectorRef } from '@angular/core';
import * as _ from 'lodash-es';
import { PlayerConfig } from '@sunbird/shared';
import { Router } from '@angular/router';
import { ToasterService, ResourceService, ContentUtilsServiceService } from '@sunbird/shared';
const OFFLINE_ARTIFACT_MIME_TYPES = ['application/epub'];
import { Subject } from 'rxjs';
import { DeviceDetectorService } from 'ngx-device-detector';
import { IInteractEventEdata } from '@sunbird/telemetry';
import { UserService, FormService } from '../../../core/services';
import { OnDestroy } from '@angular/core';
import { takeUntil } from 'rxjs/operators';
import { CsContentProgressCalculator } from '@project-sunbird/client-services/services/content/utilities/content-progress-calculator';
import { ContentService } from '@sunbird/core';
import { PublicPlayerService } from '@sunbird/public';
@Component({
  selector: 'app-player',
  templateUrl: './player.component.html',
  styleUrls: ['./player.component.scss']
})
export class PlayerComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy {
  @Input() playerConfig: PlayerConfig;
  @Output() assessmentEvents = new EventEmitter<any>();
  @Output() questionScoreSubmitEvents = new EventEmitter<any>();
  @Output() questionScoreReviewEvents = 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;
  showRatingModalAfterClose = false;
  previewCdnUrl: string;
  isCdnWorking: string;
  CONSTANT = {
    ACCESSEVENT: 'renderer:question:submitscore',
    ISLASTATTEMPT: 'renderer:selfassess:lastattempt',
    MAXATTEMPT: 'renderer:maxLimitExceeded',
    ACCESSREVIEWEVENT: 'renderer:question:reviewAssessment'
  };
  @Input() overlayImagePath: string;
  @Input() isSingleContent: boolean;
  @Input() telemetryObject: {};
  @Input() pageId: string;
  @Input() contentData;
  @Input() isContentDeleted: Subject<any>;
  @Output() closePlayerEvent = new EventEmitter<any>();
  @Output() ratingPopupClose = new EventEmitter<any>();
  @Output() selfAssessLastAttempt = new EventEmitter<any>();
  contentDeleted = false;
  isMobileOrTab: boolean;
  showPlayIcon = true;
  closeButtonInteractEdata: IInteractEventEdata;
  loadPlayerInteractEdata: IInteractEventEdata;
  playerOverlayImage: string;
  isFullScreenView = false;
  public unsubscribe = new Subject<void>();
  public showNewPlayer = false;
  mobileViewDisplay = 'block';
  playerType: string;
  isDesktopApp = false;
  showQumlPlayer = false;
  contentId: string;
  collectionId:string;
  /**
 * Dom element reference of contentRatingModal
 */
  @ViewChild('modal') modal;
  @HostListener('window:popstate', ['$event'])
  onPopState(event) {
    this.closeContentFullScreen();
  }
  constructor(public configService: ConfigService, public router: Router, private toasterService: ToasterService,
    public resourceService: ResourceService, public navigationHelperService: NavigationHelperService,
    private deviceDetectorService: DeviceDetectorService, private userService: UserService, public formService: FormService
    , public contentUtilsServiceService: ContentUtilsServiceService, private contentService: ContentService,
    private cdr: ChangeDetectorRef, public playerService: PublicPlayerService, private utilService: UtilService) {
    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';
  }
  @HostListener('window:orientationchange', ['$event'])
  public handleOrientationChange() {
    const screenType = _.get(screen, 'orientation.type');
      if ( screenType === 'portrait-primary' || screenType === 'portrait-secondary' ) {
        this.closeFullscreen();
      }
  }
  ngOnInit() {
    this.checkForQumlPlayer()
    // If `sessionStorage` has UTM data; append the UTM data to context.cdata
    if (this.playerConfig && sessionStorage.getItem('UTM')) {
      let utmData;
      try {
        utmData = JSON.parse(sessionStorage.getItem('UTM'));
      } catch (error) {
        throw new Error('JSON Parse Error => UTM data');
      }
      if (utmData && _.get(this.playerConfig, 'context.cdata')) {
        this.playerConfig.context.cdata = _.union(this.playerConfig.context.cdata, utmData);
      }
      if (utmData && !_.get(this.playerConfig, 'context.cdata')) {
        this.playerConfig.context['cdata'] = [];
        this.playerConfig.context.cdata = _.union(this.playerConfig.context.cdata, utmData);
      }
    }
    this.isDesktopApp = this.utilService.isDesktopApp;
    // Check for loggedIn user; and append user data to context object
    // User data (`firstName` and `lastName`) is used to show at the end of quiz
    if (this.playerConfig) {
        this.addUserDataToContext();
    }
    this.isMobileOrTab = this.deviceDetectorService.isMobile() || this.deviceDetectorService.isTablet();
    if (this.isSingleContent === false) {
      this.showPlayIcon = false;
    }
    this.setTelemetryData();
    this.navigationHelperService.contentFullScreenEvent.
    pipe(takeUntil(this.unsubscribe)).subscribe(isFullScreen => {
      this.isFullScreenView = isFullScreen;
      const root: HTMLElement = document.getElementsByTagName( 'html' )[0];
      if (isFullScreen) {
        root.classList.add('PlayerMediaQueryClass');
        document.body.classList.add('o-y-hidden');
      } else {
        root.classList.remove('PlayerMediaQueryClass');
        document.body.classList.remove('o-y-hidden');
      }
      if (this.isDesktopApp) {
        const hideCM = isFullScreen ? true : false;
        this.navigationHelperService.handleContentManagerOnFullscreen(hideCM);
      }
      this.loadPlayer();
    });
    this.contentUtilsServiceService.contentShareEvent.pipe(takeUntil(this.unsubscribe)).subscribe(data => {
      if (this.isMobileOrTab && data === 'close') {
        this.mobileViewDisplay = 'block';
      }
    });
  }
  /**
   * loadPlayer method will be called
   */
  ngAfterViewInit() {
    if (this.playerConfig) {
      this.loadPlayer();
    }
  }
  ngOnChanges(changes) {
    this.contentRatingModal = false;
    this.showNewPlayer = false;
    this.cdr.detectChanges();
    if (this.playerConfig) {
      this.playerOverlayImage = this.overlayImagePath ? this.overlayImagePath : _.get(this.playerConfig, 'metadata.appIcon');
      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();
          playerElement.contentWindow.initializePreview(this.playerConfig);
          if (this.playerLoaded) {
            playerElement.removeEventListener('renderer:telemetry:event', telemetryEvent => this.generateContentReadEvent(telemetryEvent));
            window.frames['contentPlayer'].removeEventListener('message', accessEvent => this.generateScoreSubmitEvent(accessEvent), false);
          }
          this.playerLoaded = true;
          playerElement.addEventListener('renderer:telemetry:event', telemetryEvent => this.generateContentReadEvent(telemetryEvent));
          window.frames['contentPlayer'].addEventListener('message', accessEvent => this.generateScoreSubmitEvent(accessEvent), false);
        } catch (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();
          playerElement.contentWindow.initializePreview(this.playerConfig);
          if (this.playerLoaded) {
            playerElement.removeEventListener('renderer:telemetry:event', telemetryEvent => this.generateContentReadEvent(telemetryEvent));
            window.frames['contentPlayer'].removeEventListener('message', accessEvent => this.generateScoreSubmitEvent(accessEvent), false);
          }
          this.playerLoaded = true;
          playerElement.addEventListener('renderer:telemetry:event', telemetryEvent => this.generateContentReadEvent(telemetryEvent));
          window.frames['contentPlayer'].addEventListener('message', accessEvent => this.generateScoreSubmitEvent(accessEvent), false);
        } catch (err) {
          const prevUrls = this.navigationHelperService.history;
          if (this.isCdnWorking.toLowerCase() === 'yes' && prevUrls[prevUrls.length - 2]) {
            history.back();
          }
        }
      };
    }, 0);
  }
  loadPlayer() {
    this.checkForQumlPlayer();
    this.playerType = null;
    const formReadInputParams = {
      formType: 'content',
      formAction: 'play',
      contentType: 'player'
    };
    this.formService.getFormConfig(formReadInputParams).subscribe(
      (data: any) => {
        let isNewPlayer = false;
        _.forEach(data, (value) => {
          if (_.includes(_.get(value, 'mimeType'), _.get(this.playerConfig, 'metadata.mimeType')) && _.get(value, 'version') === 2) {
            this.playerConfig.context.threshold = _.get(value, 'threshold');
            this.playerType = _.get(value, 'type');
            isNewPlayer = true;
          }
        });
        if (isNewPlayer) {
          this.playerLoaded = false;
          this.loadNewPlayer();
        } else {
          this.loadOldPlayer();
        }
      },
      (error) => {
        this.loadOldPlayer();
      }
    );
  }
  checkForQumlPlayer() {
    if (_.get(this.playerConfig, 'metadata.mimeType') === this.configService.appConfig.PLAYER_CONFIG.MIME_TYPE.questionset) {
      this.playerConfig.config.sideMenu.showDownload = false;
      if (!_.get(this.playerConfig, 'metadata.instructions')) {
        this.playerService.getQuestionSetRead(_.get(this.playerConfig, 'metadata.identifier')).subscribe((data: any) => {
          this.playerConfig.metadata.instructions = _.get(data, 'result.questionset.instructions');
          this.showQumlPlayer = true;
        }, (error) => {
          this.showQumlPlayer = true;
        });
      } else {
        this.showQumlPlayer = true;
      }
    }
  }
  loadOldPlayer() {
    this.showNewPlayer = false;
    if (this.isDesktopApp) {
      this.updateMetadataForDesktop();
      const downloadStatus = Boolean(_.get(this.playerConfig, 'metadata.desktopAppMetadata.isAvailable'));
      let playerUrl = this.configService.appConfig.PLAYER_CONFIG.localBaseUrl;
      if (!downloadStatus) {
        playerUrl = `${playerUrl}webview=true`;
      }
      this.loadDefaultPlayer(playerUrl);
      return;
    }
    if (this.isMobileOrTab) {
      this.rotatePlayer();
    }
    if (this.previewCdnUrl !== '' && (this.isCdnWorking).toLowerCase() === 'yes') {
      this.loadCdnPlayer();
      return;
    }
    this.loadDefaultPlayer();
  }
  loadNewPlayer() {
    const downloadStatus = Boolean(_.get(this.playerConfig, 'metadata.desktopAppMetadata.isAvailable'));
    const artifactUrl = _.get(this.playerConfig, 'metadata.artifactUrl');
    this.contentId = _.get(this.playerConfig, 'metadata.identifier');
    this.collectionId = _.get(this.playerConfig, 'context.objectRollup.l1');
    if (downloadStatus && artifactUrl && !_.startsWith(artifactUrl, 'http://')) {
      this.playerConfig.metadata.artifactUrl = `${location.origin}/${artifactUrl}`;
    }
    this.addUserDataToContext();
    if (this.isMobileOrTab) {
      this.isFullScreenView = true;
      if (_.get(this.playerConfig, 'metadata.mimeType') !== this.configService.appConfig.PLAYER_CONFIG.MIME_TYPE.questionset) {
        this.rotatePlayer();
      }
    }
    this.showNewPlayer = true;
    if (this.userService.loggedIn) {
      this.userService.userData$.subscribe((user: any) => {
        if (user && !user.err) {
          const userProfile = user.userProfile;
          const userId = userProfile.id;
          const varName = (userId + '_' + (this.collectionId ? this.collectionId : '') + '_' + (this.contentId ? this.contentId : '') + '_config');
          const playerConfig: any = JSON.parse(localStorage.getItem(varName)) || {};
          this.playerConfig['config'] = { ...this.playerConfig['config'], ...playerConfig };
        }
      });
    } else {
      const varName = ('guest' + '_' + (this.collectionId ? this.collectionId : '') + '_' + (this.contentId ? this.contentId : '') + '_config');;
      const playerConfig: any = JSON.parse(localStorage.getItem(varName)) || {};
      this.playerConfig['config'] = { ...this.playerConfig['config'], ...playerConfig };
    }
  }
  // Update ArtifactUrl for old Player
  updateMetadataForDesktop() {
    const downloadStatus = Boolean(_.get(this.playerConfig, 'metadata.desktopAppMetadata.isAvailable'));
    if (downloadStatus) {
      this.playerConfig.data = '';
      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];
      }
    }
  }
  /**
   * Adjust player height after load
   */
  adjustPlayerHeight() {
    const playerWidth = $('#contentPlayer').width();
    if (playerWidth) {
      let height = playerWidth * (9 / 16);
      if (_.get(screen, 'orientation.type') === 'landscape-primary' && this.isMobileOrTab) {
        height = window.innerHeight;
      }
      $('#contentPlayer').css('height', height + 'px');
    }
  }
  generateScoreSubmitEvent(event: any) {
    if (event.data.toLowerCase() === (this.CONSTANT.ACCESSEVENT).toLowerCase()) {
      this.questionScoreSubmitEvents.emit(event);
    }
    if (event.data.toLowerCase() === (this.CONSTANT.ISLASTATTEMPT).toLowerCase()) {
      this.selfAssessLastAttempt.emit(event);
    }
    if (event.data.toLowerCase() === (this.CONSTANT.MAXATTEMPT).toLowerCase()) {
      this.selfAssessLastAttempt.emit(event);
    }
    if (event.data.toLowerCase() === (this.CONSTANT.ACCESSREVIEWEVENT).toLowerCase()) {
      this.questionScoreReviewEvents.emit(event);
    }
  }
  generatelimitedAttemptEvent(event) {
    if (_.get(event, 'edata.isLastAttempt')) {
      this.selfAssessLastAttempt.emit(event);
    } else if (_.get(event, 'edata.maxLimitExceeded')) {
      this.selfAssessLastAttempt.emit(event);
    }
  }
  eventHandler(event) {
    if (event.eid === 'END') {
      const metaDataconfig = event.metaData;
      if (this.userService.loggedIn) {
        this.userService.userData$.subscribe((user: any) => {
          if (user && !user.err) {
            const userProfile = user.userProfile;
            const userId = userProfile.id;
            const varName = (userId + '_' + (this.collectionId ? this.collectionId : '') + '_' + (this.contentId ? this.contentId : '') + '_config');
            localStorage.setItem(varName, JSON.stringify(metaDataconfig));
          }
        });
      } else {
        const userId = 'guest';
        const varName = (userId + '_' + (this.collectionId ? this.collectionId : '') + '_' + (this.contentId ? this.contentId : '') + '_config');
        localStorage.setItem(varName, JSON.stringify(metaDataconfig));
      }
    }
    if (event.eid === 'exdata') {
      this.generatelimitedAttemptEvent(event);
      return;
    }
    if (_.get(event, 'edata.type') === 'SHARE') {
      this.contentUtilsServiceService.contentShareEvent.emit('open');
      this.mobileViewDisplay = 'none';
    }
    if (_.get(event, 'edata.type') === 'PRINT') {
      const windowFrame = window.document.querySelector('pdf-viewer iframe');
      if (windowFrame) {
        windowFrame['contentWindow'].print();
      }
      this.mobileViewDisplay = 'none';
    }
  }
  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');
    const contentId = _.get(eventCopy, 'detail.telemetryData.object.id');
    // this.contentId = contentId;
    if (eid && (eid === 'START' || eid === 'END') && contentId === _.get(this.playerConfig, 'metadata.identifier')) {
      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);
    }
    if (_.get(this.playerConfig, 'metadata.mimeType') === this.configService.appConfig.PLAYER_CONFIG.MIME_TYPE.questionset && eid === 'END') {
      this.questionScoreSubmitEvents.emit(event);
    }
  }
  emitSceneChangeEvent(timer = 0) {
    setTimeout(() => {
      if (_.get(this, 'contentIframe.nativeElement')) {
        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) {
      const contentMimeType = this.playerConfig.metadata.mimeType;
      contentProgress = CsContentProgressCalculator.calculate(playerSummary, contentMimeType);
    }
    if (event.detail.telemetryData.eid === 'END' && contentProgress === 100) {
      this.contentRatingModal = !this.isFullScreenView;
      this.showRatingModalAfterClose = true;
      if (this.modal) {
        this.modal.showContentRatingModal = true;
      }
    }
  }
  /**
   * this method will handle play button click and turn the player into landscape
   */
  enablePlayer(mode: boolean) {
    this.showPlayIcon = mode;
    this.loadPlayer();
  }
  /** this method checks for the browser capability to be fullscreen via if-else ladder
   * if match found, it will turn the player along will be close button into fullscreen and then
   * rotate it to landscape mode
   */
  rotatePlayer() {
    setTimeout(() => {
      const playVideo: any = document.querySelector('#playerFullscreen');
      try {
        if (playVideo.requestFullscreen) {
          playVideo.requestFullscreen();
        } else if (playVideo.mozRequestFullScreen) { /* Firefox */
          playVideo.mozRequestFullScreen();
        } else if (playVideo.webkitRequestFullscreen) { /* Chrome, Safari and Opera */
          playVideo.webkitRequestFullscreen();
        } else if (playVideo.msRequestFullscreen) { /* IE/Edge */
          playVideo.msRequestFullscreen();
        }
        screen.orientation.lock('landscape');
      } catch (error) {}
    });
  }
  /** when user clicks on close button
   * this method will let the player to exit from fullscreen mode and
   * 1. video thumbnail will be shown for single content
   * 2. content-details page will be shown ( for multi-result dial-code search flow)
   */
  closeFullscreen() {
    /** to exit the fullscreen mode */
    if (document['exitFullscreen']) {
      document['exitFullscreen']();
    } else if (document['mozCancelFullScreen']) { /* Firefox */
      document['mozCancelFullScreen']();
    } else if (document['webkitExitFullscreen']) { /* Chrome, Safari and Opera */
      document['webkitExitFullscreen']();
    } else if (document['msExitFullscreen']) { /* IE/Edge */
      document['msExitFullscreen']();
    }
    if (this.showRatingModalAfterClose) {
      this.contentRatingModal = true;
      if (this.modal) {
        this.modal.showContentRatingModal = true;
      }
    }
     /** to change the view of the content-details page */
    this.showPlayIcon = true;
    this.closePlayerEvent.emit();
  }
  setTelemetryData() {
    this.closeButtonInteractEdata = {
      id: 'player-close-button',
      type: 'click',
      pageid: this.pageId
    };
    this.loadPlayerInteractEdata = {
      id: 'play-button',
      type: 'click',
      pageid: this.pageId
    };
  }
  closeContentFullScreen() {
    this.navigationHelperService.emitFullScreenEvent(false);
    this.loadPlayer();
  }
  closeModal() {
    this.focusOnReplay();
    this.ratingPopupClose.emit({});
  }
  
  focusOnReplay() {
    if (this.playerType === 'quml-player') {
      const replayButton: HTMLElement = document.querySelector('.replay-section');
      if (replayButton) {
        replayButton.focus();
      }
    }
  }
  
  public addUserDataToContext() {
    if (this.userService.loggedIn) {
      this.userService.userData$.subscribe((user: any) => {
        if (user && !user.err) {
          const userProfile = user.userProfile;
          this.playerConfig.context['userData'] = {
            firstName: userProfile.firstName ? userProfile.firstName : 'Guest',
            lastName: userProfile.lastName ? userProfile.lastName : ''
          };
        }
      });
    } else {
      this.playerConfig.context.userData = {
        firstName: this.userService.guestUserProfile.formatedName || 'Guest',
        lastName: ''
      };
    }
  }
  ngOnDestroy() {
    const playerElement = _.get(this.contentIframe, 'nativeElement');
    if (playerElement) {
      if (_.get(playerElement, 'contentWindow.telemetry_web.tList.length')) {
        const request = {
          url: this.configService.urlConFig.URLS.TELEMETRY.SYNC,
          data: {
            'id': 'api.sunbird.telemetry',
            'ver': '3.0',
            'events': playerElement.contentWindow.telemetry_web.tList.map(item => JSON.parse(item))
          }
        };
        this.contentService.post(request).subscribe();
      }
      playerElement.remove();
    }
    this.unsubscribe.next();
    this.unsubscribe.complete();
  }
}
    <!-- Mobile browser player-->
<div *ngIf="isMobileOrTab && !showNewPlayer" >
    <div data-ratio="16:9" class="player-thumbnail" appTelemetryInteract [telemetryInteractObject]="telemetryObject" [telemetryInteractEdata]="loadPlayerInteractEdata"
    [ngStyle]="{'background': 'url(' + playerOverlayImage + ') center/cover no-repeat '}" *ngIf="showPlayIcon" id="contentPlayer" tabindex="0" (click)="enablePlayer(false)">
    <img class="play-icon" src="assets/images/play_circle.svg">
  </div>
  <div id="playerFullscreen" *ngIf="!showPlayIcon" > 
    <!-- <img appTelemetryInteract [telemetryInteractObject]="telemetryInteractObject" [telemetryInteractEdata]="closeButtonInteractEdata" (click)="closeFullscreen()" class="close-button" src="assets/images/close-Black.svg" alt=""> -->
    <iframe #contentIframe id="contentPlayer" title="Content Player" aria-label="Content Player" class="contentViewerIframeShadow" name="contentPlayer"></iframe>
  </div>
</div>
<!-- Portal player-->
<div class="h-100" *ngIf="!isMobileOrTab && !showNewPlayer && !isContentDeleted">
    <iframe #contentIframe id="contentPlayer" title="Content Player" aria-label="Content Player" class="contentViewerIframeShadow" [ngClass]="{'player-fullscreen': isFullScreenView}" name="contentPlayer"></iframe>
</div>
<div *ngIf="!isMobileOrTab && showNewPlayer && !isContentDeleted" class="w-100 h-100">
        <div class="contentViewerIframeShadow" [ngClass]="{'player-fullscreen content-full-video': isFullScreenView}">
        <sunbird-pdf-player *ngIf="playerType === 'pdf-player'" [playerConfig]="playerConfig"
          (playerEvent)="eventHandler($event)" (telemetryEvent)="generateContentReadEvent($event, true)">
        </sunbird-pdf-player>
        <sunbird-video-player *ngIf="playerType === 'video-player'" [playerConfig]="playerConfig"
          (playerEvent)="eventHandler($event)" (telemetryEvent)="generateContentReadEvent($event, true)">
        </sunbird-video-player>
        <sunbird-epub-player *ngIf="playerType === 'epub-player'" [playerConfig]="playerConfig" [showFullScreen]="isFullScreenView"
        (playerEvent)="eventHandler($event)" (telemetryEvent)="generateContentReadEvent($event, true)"></sunbird-epub-player>
        <quml-main-player *ngIf="playerType === 'quml-player' && showQumlPlayer" [playerConfig]="playerConfig" (playerEvent)="eventHandler($event)" (telemetryEvent)="generateContentReadEvent($event, true)"></quml-main-player>
      </div>
</div>
<!--If Content is deleted-->
<div class="d-flex flex-dc flex-jc-center text-center flex-ai-center no-content-player" *ngIf="isContentDeleted">
  <div class="no-content-player__text"></div>
  <div>
    <img src="assets/images/shape.svg" width="90px" height="70px">
  </div>
  <div class="fnormal">{{resourceService?.messages?.stmsg?.desktop?.deleteMessage}}</div>
</div>
<div *ngIf="isMobileOrTab && showNewPlayer" class="w-100 h-100">
  <div data-ratio="16:9" class="player-thumbnail" appTelemetryInteract [telemetryInteractObject]="telemetryObject" [telemetryInteractEdata]="loadPlayerInteractEdata"
  [ngStyle]="{'background': 'url(' + playerOverlayImage + ') center/cover no-repeat '}" *ngIf="showPlayIcon" id="contentPlayer" tabindex="0" (click)="enablePlayer(false)">
  <img class="play-icon" src="assets/images/play_circle.svg">
</div>
<div id="playerFullscreen" *ngIf="!showPlayIcon" class="player-fullscreen" [ngStyle]="{'display': mobileViewDisplay}"> 
  <!-- <img *ngIf="playerType !== 'quml-player'" appTelemetryInteract [telemetryInteractObject]="telemetryInteractObject" [telemetryInteractEdata]="closeButtonInteractEdata" (click)="closeFullscreen()" class="close-button" src="assets/images/close-Black.svg" alt=""> -->
  <sunbird-pdf-player *ngIf="playerType === 'pdf-player'" [playerConfig]="playerConfig"
    (playerEvent)="eventHandler($event)" (telemetryEvent)="generateContentReadEvent($event, true)"></sunbird-pdf-player>
  <sunbird-video-player *ngIf="playerType === 'video-player'" [playerConfig]="playerConfig"
    (playerEvent)="eventHandler($event)" (telemetryEvent)="generateContentReadEvent($event, true)">
  </sunbird-video-player>
  <sunbird-epub-player *ngIf="playerType === 'epub-player'" [playerConfig]="playerConfig" [showFullScreen]="isFullScreenView"
    (playerEvent)="eventHandler($event)" (telemetryEvent)="generateContentReadEvent($event, true)"></sunbird-epub-player>
    <quml-main-player *ngIf="playerType === 'quml-player' && showQumlPlayer" [playerConfig]="playerConfig" (playerEvent)="eventHandler($event)" (telemetryEvent)="generateContentReadEvent($event, true)"></quml-main-player>
</div>
</div>
    <!--Rating popup -->
<app-content-rating #modal *ngIf="contentRatingModal && playerConfig"
    [contentData]="playerConfig.metadata" (closeModal)="closeModal()"></app-content-rating>
<button *ngIf="playerType !== 'quml-player'" class="sb-btn sb-btn-primary sb-btn-normal pull-right view-fullscreen"[ngClass]="{'d-none': !viewFullscreenBtn}" tabindex="0" (click)="viewInFullscreen()" appTelemetryInteract [telemetryInteractEdata]="viewFullScreenIntractEdata" [telemetryInteractObject]="viewFullScreenIntractObject"> <i class="expand icon"></i> View Full Screen</button>
    
                    ./player.component.scss
                
@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;
@use 'components/video' as *;
.player-thumbnail {
  width: 100%;
  cursor: pointer;
  border-radius: .3125rem;
  position: relative;
  padding-bottom: 56.25%;
  border: calculateRem(1px) solid var(--black);
}
.play-icon {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  left: 50%;
  height: calculateRem(80px);
  width: calculateRem(80px)
}
.overlay-image {
  width: 100%;
  height: 100%;
}
@media only screen and (max-width: 768px) {
  .play-icon {
    height: auto;
    width: auto;
  }
}
  .content-full-video{
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: calculateRem(50px);
    z-index: 999999;
    align-items: center;
    .video-close-btn{
        position: fixed;
        right: calculateRem(32px);
        left: auto;
        cursor: pointer;
        background: var(--black);
        height: calculateRem(32px);
        width: calculateRem(32px);
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        svg{
            width: calculateRem(16px);
            height: calculateRem(16px);
        }
        html[dir="rtl"] & {
            left: calculateRem(32px);
            right: auto;
        }
    }
}
.player-fullscreen {
    position:fixed !important;
    border:none; 
    margin:0;
    padding:0; 
    overflow:hidden; 
    z-index:9999;
    // height: calc(100% - 4rem) !important;
    background:var(--white);
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    border: none;
} 
.contentViewerIframeShadow {
  width: 100%;
  border: 0;
  height: 100%;
  left:50%;
  top:50%;
  right:50%;
  bottom:50%;
  transform: translate(-50%, -50%);
  position: absolute;
  transition: all ease .3s;
  iframe {
    height: calc(100vh - 4rem) !important;
    border:calculateRem(10px) solid var(--primary-400);
  }
} 
.close-button {
  position: absolute;
  z-index: 100;
  right: calculateRem(8px);
  top: calculateRem(8px);
  cursor: pointer;
}
::ng-deep{
  iframe {
    width: 100%;
    height: 100% !important;
  }
  .video-js{height:100% !important;}
  .video-js {
    padding-top:inherit !important;
  }
}
.no-content-player{
  background: var(--black);
  color: var(--white);
  width: 100%;
  height: 100%;
  &__text{
      max-width: calculateRem(300px);   
  }
}