638 lines
18 KiB
TypeScript

/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { UserMediaAdvancement } from 'app/model/user-media-advancement';
import { DataService, VideoService, SeriesService, SeasonService, ArianeService, AdvancementService } from 'app/service';
import { HttpWrapperService } from 'common/service';
import { isNullOrUndefined } from 'common/utils';
@Component({
selector: 'app-video',
templateUrl: './video.html',
styleUrls: ['./video.less']
})
export class VideoScene implements OnInit {
videoGlobal: any;
@ViewChild('globalVideoElement')
set mainDivEl(el: ElementRef) {
if (!isNullOrUndefined(el)) {
this.videoGlobal = el.nativeElement;
}
}
videoPlayer: HTMLVideoElement;
@ViewChild('videoPlayer')
set mainVideoEl(el: ElementRef) {
if (!isNullOrUndefined(el)) {
this.videoPlayer = el.nativeElement;
}
}
videoCanva: any;
@ViewChild('canvascreenshoot')
set mainCanvaEl(el: ElementRef) {
if (!isNullOrUndefined(el)) {
this.videoCanva = el.nativeElement;
}
}
haveNext = null;
havePrevious = null;
idVideo: number = -1;
mediaIsNotFound: boolean = false;
mediaIsLoading: boolean = true;
error: string = '';
name: string = '';
description: string = '';
episode: number = undefined;
seriesId: number = undefined;
seriesName: string = undefined;
seasonId: number = undefined;
seasonName: string = undefined;
dataId: number = -1;
time: number = undefined;
typeId: number = undefined;
generatedName: string = '';
videoSource: string = '';
covers: string[];
playVideo: boolean = false;
displayVolumeMenu: boolean = false;
isPlaying: boolean = false;
isFullScreen: boolean = false;
currentTime: number = 0;
currentTimeDisplay: string = '00';
duration: number = 0;
durationDisplay: string = '00';
volumeValue: number = 100;
displayNeedHide: boolean = false;
timeLeft: number = 10;
interval = null;
userMetaData: UserMediaAdvancement & { percentDisplay?: number } = undefined
previousTime: number = 0;
startPlayingTime: number = undefined;
hasFullReadTheVideo: {
previousTime: number,
totalCount: number,
registered: boolean
} = {
previousTime: 0,
totalCount: 0,
registered: false
};
constructor(private videoService: VideoService,
private seriesService: SeriesService,
private seasonService: SeasonService,
private httpService: HttpWrapperService,
private arianeService: ArianeService,
private dataService: DataService,
private advancementService: AdvancementService) {
}
startHideTimer() {
this.displayNeedHide = false;
this.timeLeft = 5;
if (this.interval !== null) {
return;
}
let self = this;
this.interval = setInterval(() => {
console.log(`periodic event: ${self.timeLeft}`);
if (self.timeLeft > 0) {
self.timeLeft--;
} else {
clearInterval(self.interval);
self.timeOutDetected();
}
}, 1000);
}
timeOutDetected() {
console.log(' ==> stop timer');
this.displayNeedHide = true;
clearInterval(this.interval);
this.interval = null;
}
onRequireNext(event: any) {
console.log(`generate next : ${this.haveNext.id}`);
this.arianeService.navigateVideo(this.haveNext.id, event.which === 2, event.ctrlKey);
this.arianeService.setVideo(this.haveNext.id);
}
onRequirePrevious(event: any) {
console.log(`generate previous : ${this.havePrevious.id}`);
this.arianeService.navigateVideo(this.havePrevious.id, event.which === 2, event.ctrlKey);
this.arianeService.setVideo(this.havePrevious.id);
}
generateName() {
this.generatedName = '';
if (this.seriesName !== undefined) {
this.generatedName = `${this.generatedName}${this.seriesName}-`;
}
if (this.seasonName !== undefined) {
if (this.seasonName.length < 2) {
this.generatedName = `${this.generatedName}s0${this.seasonName}-`;
} else {
this.generatedName = `${this.generatedName}s${this.seasonName}-`;
}
}
if (this.episode !== undefined) {
if (this.episode < 10) {
this.generatedName = `${this.generatedName}e0${this.episode}-`;
} else {
this.generatedName = `${this.generatedName}e${this.episode}-`;
}
}
this.generatedName = this.generatedName + this.name;
this.generatedName = this.generatedName.replace(new RegExp('&', 'g'), '_');
this.generatedName = this.generatedName.replace(new RegExp('/', 'g'), '_');
// update the path of the uri request
this.videoSource = this.httpService.createRESTCall2({
api: `data/${this.dataId}/${this.generatedName}`,
addURLToken: true,
});
}
myPeriodicCheckFunction() {
console.log('check ... ');
}
changeMetadata() {
console.log('list of the stream:');
/*
let captureStream = this.videoPlayer.audioTracks;
for (let iii=0; iii < captureStream.length; iii++) {
console.log(" - " + captureStream[iii].language);
if (captureStream[iii].language.substring(0,2) === "fr") {
captureStream[iii].enabled = true;
} else {
captureStream[iii].enabled = false;
}
}
*/
}
audioTracks(event) {
console.log(`list of the stream:${event}`);
/*
let captureStream = this.videoPlayer.audioTracks;
for (let iii=0; iii < captureStream.length; iii++) {
console.log(" - " + captureStream[iii].language);
if (captureStream[iii].language.substring(0,2) === "fr") {
captureStream[iii].enabled = true;
} else {
captureStream[iii].enabled = false;
}
}
*/
}
ngOnInit() {
let self = this;
this.startHideTimer();
this.idVideo = this.arianeService.getVideoId();
this.arianeService.videoChange.subscribe((videoId) => {
console.log(`Detect videoId change...${videoId}`);
self.idVideo = videoId;
self.updateDisplay();
});
self.updateDisplay();
}
updateDisplay(): void {
let self = this;
self.haveNext = null;
self.havePrevious = null;
this.videoService.get(this.idVideo)
.then((response) => {
console.log(`get response of video : ${JSON.stringify(response, null, 2)}`);
self.error = '';
self.name = response.name;
self.description = response.description;
self.episode = response.episode;
self.seriesId = response.seriesId;
self.seasonId = response.seasonId;
self.dataId = response.dataId;
self.time = response.time;
self.generatedName = "????????? TODO: ???????" //response.generatedName;
if (self.dataId !== -1) {
self.videoSource = self.httpService.createRESTCall2({
api: `data/${self.dataId}/${self.generatedName}`,
addURLToken: true,
});
} else {
self.videoSource = '';
}
self.covers = self.dataService.getCoverListUrl(response.covers);
self.generateName();
if (self.seriesId !== undefined && self.seriesId !== null) {
self.seriesService.get(self.seriesId)
.then((response2) => {
self.seriesName = response2.name;
self.generateName();
}).catch((response3) => {
// nothing to do ...
});
}
if (self.seasonId !== undefined && self.seasonId !== null) {
self.seasonService.get(self.seasonId)
.then((response4) => {
self.seasonName = response4.name;
self.generateName();
}).catch((response5) => {
// nothing to do ...
});
self.seasonService.getVideo(self.seasonId)
.then((response6: any) => {
// console.log("saison property: " + JSON.stringify(response, null, 2));
self.haveNext = null;
self.havePrevious = null;
for (let iii = 0; iii < response6.length; iii++) {
if (isNullOrUndefined(response6[iii].episode)) {
continue;
}
if (response6[iii].episode < self.episode) {
if (self.havePrevious === null) {
self.havePrevious = response6[iii];
} else if (self.havePrevious.episode < response6[iii].episode) {
self.havePrevious = response6[iii];
}
} else if (response6[iii].episode > self.episode) {
if (self.haveNext === null) {
self.haveNext = response6[iii];
} else if (self.haveNext.episode > response6[iii].episode) {
self.haveNext = response6[iii];
}
}
//self.covers.push(self.dataService.getCoverUrl(response6[iii]));
}
}).catch((response7: any) => {
});
}
self.mediaIsLoading = false;
// console.log("display source " + self.videoSource);
// console.log("set transformed : " + JSON.stringify(self, null, 2));
}).catch((response8) => {
self.error = 'Can not get the data';
self.name = '';
self.description = '';
self.episode = undefined;
self.seriesId = undefined;
self.seasonId = undefined;
self.dataId = -1;
self.time = undefined;
self.generatedName = '';
self.videoSource = '';
self.covers = undefined;
self.seriesName = undefined;
self.seasonName = undefined;
self.mediaIsNotFound = true;
self.mediaIsLoading = false;
});
this.advancementService.get(this.idVideo)
.then((response: UserMediaAdvancement) => {
this.userMetaData = { ...response, percentDisplay: Math.floor(response.percent * 100) }
this.startPlayingTime = response.time
})
}
onRequirePlay() {
this.startHideTimer();
this.playVideo = true;
this.hasFullReadTheVideo = {
previousTime: 0,
totalCount: 0,
registered: false
};
this.displayVolumeMenu = false;
}
onRequireStop() {
this.startHideTimer();
const startPlayingTime = this.videoPlayer.currentTime
this.playVideo = false;
this.displayVolumeMenu = false;
this.startPlayingTime = startPlayingTime;
}
onVideoEnded() {
this.startHideTimer();
this.playVideo = false;
this.displayVolumeMenu = false;
/*
if(this.isFullScreen === true) {
this.isFullScreen = false;
}
*/
}
changeStateToPlay() {
this.isPlaying = true;
if (this.isFullScreen === true) {
this.onFullscreen();
}
}
changeStateToPause() {
this.isPlaying = false;
}
convertIndisplayTime(time: number): string {
let tmpp = parseInt(`${time}`, 10);
let heures = parseInt(`${tmpp / 3600}`, 10);
tmpp = tmpp - heures * 3600;
let minutes = parseInt(`${tmpp / 60}`, 10);
let seconds = tmpp - minutes * 60;
let out = '';
if (heures !== 0) {
out = `${out}${heures}:`;
}
if (minutes >= 10) {
out = `${out}${minutes}:`;
} else {
out = `${out}0${minutes}:`;
}
if (seconds >= 10) {
out = out + seconds;
} else {
out = `${out}0${seconds}`;
}
return out;
}
configureDefaultValue(): boolean {
if (!isNullOrUndefined(this.startPlayingTime)) {
this.videoPlayer.currentTime = this.startPlayingTime
this.startPlayingTime = undefined;
return true;
}
return false;
}
changeTimeupdate(currentTime: any) {
// console.log("time change ");
// console.log(" ==> " + this.videoPlayer.currentTime);
// Normal display part
this.currentTime = this.videoPlayer.currentTime;
this.currentTimeDisplay = this.convertIndisplayTime(this.currentTime);
// Cat set default value only at start
if (this.configureDefaultValue()) {
this.hasFullReadTheVideo.previousTime = this.currentTime;
return;
}
let needAddOneCount = false;
// Section to manage the detection of full read of the video
if (!this.hasFullReadTheVideo.registered) {
console.log(`Check !!!!!!!! ${this.currentTime} / ${this.hasFullReadTheVideo.previousTime} ==> ${this.currentTime - this.hasFullReadTheVideo.previousTime}`);
if (Math.abs(this.currentTime - this.hasFullReadTheVideo.previousTime) < 10) {
console.log(` ==> step 1`);
if (this.currentTime > this.hasFullReadTheVideo.previousTime) {
this.hasFullReadTheVideo.totalCount += this.currentTime - this.hasFullReadTheVideo.previousTime;
}
console.log(` ==> step 2 percent = ${this.currentTime / this.duration}, total=${this.hasFullReadTheVideo.totalCount / 60}`);
// Detect the passing of 90%
if (this.currentTime / this.duration > 0.9) {
console.log(` ==> step 3`);
this.hasFullReadTheVideo.registered = true;
// Add cont only if the user watching more than 3 minutes
if (this.hasFullReadTheVideo.totalCount > 60 * 3) {
console.log(` ==> step 4 ==> You win`);
needAddOneCount = true;
}
}
}
}
this.hasFullReadTheVideo.previousTime = this.currentTime;
// console.log(" ==> " + this.currentTimeDisplay);
if (needAddOneCount || Math.abs(this.previousTime - this.currentTime) > 15) {
this.previousTime = this.currentTime;
this.advancementService.updateTime(this.idVideo, this.currentTime, this.duration, needAddOneCount);
}
}
changeDurationchange(duration: any) {
console.log('duration change ');
console.log(` ==> ${this.videoPlayer.duration}`);
this.configureDefaultValue();
this.duration = this.videoPlayer.duration;
this.durationDisplay = this.convertIndisplayTime(this.duration);
}
onPlay() {
console.log('play');
this.startHideTimer();
if (this.videoPlayer === null ||
this.videoPlayer === undefined) {
console.log(`error element: ${this.videoPlayer}`);
return;
}
this.videoPlayer.volume = this.volumeValue / 100;
this.videoPlayer.play();
}
onPause() {
console.log('pause');
this.startHideTimer();
if (this.videoPlayer === null ||
this.videoPlayer === undefined) {
console.log(`error element: ${this.videoPlayer}`);
return;
}
this.videoPlayer.pause();
}
onPauseToggle() {
console.log('pause toggle ...');
if (this.isPlaying === true) {
this.onPause();
} else {
this.onPlay();
}
}
onStop() {
console.log('stop');
this.startHideTimer();
if (this.videoPlayer === null ||
this.videoPlayer === undefined) {
console.log(`error element: ${this.videoPlayer}`);
return;
}
this.videoPlayer.pause();
this.videoPlayer.currentTime = 0;
}
onBefore() {
console.log('before');
this.startHideTimer();
}
onNext() {
console.log('next');
this.startHideTimer();
}
seek(newValue: any) {
console.log(`seek ${newValue.value}`);
this.startHideTimer();
if (this.videoPlayer === null ||
this.videoPlayer === undefined) {
console.log(`error element: ${this.videoPlayer}`);
return;
}
this.videoPlayer.currentTime = newValue.value;
}
onRewind() {
console.log('rewind');
this.startHideTimer();
if (this.videoPlayer === null ||
this.videoPlayer === undefined) {
console.log(`error element: ${this.videoPlayer}`);
return;
}
this.videoPlayer.currentTime = this.currentTime - 10;
}
onForward() {
console.log('forward');
this.startHideTimer();
if (this.videoPlayer === null ||
this.videoPlayer === undefined) {
console.log(`error element: ${this.videoPlayer}`);
return;
}
this.videoPlayer.currentTime = this.currentTime + 10;
}
onMore() {
console.log('more');
this.startHideTimer();
if (this.videoPlayer === null ||
this.videoPlayer === undefined) {
console.log(`error element: ${this.videoPlayer}`);
return;
}
}
onFullscreen() {
console.log('fullscreen');
this.startHideTimer();
if (this.videoGlobal === null ||
this.videoGlobal === undefined) {
console.log(`error element: ${this.videoGlobal}`);
return;
}
if (this.videoGlobal.requestFullscreen) {
this.videoGlobal.requestFullscreen();
} else if (this.videoGlobal.mozRequestFullScreen) {
this.videoGlobal.mozRequestFullScreen();
} else if (this.videoGlobal.webkitRequestFullscreen) {
this.videoGlobal.webkitRequestFullscreen();
} else if (this.videoGlobal.msRequestFullscreen) {
this.videoGlobal.msRequestFullscreen();
}
}
onFullscreenExit() {
this.onFullscreenExit22(document);
}
onFullscreenExit22(docc: any) {
console.log('fullscreen EXIT');
this.startHideTimer();
if (this.videoGlobal === null ||
this.videoGlobal === undefined) {
console.log(`error element: ${this.videoGlobal}`);
return;
}
if (docc.exitFullscreen) {
docc.exitFullscreen();
} else if (docc.mozCancelFullScreen) {
docc.mozCancelFullScreen();
} else if (docc.webkitExitFullscreen) {
docc.webkitExitFullscreen();
} else if (docc.msExitFullscreen) {
docc.msExitFullscreen();
}
}
onFullscreenChange() {
this.onFullscreenChange22(document);
}
onFullscreenChange22(element: any) {
let isInFullScreen = element.fullscreenElement && element.fullscreenElement !== null ||
element.webkitFullscreenElement && element.webkitFullscreenElement !== null ||
element.mozFullScreenElement && element.mozFullScreenElement !== null ||
element.msFullscreenElement && element.msFullscreenElement !== null;
console.log(`onFullscreenChange(${isInFullScreen})`);
this.isFullScreen = isInFullScreen;
}
onVolumeMenu() {
this.displayVolumeMenu = !this.displayVolumeMenu;
this.startHideTimer();
}
onVolume(newValue: any) {
console.log(`onVolume ${newValue.value}`);
this.startHideTimer();
if (this.videoPlayer === null ||
this.videoPlayer === undefined) {
console.log(`error element: ${this.videoPlayer}`);
return;
}
this.volumeValue = newValue.value;
this.videoPlayer.volume = this.volumeValue / 100;
this.videoPlayer.muted = false;
}
onVolumeMute() {
this.startHideTimer();
if (this.videoPlayer === null ||
this.videoPlayer === undefined) {
console.log(`error element: ${this.videoPlayer}`);
return;
}
this.videoPlayer.muted = true;
}
onVolumeUnMute() {
this.startHideTimer();
if (this.videoPlayer === null ||
this.videoPlayer === undefined) {
console.log(`error element: ${this.videoPlayer}`);
return;
}
this.videoPlayer.muted = false;
}
onTakeScreenShoot() {
this.startHideTimer();
// const canvas = document.createElement("canvas");
// scale the canvas accordingly
this.videoCanva.width = this.videoPlayer.videoWidth;
this.videoCanva.height = this.videoPlayer.videoHeight;
// draw the video at that frame
this.videoCanva.getContext('2d').drawImage(this.videoPlayer, 0, 0, this.videoCanva.width, this.videoCanva.height);
// canvas.crossorigin="anonymous"
// convert it and send it to the server
let self = this;
this.videoCanva.toBlob((blob) => {
self.videoService.uploadCoverBlob(blob, this.idVideo);
}, 'image/jpeg', 0.95);
/*
let tmpUrl = this.videoCanva.toDataURL('image/jpeg', 0.95);
fetch(tmpUrl)
.then(res => res.blob()) // Gets the response and returns it as a blob
.then(blob => {
self.videoService.uploadCoverBlob(blob, this.idVideo);
});
*/
}
}