WIP: Extras view, has a bug!

pull/16/head
Juraj Nyíri 3 years ago
parent e44f141c64
commit a7494f1d6b

@ -17205,8 +17205,8 @@ const CSS_STYLE = {
};
const supported = {
kodi: ['movie', 'episode'],
androidtv: ['movie', 'show', 'season', 'episode'],
plexPlayer: ['movie', 'show', 'season', 'episode']
androidtv: ['movie', 'show', 'season', 'episode', 'clip'],
plexPlayer: ['movie', 'show', 'season', 'episode', 'clip']
};
var bind = function bind(fn, thisArg) {
@ -19041,6 +19041,71 @@ const getOffset = (el) => {
}
return { top: y, left: x };
};
const createEpisodesView = (playController, plexProtocol, ip, port, token, data) => {
const episodeContainer = document.createElement('div');
episodeContainer.className = 'episodeContainer';
episodeContainer.style.width = `${CSS_STYLE.episodeWidth}px`;
const episodeThumbURL = `${plexProtocol}://${ip}:${port}/photo/:/transcode?width=${CSS_STYLE.episodeWidth}&height=${CSS_STYLE.episodeHeight}&minSize=1&upscale=1&url=${data.thumb}&X-Plex-Token=${token}`;
const episodeElem = document.createElement('div');
episodeElem.className = 'episodeElem';
episodeElem.style.width = `${CSS_STYLE.episodeWidth}px`;
episodeElem.style.height = `${CSS_STYLE.episodeHeight}px`;
episodeElem.style.backgroundImage = `url('${episodeThumbURL}')`;
episodeElem.dataset.clicked = 'false';
if (typeof data.lastViewedAt === 'undefined') {
const toViewElem = document.createElement('div');
toViewElem.className = 'toViewEpisode';
episodeElem.appendChild(toViewElem);
}
if (playController.isPlaySupported(data)) {
const episodeInteractiveArea = document.createElement('div');
episodeInteractiveArea.className = 'interactiveArea';
const episodePlayButton = document.createElement('button');
episodePlayButton.name = 'playButton';
episodePlayButton.addEventListener('click', episodeEvent => {
episodeEvent.stopPropagation();
playController.play(data, true);
});
episodeInteractiveArea.append(episodePlayButton);
episodeElem.append(episodeInteractiveArea);
}
episodeContainer.append(episodeElem);
const episodeTitleElem = document.createElement('div');
episodeTitleElem.className = 'episodeTitleElem';
episodeTitleElem.innerHTML = escapeHtml(data.title);
episodeContainer.append(episodeTitleElem);
const episodeNumber = document.createElement('div');
episodeNumber.className = 'episodeNumber';
if (data.type === 'episode') {
episodeNumber.innerHTML = escapeHtml(`Episode ${escapeHtml(data.index)}`);
}
else if (data.type === 'clip') {
let text = '';
switch (data.subtype) {
case 'behindTheScenes':
text = 'Behind the Scenes';
break;
case 'trailer':
text = 'Trailer';
break;
case 'scene':
text = 'Scene';
break;
case 'sceneOrSample':
text = 'Scene';
break;
default:
text = data.subtype;
break;
}
episodeNumber.innerHTML = escapeHtml(text);
}
episodeContainer.append(episodeNumber);
episodeContainer.addEventListener('click', episodeEvent => {
episodeEvent.stopPropagation();
});
return episodeContainer;
};
const isScrolledIntoView = (elem) => {
const rect = elem.getBoundingClientRect();
const elemTop = rect.top;
@ -19558,6 +19623,14 @@ style.textContent = css `
margin-right: 10px;
transition: 0.5s;
}
.movieExtras {
z-index: 4;
position: absolute;
top: 340px;
width: calc(100% - 32px);
left: 0;
padding: 16px;
}
.interactiveArea {
position: relative;
width: 100%;
@ -20134,49 +20207,8 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.episodesElem.style.transition = `0s`;
this.episodesElem.style.top = `${top + 2000}px`;
lodash.forEach(episodesData, episodeData => {
if (this.episodesElem) {
const episodeContainer = document.createElement('div');
episodeContainer.className = 'episodeContainer';
episodeContainer.style.width = `${CSS_STYLE.episodeWidth}px`;
const episodeThumbURL = `${this.plexProtocol}://${this.config.ip}:${this.config.port}/photo/:/transcode?width=${CSS_STYLE.episodeWidth}&height=${CSS_STYLE.episodeHeight}&minSize=1&upscale=1&url=${episodeData.thumb}&X-Plex-Token=${this.config.token}`;
const episodeElem = document.createElement('div');
episodeElem.className = 'episodeElem';
episodeElem.style.width = `${CSS_STYLE.episodeWidth}px`;
episodeElem.style.height = `${CSS_STYLE.episodeHeight}px`;
episodeElem.style.backgroundImage = `url('${episodeThumbURL}')`;
episodeElem.dataset.clicked = 'false';
if (typeof episodeData.lastViewedAt === 'undefined') {
const toViewElem = document.createElement('div');
toViewElem.className = 'toViewEpisode';
episodeElem.appendChild(toViewElem);
}
if (this.playController && this.playController.isPlaySupported(episodeData)) {
const episodeInteractiveArea = document.createElement('div');
episodeInteractiveArea.className = 'interactiveArea';
const episodePlayButton = document.createElement('button');
episodePlayButton.name = 'playButton';
episodePlayButton.addEventListener('click', episodeEvent => {
episodeEvent.stopPropagation();
if (this.plex && this.playController) {
this.playController.play(episodeData, true);
}
});
episodeInteractiveArea.append(episodePlayButton);
episodeElem.append(episodeInteractiveArea);
}
episodeContainer.append(episodeElem);
const episodeTitleElem = document.createElement('div');
episodeTitleElem.className = 'episodeTitleElem';
episodeTitleElem.innerHTML = escapeHtml(episodeData.title);
episodeContainer.append(episodeTitleElem);
const episodeNumber = document.createElement('div');
episodeNumber.className = 'episodeNumber';
episodeNumber.innerHTML = escapeHtml(`Episode ${escapeHtml(episodeData.index)}`);
episodeContainer.append(episodeNumber);
episodeContainer.addEventListener('click', episodeEvent => {
episodeEvent.stopPropagation();
});
this.episodesElem.append(episodeContainer);
if (this.episodesElem && this.playController) {
this.episodesElem.append(createEpisodesView(this.playController, this.plexProtocol, this.config.ip, this.config.port, this.config.token, episodeData));
}
});
clearInterval(this.episodesLoadTimeout);
@ -20245,7 +20277,33 @@ class PlexMeetsHomeAssistant extends HTMLElement {
}, 200);
}
else {
console.log(await this.plex.getDetails(data.key.split('/')[3]));
const movieDetails = await this.plex.getDetails(data.key.split('/')[3]);
const extras = movieDetails.Extras.Metadata;
this.episodesElemFreshlyLoaded = true;
if (this.episodesElem) {
this.episodesElemHidden = false;
this.episodesElem.style.display = 'block';
this.episodesElem.innerHTML = '';
this.episodesElem.style.transition = `0s`;
this.episodesElem.style.top = `${top + 2000}px`;
lodash.forEach(extras, extrasData => {
if (this.episodesElem && this.playController) {
this.episodesElem.append(createEpisodesView(this.playController, this.plexProtocol, this.config.ip, this.config.port, this.config.token, extrasData));
}
});
clearInterval(this.episodesLoadTimeout);
this.episodesLoadTimeout = setTimeout(() => {
if (this.episodesElem) {
this.episodesElem.style.transition = `0.7s`;
this.episodesElem.style.top = `${top + CSS_STYLE.expandedHeight + 16}px`;
this.resizeBackground();
}
}, 200);
clearInterval(this.episodesElemFreshlyLoadedTimeout);
this.episodesElemFreshlyLoadedTimeout = setTimeout(() => {
this.episodesElemFreshlyLoaded = false;
}, 700);
}
}
}
};

@ -10,8 +10,8 @@ const CSS_STYLE = {
const supported: any = {
kodi: ['movie', 'episode'],
androidtv: ['movie', 'show', 'season', 'episode'],
plexPlayer: ['movie', 'show', 'season', 'episode']
androidtv: ['movie', 'show', 'season', 'episode', 'clip'],
plexPlayer: ['movie', 'show', 'season', 'episode', 'clip']
};
const LOREM_IPSUM = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec semper risus vitae aliquet interdum. Nulla facilisi. Pellentesque viverra sagittis lorem eget aliquet. Cras vehicula, purus vel consectetur mattis, ipsum arcu ullamcorper mi, id viverra purus ex eu dolor. Integer vehicula lacinia sem convallis iaculis. Nulla fermentum erat interdum, efficitur felis in, mollis neque. Vivamus luctus metus eget nisl pellentesque, placerat elementum magna eleifend.

@ -272,6 +272,14 @@ style.textContent = css`
margin-right: 10px;
transition: 0.5s;
}
.movieExtras {
z-index: 4;
position: absolute;
top: 340px;
width: calc(100% - 32px);
left: 0;
padding: 16px;
}
.interactiveArea {
position: relative;
width: 100%;

@ -1,6 +1,9 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-env browser */
import _ from 'lodash';
import { CSS_STYLE } from '../const';
import PlayController from './PlayController';
import Plex from './Plex';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const escapeHtml = (unsafe: any): string => {
if (unsafe) {
@ -40,6 +43,86 @@ const getOffset = (el: Element): Record<string, any> => {
return { top: y, left: x };
};
const createEpisodesView = (
playController: PlayController,
plexProtocol: string,
ip: string,
port: string,
token: string,
data: Record<string, any>
): HTMLElement => {
const episodeContainer = document.createElement('div');
episodeContainer.className = 'episodeContainer';
episodeContainer.style.width = `${CSS_STYLE.episodeWidth}px`;
const episodeThumbURL = `${plexProtocol}://${ip}:${port}/photo/:/transcode?width=${CSS_STYLE.episodeWidth}&height=${CSS_STYLE.episodeHeight}&minSize=1&upscale=1&url=${data.thumb}&X-Plex-Token=${token}`;
const episodeElem = document.createElement('div');
episodeElem.className = 'episodeElem';
episodeElem.style.width = `${CSS_STYLE.episodeWidth}px`;
episodeElem.style.height = `${CSS_STYLE.episodeHeight}px`;
episodeElem.style.backgroundImage = `url('${episodeThumbURL}')`;
episodeElem.dataset.clicked = 'false';
if (typeof data.lastViewedAt === 'undefined') {
const toViewElem = document.createElement('div');
toViewElem.className = 'toViewEpisode';
episodeElem.appendChild(toViewElem);
}
if (playController.isPlaySupported(data)) {
const episodeInteractiveArea = document.createElement('div');
episodeInteractiveArea.className = 'interactiveArea';
const episodePlayButton = document.createElement('button');
episodePlayButton.name = 'playButton';
episodePlayButton.addEventListener('click', episodeEvent => {
episodeEvent.stopPropagation();
playController.play(data, true);
});
episodeInteractiveArea.append(episodePlayButton);
episodeElem.append(episodeInteractiveArea);
}
episodeContainer.append(episodeElem);
const episodeTitleElem = document.createElement('div');
episodeTitleElem.className = 'episodeTitleElem';
episodeTitleElem.innerHTML = escapeHtml(data.title);
episodeContainer.append(episodeTitleElem);
const episodeNumber = document.createElement('div');
episodeNumber.className = 'episodeNumber';
if (data.type === 'episode') {
episodeNumber.innerHTML = escapeHtml(`Episode ${escapeHtml(data.index)}`);
} else if (data.type === 'clip') {
let text = '';
switch (data.subtype) {
case 'behindTheScenes':
text = 'Behind the Scenes';
break;
case 'trailer':
text = 'Trailer';
break;
case 'scene':
text = 'Scene';
break;
case 'sceneOrSample':
text = 'Scene';
break;
default:
text = data.subtype;
break;
}
episodeNumber.innerHTML = escapeHtml(text);
}
episodeContainer.append(episodeNumber);
episodeContainer.addEventListener('click', episodeEvent => {
episodeEvent.stopPropagation();
});
return episodeContainer;
};
const isScrolledIntoView = (elem: HTMLElement): boolean => {
const rect = elem.getBoundingClientRect();
const elemTop = rect.top;
@ -53,4 +136,4 @@ const isScrolledIntoView = (elem: HTMLElement): boolean => {
};
// eslint-disable-next-line import/prefer-default-export
export { escapeHtml, getOffset, isScrolledIntoView, getHeight };
export { escapeHtml, getOffset, isScrolledIntoView, getHeight, createEpisodesView };

@ -5,7 +5,7 @@ import _ from 'lodash';
import { supported, CSS_STYLE } from './const';
import Plex from './modules/Plex';
import PlayController from './modules/PlayController';
import { escapeHtml, getOffset, isScrolledIntoView, getHeight } from './modules/utils';
import { escapeHtml, getOffset, isScrolledIntoView, getHeight, createEpisodesView } from './modules/utils';
import style from './modules/style';
class PlexMeetsHomeAssistant extends HTMLElement {
@ -637,58 +637,17 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.episodesElem.style.transition = `0s`;
this.episodesElem.style.top = `${top + 2000}px`;
_.forEach(episodesData, episodeData => {
if (this.episodesElem) {
const episodeContainer = document.createElement('div');
episodeContainer.className = 'episodeContainer';
episodeContainer.style.width = `${CSS_STYLE.episodeWidth}px`;
const episodeThumbURL = `${this.plexProtocol}://${this.config.ip}:${this.config.port}/photo/:/transcode?width=${CSS_STYLE.episodeWidth}&height=${CSS_STYLE.episodeHeight}&minSize=1&upscale=1&url=${episodeData.thumb}&X-Plex-Token=${this.config.token}`;
const episodeElem = document.createElement('div');
episodeElem.className = 'episodeElem';
episodeElem.style.width = `${CSS_STYLE.episodeWidth}px`;
episodeElem.style.height = `${CSS_STYLE.episodeHeight}px`;
episodeElem.style.backgroundImage = `url('${episodeThumbURL}')`;
episodeElem.dataset.clicked = 'false';
if (typeof episodeData.lastViewedAt === 'undefined') {
const toViewElem = document.createElement('div');
toViewElem.className = 'toViewEpisode';
episodeElem.appendChild(toViewElem);
}
if (this.playController && this.playController.isPlaySupported(episodeData)) {
const episodeInteractiveArea = document.createElement('div');
episodeInteractiveArea.className = 'interactiveArea';
const episodePlayButton = document.createElement('button');
episodePlayButton.name = 'playButton';
episodePlayButton.addEventListener('click', episodeEvent => {
episodeEvent.stopPropagation();
if (this.plex && this.playController) {
this.playController.play(episodeData, true);
}
});
episodeInteractiveArea.append(episodePlayButton);
episodeElem.append(episodeInteractiveArea);
}
episodeContainer.append(episodeElem);
const episodeTitleElem = document.createElement('div');
episodeTitleElem.className = 'episodeTitleElem';
episodeTitleElem.innerHTML = escapeHtml(episodeData.title);
episodeContainer.append(episodeTitleElem);
const episodeNumber = document.createElement('div');
episodeNumber.className = 'episodeNumber';
episodeNumber.innerHTML = escapeHtml(`Episode ${escapeHtml(episodeData.index)}`);
episodeContainer.append(episodeNumber);
episodeContainer.addEventListener('click', episodeEvent => {
episodeEvent.stopPropagation();
});
this.episodesElem.append(episodeContainer);
if (this.episodesElem && this.playController) {
this.episodesElem.append(
createEpisodesView(
this.playController,
this.plexProtocol,
this.config.ip,
this.config.port,
this.config.token,
episodeData
)
);
}
});
clearInterval(this.episodesLoadTimeout);
@ -762,7 +721,47 @@ class PlexMeetsHomeAssistant extends HTMLElement {
}
}, 200);
} else {
console.log(await this.plex.getDetails(data.key.split('/')[3]));
const movieDetails = await this.plex.getDetails(data.key.split('/')[3]);
const extras = movieDetails.Extras.Metadata;
this.episodesElemFreshlyLoaded = true;
if (this.episodesElem) {
this.episodesElemHidden = false;
this.episodesElem.style.display = 'block';
this.episodesElem.innerHTML = '';
this.episodesElem.style.transition = `0s`;
this.episodesElem.style.top = `${top + 2000}px`;
_.forEach(extras, extrasData => {
if (this.episodesElem && this.playController) {
this.episodesElem.append(
createEpisodesView(
this.playController,
this.plexProtocol,
this.config.ip,
this.config.port,
this.config.token,
extrasData
)
);
}
});
clearInterval(this.episodesLoadTimeout);
this.episodesLoadTimeout = setTimeout(() => {
if (this.episodesElem) {
this.episodesElem.style.transition = `0.7s`;
this.episodesElem.style.top = `${top + CSS_STYLE.expandedHeight + 16}px`;
this.resizeBackground();
}
}, 200);
clearInterval(this.episodesElemFreshlyLoadedTimeout);
this.episodesElemFreshlyLoadedTimeout = setTimeout(() => {
this.episodesElemFreshlyLoaded = false;
}, 700);
}
}
}
};

Loading…
Cancel
Save