import HTMLManager from './HTMLManager.js';
import Loader from '../Loader.js';
import
{
ScreenElementManager,
ScreenElement,
ScreenElementFromElement,
SrcElement,
ButtonElement,
InputElement,
MenuButtonElement,
ProgressIndicator,
ProgressBarIndicator,
AnimeElement,
EpisodeElement,
EpisodeWatchButton,
ReturnButton,
DownloadAllButton,
EpisodeInfoElement,
PlayerInfoElement,
YtDlFormatElement,
EpisodeDlProgress,
EpisodeDlErrorProgress
}
from './ScreenElement.js';
const LOADING_ANIMES = "Loading Animes...";
const LOADING_THUMBNAILS = "Loading Thumbnails...";
const ANIME_NODEJS = "AnimeNodeJs";
const INFO = "Info";
const WATCH = "Watch";
/**
* Manage Screen
* @memberof Public.Html
*/
class ScreenManager {
/**
*
* @param {string} title
* @param {string} htmlTitle
*/
static setTitle(title, htmlTitle)
{
if (!htmlTitle) htmlTitle = title;
HTMLManager.title.setText(htmlTitle);
document.title = title;
}
static init()
{
HTMLManager.menuBar.append(
//If click on Watch generate AnimeList
new MenuButtonElement("Watch", () => {
ScreenElementManager.removeListenersOnAllElements();
this.generateAnimeListHTML();
}),
/*new MenuButtonElement("Edit Animes", () => {
}),
new MenuButtonElement("Edit Streams", () => {
}),*/
new MenuButtonElement("Reload Animes", () => {
ScreenElementManager.removeListenersOnAllElements();
Loader.loadAnimeList();
})
);
}
static showLoadingAnime()
{
this.setTitle(LOADING_ANIMES, ANIME_NODEJS);
HTMLManager.body.clear();
HTMLManager.body.append(
new ScreenElement("p").setText(LOADING_ANIMES)
);
}
static initAnimes(json)
{
this.setTitle(LOADING_THUMBNAILS, ANIME_NODEJS);
HTMLManager.body.clear();
/* It's cool to get the anime from the episode */
this.animes = json.map( (m) => {
m.episodes = m.episodes.map( e => {e.anime = m; return e;});
return m;
});
console.log(this.animes);
/* Get all id (to generate the thumnail) */
/**
* @type {number[]}
*/
let episodeIds = [];
for (let i = this.animes.length - 1; i >= 0; i--) {
let lAnime = this.animes[i];
for (let j = lAnime.episodes.length - 1; j >= 0; j--) {
let lEpisode = lAnime.episodes[j];
if (episodeIds.includes(lEpisode.episodeId)) continue;
episodeIds.push(lEpisode.episodeId);
}
}
let progress = new ProgressIndicator();
HTMLManager.body.append(
new ScreenElement("p").setText("Generating default episode thumbnail please wait..."),
new ScreenElement("br"),
progress
);
let oncomplete = () =>
{
this.generateAnimeListHTML();
};
let onprogress = (p) =>
{
progress.setProgress(p);
}
/* Generate the Thumbnails */
Loader.preloadDefaultThumbnail(episodeIds, oncomplete, onprogress);
}
/**
* Generate the list of animes
*/
static generateAnimeListHTML()
{
this.setTitle(ANIME_NODEJS);
HTMLManager.body.clear();
var animesElms = [];
for (let i = 0; i < this.animes.length; i++) {
const a = this.animes[i];
animesElms.push(new AnimeElement(a, (anime) => {
ScreenElementManager.removeListenersOnAllElements();
let listIsEpisodeLocal = [];
//Get if the episode is local or not for each episode
let currentIndex = -1;
const next = () => {
++currentIndex;
if (currentIndex >= anime.episodes.length)
{
this.generateEpisodeListHTML(anime, listIsEpisodeLocal);
return;
}
let epId = anime.episodes[currentIndex].episodeId;
Loader.getEpisodeInfo(anime.id, epId, (d) => {
listIsEpisodeLocal[epId] = d.isLocal;
next();
}, false);
};
next();
}));
}
console.log(animesElms);
// **************** //
// HTML STARTS HERE //
// **************** //
HTMLManager.body.append(
new ScreenElement("ul").setId("animeList").appendList(animesElms)
);
// **************** //
// HTML ENDS HERE //
// **************** //
ScreenElementManager.allowStaticListener();
}
static generateEpisodeListHTML(anime, listIsEpisodeLocal)
{
this.setTitle(ANIME_NODEJS + " - " + anime.name, anime.name);
HTMLManager.body.clear();
let episodeElms = [];
for (let i = 0; i < anime.episodes.length; i++) {
let episode = anime.episodes[i];
let isLocal = listIsEpisodeLocal[episode.episodeId];
episodeElms.push(new EpisodeElement(anime, episode, isLocal, listIsEpisodeLocal,
//OnClick
(a,e) => {
ScreenElementManager.removeListenersOnAllElements();
Loader.getEpisodeInfo(a.id, e.episodeId, (d) => {ScreenManager.generateEpisodeInfo(d, a, e, listIsEpisodeLocal)});
}
));
}
HTMLManager.body.append(
new ReturnButton(() => {
ScreenElementManager.removeListenersOnAllElements();
ScreenManager.generateAnimeListHTML();
}),
/*new DownloadAllButton(() => {
ScreenElementManager.removeListenersOnAllElements();
let i = -1;
let next = () =>
{
if (++i >= episodeButtons.length)
{
alert("Download is done");
ScreenManager.generateEpisodeListHTML(anime);
return;
}
let lElement = episodeButtons[i].parentElement;
let args = lElement.id.slice("episode".length).split("-").map( i => parseInt(i));
Loader.getEpisodeInfo(args[0], args[1], (d) => {ScreenManager.generateEpisodeInfoForDownload(d, next)});
}
next();
}),*/
new ScreenElement("ul").addClass("episodes").appendList(episodeElms)
);
ScreenElementManager.allowStaticListener();
}
/**
*
* @deprecated
* @param {*} info
* @param {*} next
*/
static generateEpisodeInfoForDownload(info, next)
{
if (info.isLocal)
{
next();
return;
}
let animeId = info.animeId;
let episodeId = info.episodeId;
let anime = this.animes[animeId];
let episode = ScreenManager.getEpisodeFromId(anime, episodeId);
let lText =
`<button id="return">Return</button>\n`+
`<br/>`+
`<br/>`+
`<div>\n`+
`Name : ${info.name}<br/>\n`+
`AnimeId : ${info.animeId}<br/>\n`+
`EpisodeId : ${info.episodeId}<br/>\n`+
`${info.players.map( (player, i) => {
let lToReturn = `${player.player.name}:<br/>\n`+
`<div class="tab-1">\n`+
`\tURL : ${player.url}<br/>\n`+
`\tisYoutube : ${Boolean(player.isYoutube)}<br/>\n`+
`\tisNatif : ${player.player.isNatif}<br/>\n`+
`\tdownloadable : ${player.player.downloadable}<br/>\n`+
`\tautoDownload : ${player.player.autoDownload}<br/>\n`+
`\tid : ${player.player.id}<br/>`
lToReturn += `<button class="download ${i}"> dl</button>`
lToReturn += `</div>`;
return `<div class="tab-1">${lToReturn}</div>`;
}).join("<br/>\n")}`+
`</div>`;
HTMLManager.body.innerHTML = lText;
this.addListener(HTMLManager.body.querySelector("#return"), "click", () => {
ScreenElementManager.removeListenersOnAllElements();
ScreenManager.generateAnimeListHTML();
});
this.allowStaticListener();
}
static generateEpisodeInfo(info, anime, episode, listIsEpisodeLocal)
{
HTMLManager.body.clear();
let animeId = info.animeId;
let episodeId = info.episodeId;
this.setTitle(INFO + " - " + anime.name + " : " + info.episodeId, INFO + " - " + anime.name + " : " + "Episode " + episodeId);
let elmsToAppend = [];
elmsToAppend.push(new ReturnButton(() => {
ScreenElementManager.removeListenersOnAllElements();
ScreenManager.generateEpisodeListHTML(anime, listIsEpisodeLocal);
}));
if (info.isLocal) elmsToAppend.push(new EpisodeWatchButton(anime, episode, listIsEpisodeLocal));
//* SHOW NEXT EPISODE BUTTON *//
let nextEpisode = ScreenManager.getNextEpisode(anime, episode);
if (nextEpisode != null)
{
elmsToAppend.push(
new ButtonElement(() => {
ScreenElementManager.removeListenersOnAllElements();
Loader.getEpisodeInfo(animeId, nextEpisode.episodeId, (d) => {ScreenManager.generateEpisodeInfo(d, anime, nextEpisode, listIsEpisodeLocal)});
}).append(new ScreenElement("h4").setText("Next - Episode "+nextEpisode.episodeId))
);
}
elmsToAppend.push(
new ScreenElement("br"),
new ScreenElement("hr"),
new ScreenElement("br"),
new ScreenElement("br"),
new EpisodeInfoElement(info,
//Complete
(p) => {
alert("Download success ! Progess : "+p.progress);
//ScreenManager.generateEpisodeListHTML(anime, listIsEpisodeLocal);
ScreenElementManager.allowStaticListener();
},
//Error
(e) => {
alert("Can't download episode\nError : "+e);
ScreenElementManager.allowStaticListener();
}
)
);
HTMLManager.body.appendList(elmsToAppend);
ScreenElementManager.allowStaticListener();
}
/**
*
* @param {string} url
* @param {number} animeId
* @param {number} episodeId
*/
static showVideo(url, animeId, episodeId, listIsEpisodeLocal)
{
let anime = this.animes[animeId];
this.setTitle(WATCH + " - " + anime.name + " : " + episodeId, anime.name + " : " + "Episode " + episodeId);
let episode = ScreenManager.getEpisodeFromId(anime, episodeId);
let nextEpisode = ScreenManager.getNextEpisode(anime, episode);
HTMLManager.body.clear();
HTMLManager.body.append(
new SrcElement("video", url)
.setControls(true)
.setAutoplay(false)
.setPoster(episode.posterLink || Loader.defaultThumbnailList[episodeId] || `/asset/thumbnail/${episodeId}.png?width:170&height:90&textSize=700`),
new ScreenElement("h2")
.setText(anime.name + " - " + (episode.name || "Episode " + episodeId)),
new ScreenElement("br"),
new ScreenElement("br"),
);
if (nextEpisode != null)
{
HTMLManager.body.append(
new ButtonElement(
() => {
ScreenElementManager.removeListenersOnAllElements();
//If episode is local, show next video. Else show info
if (listIsEpisodeLocal[nextEpisode.episodeId])
Loader.loadLocalEpisode(animeId, nextEpisode.episodeId, listIsEpisodeLocal);
else
Loader.getEpisodeInfo(animeId, nextEpisode.episodeId, (d) => {ScreenManager.generateEpisodeInfo(d, anime, nextEpisode, listIsEpisodeLocal)});
}
)
.setText("Next - Episode "+nextEpisode.episodeId)
);
}
HTMLManager.body.append(new ButtonElement(
() => {
ScreenElementManager.removeListenersOnAllElements();
ScreenManager.generateEpisodeListHTML(anime, listIsEpisodeLocal);
}).setText("Return to anime")
);
ScreenElementManager.allowStaticListener();
}
static getNextEpisode(anime, episode)
{
let nextEpisode = null;
//Get next episode
for (let i = anime.episodes.length - 1; i >= 0; i--) {
let epi = anime.episodes[i];
if (epi.episodeId <= episode.episodeId) continue;
if (nextEpisode == null || epi.episodeId < nextEpisode.episodeId)
{
nextEpisode = epi;
}
}
return nextEpisode;
}
static getEpisodeFromId(anime, episodeId)
{
for (let i = anime.episodes.length - 1; i >= 0; i--) {
let epi = anime.episodes[i];
if (epi.episodeId == episodeId) return epi;
}
return null;
}
/**
* @typedef DlCurrent
* @property {string} episode
* @property {number} progress
* @memberof Public.Html.ScreenManager
*/
/**
* @typedef DlError
* @property {string} episode
* @property {string} error
* @memberof Public.Html.ScreenManager
*/
/**
* @typedef DlList
* @property {DlCurrent} current
* @property {string[]} list
* @property {DlError[]} error
* @memberof Public.Html.ScreenManager
*/
/**
*
* @param {DlList} list
*/
static downloadList(list)
{
HTMLManager.downloadContainer.clear();
if (list.current && list.current.episode)
{
let indexOfCurrentEp = list.list.indexOf(list.current.episode);
if (indexOfCurrentEp != -1) {
list.list.splice(indexOfCurrentEp, 1);
}
HTMLManager.downloadContainer.append(new EpisodeDlProgress(list.current.episode,list.current.progress));
}
if (list.list.length > 0)
{
HTMLManager.downloadContainer.appendList(
list.list.map(m => {return new ScreenElement("div").setText(m); })
);
}
if (list.error.length > 0)
{
HTMLManager.downloadContainer.appendList(
list.error.map(m => {return new EpisodeDlErrorProgress(m.episode, m.error); })
);
}
}
};
export default ScreenManager;